rsalz@uunet.UU.NET (Rich Salz) (09/26/87)
Submitted-by: sun!suneast!kumquat!gmcgary (Greg Mcgary - Sun ECD Software) Posting-number: Volume 11, Issue 80 Archive-name: id/Part03 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # mkid.c # numtst.c # opensrc.c # paths.c # scan-asm.c # scan-c.c # stoi.c # tty.c # uerror.c # wmatch.c export PATH; PATH=/bin:$PATH echo shar: extracting "'mkid.c'" '(17095 characters)' sed 's/^X//' << \SHAR_EOF > 'mkid.c' Xstatic char copyright[] = "@(#)Copyright (c) 1986, Greg McGary"; Xstatic char sccsid[] = "@(#)mkid.c 1.4 86/11/06"; X X#include <bool.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <id.h> X#include <bitops.h> X#include <errno.h> X#include <extern.h> X Xint idnHashCmp(); Xint idnQsortCmp(); Xint round2(); Xstruct idname *newIdName(); Xvoid extractId(); Xvoid fileIdArgs(); Xvoid initHashTable(); Xvoid oldIdArgs(); Xvoid rehash(); Xvoid updateID(); Xvoid writeID(); X Xlong NameCount; /* Count of names in database */ Xlong NumberCount; /* Count of numbers in database */ Xlong StringCount; /* Count of strings in database */ Xlong SoloCount; /* Count of identifiers that occur only once */ X Xlong HashSize; /* Total Slots in hash table */ Xlong HashMaxLoad; /* Maximum loading of hash table */ Xlong HashFill; /* Number of keys inserted in table */ Xlong HashProbes; /* Total number of probes */ Xlong HashSearches; /* Total number of searches */ Xstruct idname **HashTable; /* Vector of idname pointers */ X Xbool Verbose = FALSE; X Xint ArgsCount = 0; /* Count of args to save */ Xint ScanCount = 0; /* Count of files to scan */ Xint PathCount = 0; /* Count of files covered in database */ Xint BitArraySize; /* Size of bit array slice (per name) */ X X Xchar *MyName; Xstatic void Xusage() X{ X fprintf(stderr, "Usage: %s [-f<idfile>] [-s<dir>] [-r<dir>] [(+|-)l[<lang>]] [-v] [(+|-)S<scanarg>] [-a<argfile>] [-] [-u] [files...]\n", MyName); X exit(1); X} Xmain(argc, argv) X int argc; X char **argv; X{ X char *arg; X int op; X FILE *argFILE = NULL; X char *idFile = IDFILE; X char *rcsDir = NULL; X char *sccsDir = NULL; X struct idarg *idArgs, *idArgHead; X bool keepLang = FALSE; X int argsFrom = 0; X#define AF_CMDLINE 0x1 /* file args came on command line */ X#define AF_FILE 0x2 /* file args came from a file (-f<file>) */ X#define AF_IDFILE 0x4 /* file args came from an old ID file (-u) */ X#define AF_QUERY 0x8 /* no file args necessary: usage query */ X X MyName = basename(GETARG(argc, argv)); X#ifdef ERRLINEBUF X setlinebuf(stderr); X#endif X X idArgs = idArgHead = NEW(struct idarg); X X /* X Process some arguments, and snarf-up some X others for processing later. X */ X while (argc) { X arg = GETARG(argc, argv); X if (*arg != '-' && *arg != '+') { X argsFrom |= AF_CMDLINE; X idArgs->ida_arg = arg; X idArgs->ida_flags = IDA_SCAN|IDA_PATH; X idArgs->ida_index = postIncr(&PathCount); X ScanCount++; X idArgs = (idArgs->ida_next = NEW(struct idarg)); X continue; X } X op = *arg++; X switch (*arg++) X { X case 'u': X argsFrom |= AF_IDFILE; X oldIdArgs(idFile, &idArgs); X break; X case '\0': X argsFrom |= AF_FILE; X fileIdArgs(stdin, &idArgs); X break; X case 'a': X if ((argFILE = fopen(arg, "r")) == NULL) { X filerr("open", arg); X exit(1); X } X argsFrom |= AF_FILE; X fileIdArgs(argFILE, &idArgs); X break; X case 'f': X idFile = arg; X break; X case 'v': X Verbose = TRUE; X break; X case 'S': X if (strchr(&arg[-2], '?')) { X setScanArgs(op, arg); X argsFrom |= AF_QUERY; X } X /*FALLTHROUGH*/ X case 'l': X case 's': X case 'r': X idArgs->ida_arg = &arg[-2]; X idArgs->ida_index = -1; X idArgs->ida_flags = IDA_ARG; X idArgs = (idArgs->ida_next = NEW(struct idarg)); X ArgsCount++; X break; X default: X usage(); X } X } X X if (argsFrom & AF_QUERY) X exit(0); X /* X File args should only come from one place. Ding the X user if arguments came from multiple places, or if none X were supplied at all. X */ X switch (argsFrom) X { X case AF_CMDLINE: X case AF_FILE: X case AF_IDFILE: X if (PathCount > 0) X break; X /*FALLTHROUGH*/ X case 0: X fprintf(stderr, "%s: Use -u, -f<file>, or cmd-line for file args!\n", MyName); X usage(); X default: X fprintf(stderr, "%s: Use only one of: -u, -f<file>, or cmd-line for file args!\n", MyName); X usage(); X } X X if (ScanCount == 0) X exit(0); X X BitArraySize = (PathCount + 7) >> 3; X initHashTable(ScanCount); X X if (access(idFile, 06) < 0 X && (errno != ENOENT || access(dirname(idFile), 06) < 0)) { X filerr("modify", idFile); X exit(1); X } X X for (idArgs = idArgHead; idArgs->ida_next; idArgs = idArgs->ida_next) { X char *(*scanner)(); X FILE *srcFILE; X char *arg, *lang, *suff; X X arg = idArgs->ida_arg; X if (idArgs->ida_flags & IDA_ARG) { X op = *arg++; X switch (*arg++) X { X case 'l': X if (*arg == '\0') { X keepLang = FALSE; X lang = NULL; X break; X } X if (op == '+') X keepLang = TRUE; X lang = arg; X break; X case 's': X sccsDir = arg; X break; X case 'r': X rcsDir = arg; X break; X case 'S': X setScanArgs(op, strsav(arg)); X break; X default: X usage(); X } X continue; X } X if (!(idArgs->ida_flags & IDA_SCAN)) X goto skip; X if (lang == NULL) { X if ((suff = strrchr(arg, '.')) == NULL) X suff = ""; X if ((lang = getLanguage(suff)) == NULL) { X fprintf(stderr, "%s: No language assigned to suffix: `%s'\n", MyName, suff); X goto skip; X } X } X if ((scanner = getScanner(lang)) == NULL) { X fprintf(stderr, "%s: No scanner for language: `%s'\n", MyName, lang); X goto skip; X } X if ((srcFILE = openSrcFILE(arg, sccsDir, rcsDir)) == NULL) X goto skip; X if (Verbose) X fprintf(stderr, "%s: %s\n", lang, arg); X extractId(scanner, srcFILE, idArgs->ida_index); X fclose(srcFILE); X skip: X if (!keepLang) X lang = NULL; X } X X if (HashFill == 0) X exit(0); X X if (Verbose) X fprintf(stderr, "Compressing Hash Table...\n"); X hashCompress(HashTable, HashSize); X if (Verbose) X fprintf(stderr, "Sorting Hash Table...\n"); X qsort(HashTable, HashFill, sizeof(struct idname *), idnQsortCmp); X X if (argsFrom == AF_IDFILE) { X if (Verbose) X fprintf(stderr, "Merging Tables...\n"); X updateID(idFile, idArgHead); X } X X if (Verbose) X fprintf(stderr, "Writing `%s'...\n", idFile); X writeID(idFile, idArgHead); X X if (Verbose) { X float loadFactor = (float)HashFill / (float)HashSize; X float aveProbes = (float)HashProbes / (float)HashSearches; X float aveOccur = (float)HashSearches / (float)HashFill; X fprintf(stderr, "Names: %ld, ", NameCount); X fprintf(stderr, "Numbers: %ld, ", NumberCount); X fprintf(stderr, "Strings: %ld, ", StringCount); X fprintf(stderr, "Solo: %ld, ", SoloCount); X fprintf(stderr, "Total: %ld\n", HashFill); X fprintf(stderr, "Occurances: %.2f, ", aveOccur); X fprintf(stderr, "Load: %.2f, ", loadFactor); X fprintf(stderr, "Probes: %.2f\n", aveProbes); X } X exit(0); X} X Xvoid XextractId(getId, srcFILE, index) X register char *(*getId)(); X register FILE *srcFILE; X int index; X{ X register struct idname **slot; X register char *key; X int flags; X X while ((key = (*getId)(srcFILE, &flags)) != NULL) { X slot = (struct idname **)hashSearch(key, HashTable, HashSize, sizeof(struct idname *), h1str, h2str, idnHashCmp, &HashProbes); X HashSearches++; X if (*slot != NULL) { X (*slot)->idn_flags |= flags; X BITSET((*slot)->idn_bitv, index); X continue; X } X *slot = newIdName(key); X (*slot)->idn_flags = IDN_SOLO|flags; X BITSET((*slot)->idn_bitv, index); X if (HashFill++ >= HashMaxLoad) X rehash(); X } X} X Xvoid XwriteID(idFile, idArgs) X char *idFile; X struct idarg *idArgs; X{ X register struct idname **idnp; X register struct idname *idn; X register int i; X char *vecBuf; X FILE *idFILE; X int count; X int lasti; X long before, after; X int length, longest; X struct idhead idh; X X if ((idFILE = fopen(idFile, "w+")) == NULL) { X filerr("create", idFile); X exit(1); X } X fseek(idFILE, (long)sizeof(struct idhead), 0); X X /* write out the list of pathnames */ X idh.idh_argo = ftell(idFILE); X for (i = lasti = 0; idArgs->ida_next; idArgs = idArgs->ida_next) { X if (idArgs->ida_index > 0) X while (++lasti < idArgs->ida_index) X i++, putc('\0', idFILE); X fputs(idArgs->ida_arg, idFILE); X i++, putc('\0', idFILE); X } X idh.idh_argc = i; X idh.idh_pthc = PathCount; X X /* write out the list of identifiers */ X i = 1; X if (idh.idh_pthc >= 0x000000ff) X i++; X if (idh.idh_pthc >= 0x0000ffff) X i++; X if (idh.idh_pthc >= 0x00ffffff) X i++; X idh.idh_vecc = i; X X vecBuf = malloc((idh.idh_pthc + 1) * idh.idh_vecc); X X putc('\377', idFILE); X before = idh.idh_namo = ftell(idFILE); X longest = 0; X for (idnp = HashTable, i = 0; i < HashFill; i++, idnp++) { X idn = *idnp; X if (idn->idn_name[0] == '\0') { X HashFill--; i--; X continue; X } X if (idn->idn_flags & IDN_SOLO) X SoloCount++; X if (idn->idn_flags & IDN_NUMBER) X NumberCount++; X if (idn->idn_flags & IDN_NAME) X NameCount++; X if (idn->idn_flags & IDN_STRING) X StringCount++; X X putc((*idnp)->idn_flags, idFILE); X fputs(idn->idn_name, idFILE); X putc('\0', idFILE); X X count = bitsToVec(vecBuf, (*idnp)->idn_bitv, idh.idh_pthc, idh.idh_vecc); X fwrite(vecBuf, idh.idh_vecc, count, idFILE); X putc('\377', idFILE); X after = ftell(idFILE); X X if ((length = (after - before)) > longest) X longest = length; X before = after; X } X idh.idh_namc = i; X putc('\377', idFILE); X idh.idh_endo = ftell(idFILE); X idh.idh_bsiz = longest; X X /* write out the header */ X strncpy(idh.idh_magic, IDH_MAGIC, sizeof(idh.idh_magic)); X idh.idh_vers = IDH_VERS; X fseek(idFILE, 0L, 0); X fwrite(&idh, sizeof(struct idhead), 1, idFILE); X X fclose(idFILE); X} X X/* X Build an idarg vector from pathnames contained in an existing X id file. Only include pathnames for files whose modification X time is later than that of the id file itself. X*/ Xvoid XoldIdArgs(idFile, idArgsP) X char *idFile; X struct idarg **idArgsP; X{ X struct stat statBuf; X struct idhead idh; X FILE *idFILE; X register int i; X register char *strings; X time_t idModTime; X X if ((idFILE = fopen(idFile, "r")) == NULL) { X filerr("open", idFile); X usage(); X } X /* X * Open the id file, get its mod-time, and read its header. X */ X if (fstat(fileno(idFILE), &statBuf) < 0) { X filerr("stat", idFile); X usage(); X } X idModTime = statBuf.st_mtime; X fread(&idh, sizeof(struct idhead), 1, idFILE); X if (!strnequ(idh.idh_magic, IDH_MAGIC, sizeof(idh.idh_magic))) { X fprintf(stderr, "%s: Not an id file: `%s'\n", MyName, idFile); X exit(1); X } X if (idh.idh_vers != IDH_VERS) { X fprintf(stderr, "%s: ID version mismatch (%ld,%ld)\n", MyName, idh.idh_vers, IDH_VERS); X exit(1); X } X X /* X * Read in the id pathnames, compare their mod-times with X * the id file, and incorporate the pathnames of recently modified X * files in the idarg vector. Also, construct a mask of X * bit array positions we want to turn off when we build the X * initial hash-table. X */ X fseek(idFILE, idh.idh_argo, 0); X strings = malloc(i = idh.idh_namo - idh.idh_argo); X fread(strings, i, 1, idFILE); X ScanCount = 0; X for (i = 0; i < idh.idh_argc; i++) { X (*idArgsP)->ida_arg = strings; X if (*strings == '+' || *strings == '-') { X (*idArgsP)->ida_flags = IDA_ARG; X (*idArgsP)->ida_index = -1; X } else { X (*idArgsP)->ida_flags = IDA_PATH; X (*idArgsP)->ida_index = postIncr(&PathCount); X if (stat(strings, &statBuf) < 0) { X filerr("stat", strings); X } else if (statBuf.st_mtime >= idModTime) { X (*idArgsP)->ida_flags |= IDA_SCAN; X ScanCount++; X } X } X (*idArgsP) = ((*idArgsP)->ida_next = NEW(struct idarg)); X while (*strings++) X ; X } X if (ScanCount == 0) { X fclose(idFILE); X exit(0); X } X fclose(idFILE); X} X Xvoid XupdateID(idFile, idArgs) X char *idFile; X struct idarg *idArgs; X{ X struct idname *idn; X struct idhead idh; X register char *bitArray; X char *entry; X register int i; X FILE *idFILE; X int cmp, count, size; X char *bitsOff; X struct idname **newTable, **mergeTable; X struct idname **t1, **t2, **tm; X X if ((idFILE = fopen(idFile, "r")) == NULL) X filerr("open", idFile); X fread(&idh, sizeof(struct idhead), 1, idFILE); X X entry = malloc(idh.idh_bsiz); X X bitsOff = malloc(BitArraySize); X bzero(bitsOff, BitArraySize); X for (i = 0; idArgs->ida_next; idArgs = idArgs->ida_next) X if (idArgs->ida_flags & IDA_SCAN) X BITSET(bitsOff, idArgs->ida_index); X X bitArray = malloc(BitArraySize); X bzero(bitArray, BitArraySize); X t2 = newTable = (struct idname **)malloc((idh.idh_namc + 1) * sizeof(struct idname *)); X fseek(idFILE, idh.idh_namo, 0); X count = 0; X for (i = 0; i < idh.idh_namc; i++) { X size = 1 + fgets0(entry, idh.idh_bsiz, idFILE); X getsFF(&entry[size], idFILE); X vecToBits(bitArray, &entry[size], idh.idh_vecc); X bitsclr(bitArray, bitsOff, BitArraySize); X if (!bitsany(bitArray, BitArraySize)) X continue; X *t2 = newIdName(ID_STRING(entry)); X bitsset((*t2)->idn_bitv, bitArray, BitArraySize); X (*t2)->idn_flags = ID_FLAGS(entry); X bzero(bitArray, BitArraySize); X t2++; count++; X } X *t2 = NULL; X X t1 = HashTable; X t2 = newTable; X tm = mergeTable = (struct idname **)calloc(HashFill + count + 1, sizeof(struct idname *)); X while (*t1 && *t2) { X cmp = strcmp((*t1)->idn_name, (*t2)->idn_name); X if (cmp < 0) X *tm++ = *t1++; X else if (cmp > 0) X *tm++ = *t2++; X else { X (*t1)->idn_flags |= (*t2)->idn_flags; X (*t1)->idn_flags &= ~IDN_SOLO; X bitsset((*t1)->idn_bitv, (*t2)->idn_bitv, BitArraySize); X *tm++ = *t1; X t1++, t2++; X } X } X while (*t1) X *tm++ = *t1++; X while (*t2) X *tm++ = *t2++; X *tm = NULL; X HashTable = mergeTable; X HashFill = tm - mergeTable; X} X X/* X Cons up a list of idArgs as supplied in a file. X*/ Xvoid XfileIdArgs(argFILE, idArgsP) X FILE *argFILE; X struct idarg **idArgsP; X{ X int fileCount; X char buf[BUFSIZ]; X char *arg; X X fileCount = 0; X while (fgets(buf, sizeof(buf), argFILE)) { X (*idArgsP)->ida_arg = arg = strnsav(buf, strlen(buf)-1); X if (*arg == '+' || *arg == '-') { X (*idArgsP)->ida_flags = IDA_ARG; X (*idArgsP)->ida_index = -1; X } else { X (*idArgsP)->ida_flags = IDA_SCAN|IDA_PATH; X (*idArgsP)->ida_index = postIncr(&PathCount); X ScanCount++; X } X (*idArgsP) = ((*idArgsP)->ida_next = NEW(struct idarg)); X } X} X Xvoid XinitHashTable(pathCount) X int pathCount; X{ X if ((HashSize = round2((pathCount << 6) + 511)) > 0x8000) X HashSize = 0x8000; X HashMaxLoad = HashSize - (HashSize >> 4); /* about 94% */ X HashTable = (struct idname **)calloc(HashSize, sizeof(struct idname *)); X} X X/* X Double the size of the hash table in the X event of overflow... X*/ Xvoid Xrehash() X{ X long oldHashSize = HashSize; X struct idname **oldHashTable = HashTable; X register struct idname **htp; X register struct idname **slot; X X HashSize *= 2; X if (Verbose) X fprintf(stderr, "Rehashing... (doubling size to %ld)\n", HashSize); X HashMaxLoad = HashSize - (HashSize >> 4); X HashTable = (struct idname **)calloc(HashSize, sizeof(struct idname *)); X X HashFill = 0; X for (htp = oldHashTable; htp < &oldHashTable[oldHashSize]; htp++) { X if (*htp == NULL) X continue; X slot = (struct idname **)hashSearch((*htp)->idn_name, (char *)HashTable, HashSize, sizeof(struct idname *), h1str, h2str, idnHashCmp, &HashProbes); X if (*slot) { X fprintf(stderr, "%s: Duplicate hash entry!\n"); X exit(1); X } X *slot = *htp; X HashSearches++; X HashFill++; X } X free(oldHashTable); X} X X/* X Round a given number up to the nearest power of 2. X*/ Xint Xround2(rough) X int rough; X{ X int round; X X round = 1; X while (rough) { X round <<= 1; X rough >>= 1; X } X return round; X} X X/* X `compar' function for hashSearch() X*/ Xint XidnHashCmp(key, idn) X char *key; X struct idname **idn; X{ X int collate; X X if (*idn == NULL) X return 0; X X if ((collate = strcmp(key, (*idn)->idn_name)) == 0) X (*idn)->idn_flags &= ~IDN_SOLO; /* we found another occurance */ X X return collate; X} X X/* X `compar' function for qsort(). X*/ Xint XidnQsortCmp(idn1, idn2) X struct idname **idn1; X struct idname **idn2; X{ X if (*idn1 == *idn2) X return 0; X if (*idn1 == NULL) X return 1; X if (*idn2 == NULL) X return -1; X X return strcmp((*idn1)->idn_name, (*idn2)->idn_name); X} X X/* X Allocate a new idname struct and fill in the name field. X We allocate memory in large chunks to avoid frequent X calls to malloc() which is a major pig. X*/ Xstruct idname * XnewIdName(name) X char *name; X{ X register struct idname *idn; X register char *allocp; X register int allocsiz; X static char *allocBuf = NULL; X static char *allocEnd = NULL; X#define ALLOCSIZ (8*1024) X X allocsiz = sizeof(struct idname) + strlen(name) + 1 + BitArraySize; X allocsiz += (sizeof(long) - 1); X allocsiz &= ~(sizeof(long) - 1); X X allocp = allocBuf; X allocBuf += allocsiz; X if (allocBuf > allocEnd) { X allocBuf = malloc(ALLOCSIZ); X allocEnd = &allocBuf[ALLOCSIZ]; X allocp = allocBuf; X allocBuf += allocsiz; X } X X idn = (struct idname *)allocp; X allocp += sizeof(struct idname); X idn->idn_bitv = allocp; X for (allocsiz = BitArraySize; allocsiz--; allocp++) X *allocp = '\0'; X idn->idn_name = strcpy(allocp, name); X X return idn; X} X Xint XpostIncr(ip) X int *ip; X{ X register int i; X int save; X X save = *ip; X i = save + 1; X if ((i & 0x00ff) == 0x00ff) X i++; X if ((i & 0xff00) == 0xff00) /* This isn't bloody likely */ X i += 0x100; X *ip = i; X X return save; X} X X/* X Move all non-NULL table entries to the front of the table. X return the number of non-NULL elements in the table. X*/ Xint XhashCompress(table, size) X char **table; X int size; X{ X register char **front; X register char **back; X X front = &table[-1]; X back = &table[size]; X X for (;;) { X while (*--back == NULL) X ; X if (back < front) X break; X while (*++front != NULL) X ; X if (back < front) X break; X *front = *back; X } X X return (back - table + 1); X} SHAR_EOF if test 17095 -ne "`wc -c < 'mkid.c'`" then echo shar: error transmitting "'mkid.c'" '(should have been 17095 characters)' fi echo shar: extracting "'numtst.c'" '(60 characters)' sed 's/^X//' << \SHAR_EOF > 'numtst.c' X000004 X00010 X012 X020 X04 X0x00004 X0x00010 X0x00a X0XA X10 X16 X4 X8 SHAR_EOF if test 60 -ne "`wc -c < 'numtst.c'`" then echo shar: error transmitting "'numtst.c'" '(should have been 60 characters)' fi echo shar: extracting "'opensrc.c'" '(2172 characters)' sed 's/^X//' << \SHAR_EOF > 'opensrc.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)opensrc.c 1.1 86/10/09"; X X#include <stdio.h> X#include <string.h> X#include <sys/types.h> X#include <sys/stat.h> X XFILE *openSrcFILE(); Xchar *getSCCS(); Xchar *coRCS(); X XFILE * XopenSrcFILE(path, sccsDir, rcsDir) X char *path; X char *sccsDir; X char *rcsDir; X{ X char *command = NULL; X char *what = NULL; X char *get = "get SCCS file"; X char *checkout = "checkout RCS file"; X char *dirName; X char *baseName; X FILE *srcFILE; X X if ((srcFILE = fopen(path, "r")) != NULL) X return srcFILE; X X if ((baseName = strrchr(path, '/')) == NULL) { X dirName = "."; X baseName = path; X } else { X dirName = path; X *baseName++ = '\0'; X } X X if (rcsDir && (command = coRCS(dirName, baseName, rcsDir))) X what = checkout; X else if (sccsDir && (command = getSCCS(dirName, baseName, sccsDir))) X what = get; X else if ((command = coRCS(dirName, baseName, "RCS")) X || (command = coRCS(dirName, baseName, "."))) X what = checkout; X else if ((command = getSCCS(dirName, baseName, "SCCS")) X || (command = getSCCS(dirName, baseName, "sccs")) X || (command = getSCCS(dirName, baseName, "."))) X what = get; X X if (dirName == path) X *--baseName = '/'; X X if (!command) { X filerr("open", path); X return NULL; X } X X system(command); X if ((srcFILE = fopen(path, "r")) == NULL) { X filerr("open", path); X return NULL; X } X X fprintf(stderr, "%s\n", command); X return srcFILE; X} X Xchar * XgetSCCS(dir, base, sccsDir) X char *dir; X char *base; X char *sccsDir; X{ X static char cmdBuf[BUFSIZ]; X char fileBuf[BUFSIZ]; X struct stat statBuf; X X if (!*sccsDir) X sccsDir = "."; X X sprintf(fileBuf, "%s/%s/s.%s", dir, sccsDir, base); X if (stat(fileBuf, &statBuf) < 0) X return NULL; X sprintf(cmdBuf, "cd %s; get -s %s/s.%s", dir, sccsDir, base); X X return cmdBuf; X} X Xchar * XcoRCS(dir, base, rcsDir) X char *dir; X char *base; X char *rcsDir; X{ X static char cmdBuf[BUFSIZ]; X char fileBuf[BUFSIZ]; X struct stat statBuf; X X if (!*rcsDir) X rcsDir = "."; X X sprintf(fileBuf, "%s/%s/%s,v", dir, rcsDir, base); X if (stat(fileBuf, &statBuf) < 0) X return NULL; X sprintf(cmdBuf, "cd %s; co -q %s/%s,v", dir, rcsDir, base); X X return cmdBuf; X} SHAR_EOF if test 2172 -ne "`wc -c < 'opensrc.c'`" then echo shar: error transmitting "'opensrc.c'" '(should have been 2172 characters)' fi echo shar: extracting "'paths.c'" '(3629 characters)' sed 's/^X//' << \SHAR_EOF > 'paths.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)paths.c 1.1 86/10/09"; X X#include <bool.h> X#include <stdio.h> X#include <string.h> X Xbool canCrunch(); Xchar *getDirToName(); Xchar *rootName(); Xchar *skipJunk(); Xchar *spanPath(); Xchar *suffName(); X Xchar * XspanPath(dir, arg) X char *dir; X char *arg; X{ X static char pathBuf[BUFSIZ]; X char *path; X char *argTail; X char *dirTail; X int argLength; X int dirLength; X X for (dirTail = &dir[strlen(dir)-1]; *dirTail == '/'; dirTail--) X *dirTail = '\0'; X for (;;) { X dir = skipJunk(dir); X if ((dirTail = strchr(dir, '/')) == NULL) X dirTail = &dir[strlen(dir)]; X dirLength = dirTail - dir; X X arg = skipJunk(arg); X if ((argTail = strchr(arg, '/')) == NULL) X break; X argLength = argTail - arg; X X if (argLength != dirLength) X break; X if (!strnequ(arg, dir, argLength)) X break; X arg = argTail; X dir = dirTail; X } X X (path = pathBuf)[0] = '\0'; X for (; dir && *dir; dir = skipJunk(strchr(dir, '/'))) { X strcpy(path, "../"); X path += 3; X } X strcat(path, arg); X return pathBuf; X} X Xchar * XskipJunk(path) X char *path; X{ X if (path == NULL) X return NULL; X while (*path == '/') X path++; X while (path[0] == '.' && path[1] == '/') { X path += 2; X while (*path == '/') X path++; X } X if (strequ(path, ".")) X path++; X X return path; X} X Xchar * XrootName(path) X char *path; X{ X static char pathBuf[BUFSIZ]; X char *root; X char *dot; X X if ((root = strrchr(path, '/')) == NULL) X root = path; X else X root++; X X if ((dot = strrchr(root, '.')) == NULL) X strcpy(pathBuf, root); X else { X strncpy(pathBuf, root, dot - root); X pathBuf[dot - root] = '\0'; X } X return pathBuf; X} X Xchar * XsuffName(path) X char *path; X{ X char *dot; X X if ((dot = strrchr(path, '.')) == NULL) X return ""; X return dot; X} X Xbool XcanCrunch(path1, path2) X char *path1; X char *path2; X{ X char *slash1; X char *slash2; X X slash1 = strrchr(path1, '/'); X slash2 = strrchr(path2, '/'); X X if (slash1 == NULL && slash2 == NULL) X return strequ(suffName(path1), suffName(path2)); X if ((slash1 - path1) != (slash2 - path2)) X return FALSE; X if (!strnequ(path1, path2, slash1 - path1)) X return FALSE; X return strequ(suffName(slash1), suffName(slash2)); X} X#include <sys/types.h> X#include <sys/stat.h> X#ifdef NDIR X#include <ndir.h> X#else X#include <sys/dir.h> X#endif X Xstatic char dot[] = "."; Xstatic char dotdot[] = ".."; X X/* X Return our directory name relative to the first parent dir X that contains a file with a name that matches `topName'. X Fail if we hit the root, or if any dir in our way is unreadable. X*/ Xchar * XgetDirToName(topName) X char *topName; X{ X register struct direct *dirp; X register DIR *dirdp; X static char nameBuf[BUFSIZ]; X char *name; X struct stat dStat; X struct stat ddStat; X X name = &nameBuf[sizeof(nameBuf)-1]; X *name = '\0'; X for (;;) { X if (stat(topName, &dStat) == 0) { X if (!*name) X name = dot; X else X chdir(name); X return name; X } if (stat(dot, &dStat) < 0) X return NULL; X if ((dirdp = opendir(dotdot)) == NULL) X return NULL; X if (fstat(dirdp->dd_fd, &ddStat) < 0) X return NULL; X if (chdir(dotdot) < 0) X return NULL; X if (dStat.st_dev == ddStat.st_dev) { X if (dStat.st_ino == ddStat.st_ino) X return NULL; X do { X if ((dirp = readdir(dirdp)) == NULL) X return NULL; X } while (dirp->d_ino != dStat.st_ino); X } else { X do { X if ((dirp = readdir(dirdp)) == NULL) X return NULL; X stat(dirp->d_name, &ddStat); X } while (ddStat.st_ino != dStat.st_ino || ddStat.st_dev != dStat.st_dev); X } X closedir(dirdp); X X if (*name != '\0') X *--name = '/'; X name -= dirp->d_namlen; X strncpy(name, dirp->d_name, dirp->d_namlen); X } X} SHAR_EOF if test 3629 -ne "`wc -c < 'paths.c'`" then echo shar: error transmitting "'paths.c'" '(should have been 3629 characters)' fi echo shar: extracting "'scan-asm.c'" '(6157 characters)' sed 's/^X//' << \SHAR_EOF > 'scan-asm.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)scan-asm.c 1.2 86/11/06"; X X#include <bool.h> X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <id.h> X Xchar *getAsmId(); Xvoid setAsmArgs(); X Xstatic void clrCtype(); Xstatic void setCtype(); X X#define I1 0x01 /* 1st char of an identifier [a-zA-Z_] */ X#define NM 0x02 /* digit [0-9a-fA-FxX] */ X#define NL 0x04 /* newline: \n */ X#define CM 0x08 /* assembler comment char: usually # or | */ X#define IG 0x10 /* ignore `identifiers' with these chars in them */ X#define C1 0x20 /* C comment introduction char: / */ X#define C2 0x40 /* C comment termination char: * */ X#define EF 0x80 /* EOF */ X X/* Assembly Language character classes */ X#define ISID1ST(c) ((rct)[c]&(I1)) X#define ISIDREST(c) ((rct)[c]&(I1|NM)) X#define ISNUMBER(c) ((rct)[c]&(NM)) X#define ISEOF(c) ((rct)[c]&(EF)) X#define ISCOMMENT(c) ((rct)[c]&(CM)) X#define ISBORING(c) (!((rct)[c]&(EF|NL|I1|NM|CM|C1))) X#define ISCBORING(c) (!((rct)[c]&(EF|NL))) X#define ISCCBORING(c) (!((rct)[c]&(EF|C2))) X#define ISIGNORE(c) ((rct)[c]&(IG)) X Xstatic char idctype[] = { X X EF, X X /* 0 1 2 3 4 5 6 7 */ X /* ----- ----- ----- ----- ----- ----- ----- ----- */ X X /*000*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*010*/ 0, 0, NL, 0, 0, 0, 0, 0, X /*020*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*030*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*040*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*050*/ 0, 0, C2, 0, 0, 0, 0, C1, X /*060*/ NM, NM, NM, NM, NM, NM, NM, NM, X /*070*/ NM, NM, 0, 0, 0, 0, 0, 0, X /*100*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1, X /*110*/ I1, I1, I1, I1, I1|NM, I1, I1, I1, X /*120*/ I1, I1, I1, I1, I1, I1, I1, I1, X /*130*/ I1|NM, I1, I1, 0, 0, 0, 0, I1, X /*140*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1, X /*150*/ I1, I1, I1, I1, I1|NM, I1, I1, I1, X /*160*/ I1, I1, I1, I1, I1, I1, I1, I1, X /*170*/ I1|NM, I1, I1, 0, 0, 0, 0, 0, X X /*200*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*210*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*220*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*230*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*240*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*250*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*260*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*270*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*300*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*310*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*320*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*330*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*340*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*350*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*360*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*370*/ 0, 0, 0, 0, 0, 0, 0, 0, X X}; X Xstatic bool eatUnder = TRUE; Xstatic bool preProcess = TRUE; X X/* X Grab the next identifier the assembly language X source file opened with the handle `inFILE'. X This state machine is built for speed, not elegance. X*/ Xchar * XgetAsmId(inFILE, flagP) X FILE *inFILE; X int *flagP; X{ X static char idBuf[BUFSIZ]; X register char *rct = &idctype[1]; X register int c; X register char *id = idBuf; X static bool newLine = TRUE; X Xtop: X c = getc(inFILE); X if (preProcess > 0 && newLine) { X newLine = FALSE; X if (c != '#') X goto next; X while (ISBORING(c)) X c = getc(inFILE); X if (!ISID1ST(c)) X goto next; X id = idBuf; X *id++ = c; X while (ISIDREST(c = getc(inFILE))) X *id++ = c; X *id = '\0'; X if (strequ(idBuf, "include")) { X while (c != '"' && c != '<') X c = getc(inFILE); X id = idBuf; X *id++ = c = getc(inFILE); X while ((c = getc(inFILE)) != '"' && c != '>') X *id++ = c; X *id = '\0'; X *flagP = IDN_STRING; X return idBuf; X } X if (strnequ(idBuf, "if", 2) X || strequ(idBuf, "define") X || strequ(idBuf, "undef")) X goto next; X while (c != '\n') X c = getc(inFILE); X newLine = TRUE; X goto top; X } X Xnext: X while (ISBORING(c)) X c = getc(inFILE); X X if (ISCOMMENT(c)) { X while (ISCBORING(c)) X c = getc(inFILE); X newLine = TRUE; X } X X if (ISEOF(c)) { X newLine = TRUE; X return NULL; X } X X if (c == '\n') { X newLine = TRUE; X goto top; X } X X if (c == '/') { X if ((c = getc(inFILE)) != '*') X goto next; X c = getc(inFILE); X for (;;) { X while (ISCCBORING(c)) X c = getc(inFILE); X if ((c = getc(inFILE)) == '/') { X c = getc(inFILE); X break; X } else if (ISEOF(c)) { X newLine = TRUE; X return NULL; X } X } X goto next; X } X X id = idBuf; X if (eatUnder && c == '_' && !ISID1ST(c = getc(inFILE))) { X ungetc(c, inFILE); X return "_"; X } X *id++ = c; X if (ISID1ST(c)) { X *flagP = IDN_NAME; X while (ISIDREST(c = getc(inFILE))) X *id++ = c; X } else if (ISNUMBER(c)) { X *flagP = IDN_NUMBER; X while (ISNUMBER(c = getc(inFILE))) X *id++ = c; X } else { X if (isprint(c)) X fprintf(stderr, "junk: `%c'", c); X else X fprintf(stderr, "junk: `\\%03o'", c); X goto next; X } X X *id = '\0'; X for (id = idBuf; *id; id++) X if (ISIGNORE(*id)) X goto next; X ungetc(c, inFILE); X *flagP |= IDN_LITERAL; X return idBuf; X} X Xstatic void XsetCtype(chars, type) X char *chars; X int type; X{ X char *rct = &idctype[1]; X X while (*chars) X rct[*chars++] |= type; X} Xstatic void XclrCtype(chars, type) X char *chars; X int type; X{ X char *rct = &idctype[1]; X X while (*chars) X rct[*chars++] &= ~type; X} X Xextern char *MyName; Xstatic void Xusage(lang) X char *lang; X{ X fprintf(stderr, "Usage: %s -S%s([-c<cc>] [-u] [(+|-)a<cc>] [(+|-)p] [(+|-)C])\n", MyName, lang); X exit(1); X} Xstatic char *asmDocument[] = X{ X"The Assembler scanner arguments take the form -Sasm<arg>, where", X"<arg> is one of the following: (<cc> denotes one or more characters)", X" -c<cc> . . . . <cc> introduce(s) a comment until end-of-line.", X" (+|-)u . . . . (Do|Don't) strip a leading `_' from ids.", X" (+|-)a<cc> . . Allow <cc> in ids, and (keep|ignore) those ids.", X" (+|-)p . . . . (Do|Don't) handle C-preprocessor directives.", X" (+|-)C . . . . (Do|Don't) handle C-style comments. (/* */)", XNULL X}; Xvoid XsetAsmArgs(lang, op, arg) X char *lang; X int op; X char *arg; X{ X if (op == '?') { X document(asmDocument); X return; X } X switch (*arg++) X { X case 'a': X setCtype(arg, I1|((op == '-') ? IG : 0)); X break; X case 'c': X setCtype(arg, CM); X break; X case 'u': X eatUnder = (op == '+'); X break; X case 'p': X preProcess = (op == '+'); X break; X case 'C': X if (op == '+') { X setCtype("/", C1); X setCtype("*", C2); X } else { X clrCtype("/", C1); X clrCtype("*", C2); X } X break; X default: X if (lang) X usage(lang); X break; X } X} SHAR_EOF if test 6157 -ne "`wc -c < 'scan-asm.c'`" then echo shar: error transmitting "'scan-asm.c'" '(should have been 6157 characters)' fi echo shar: extracting "'scan-c.c'" '(6502 characters)' sed 's/^X//' << \SHAR_EOF > 'scan-c.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)scan-c.c 1.1 86/10/09"; X X#include <bool.h> X#include <stdio.h> X#include <string.h> X#include <id.h> X Xchar *getCId(); Xvoid setCArgs(); X Xstatic void clrCtype(); Xstatic void setCtype(); X X#define I1 0x0001 /* 1st char of an identifier [a-zA-Z_] */ X#define DG 0x0002 /* decimal digit [0-9] */ X#define NM 0x0004 /* extra chars in a hex or long number [a-fA-FxXlL] */ X#define C1 0x0008 /* C comment introduction char: / */ X#define C2 0x0010 /* C comment termination char: * */ X#define Q1 0x0020 /* single quote: ' */ X#define Q2 0x0040 /* double quote: " */ X#define ES 0x0080 /* escape char: \ */ X#define NL 0x0100 /* newline: \n */ X#define EF 0x0200 /* EOF */ X#define SK 0x0400 /* Make these chars valid for names within strings */ X X/* X character class membership macros: X*/ X#define ISDIGIT(c) ((rct)[c]&(DG)) /* digit */ X#define ISNUMBER(c) ((rct)[c]&(DG|NM)) /* legal in a number */ X#define ISEOF(c) ((rct)[c]&(EF)) /* EOF */ X#define ISID1ST(c) ((rct)[c]&(I1)) /* 1st char of an identifier */ X#define ISIDREST(c) ((rct)[c]&(I1|DG)) /* rest of an identifier */ X#define ISSTRKEEP(c) ((rct)[c]&(I1|DG|SK)) /* keep contents of string */ X/* X The `BORING' classes should be skipped over X until something interesting comes along... X*/ X#define ISBORING(c) (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1))) /* fluff */ X#define ISCBORING(c) (!((rct)[c]&(EF|C2))) /* comment fluff */ X#define ISQ1BORING(c) (!((rct)[c]&(EF|NL|Q1|ES))) /* char const fluff */ X#define ISQ2BORING(c) (!((rct)[c]&(EF|NL|Q2|ES))) /* quoted str fluff */ X Xstatic short idctype[] = { X X EF, X X /* 0 1 2 3 4 5 6 7 */ X /* ----- ----- ----- ----- ----- ----- ----- ----- */ X X /*000*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*010*/ 0, 0, NL, 0, 0, 0, 0, 0, X /*020*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*030*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*040*/ 0, 0, Q2, 0, 0, 0, 0, Q1, X /*050*/ 0, 0, C2, 0, 0, 0, 0, C1, X /*060*/ DG, DG, DG, DG, DG, DG, DG, DG, X /*070*/ DG, DG, 0, 0, 0, 0, 0, 0, X /*100*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1, X /*110*/ I1, I1, I1, I1, I1|NM, I1, I1, I1, X /*120*/ I1, I1, I1, I1, I1, I1, I1, I1, X /*130*/ I1|NM, I1, I1, 0, ES, 0, 0, I1, X /*140*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1, X /*150*/ I1, I1, I1, I1, I1|NM, I1, I1, I1, X /*160*/ I1, I1, I1, I1, I1, I1, I1, I1, X /*170*/ I1|NM, I1, I1, 0, 0, 0, 0, 0, X X /*200*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*210*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*220*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*230*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*240*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*250*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*260*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*270*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*300*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*310*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*320*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*330*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*340*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*350*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*360*/ 0, 0, 0, 0, 0, 0, 0, 0, X /*370*/ 0, 0, 0, 0, 0, 0, 0, 0, X X}; X Xstatic bool eatUnder = TRUE; X X/* X Grab the next identifier the C source X file opened with the handle `inFILE'. X This state machine is built for speed, not elegance. X*/ Xchar * XgetCId(inFILE, flagP) X FILE *inFILE; X int *flagP; X{ X static char idBuf[BUFSIZ]; X static bool newLine = TRUE; X register short *rct = &idctype[1]; X register int c; X register char *id = idBuf; X Xtop: X c = getc(inFILE); X if (newLine) { X newLine = FALSE; X if (c != '#') X goto next; X while (ISBORING(c)) X c = getc(inFILE); X if (!ISID1ST(c)) X goto next; X id = idBuf; X *id++ = c; X while (ISIDREST(c = getc(inFILE))) X *id++ = c; X *id = '\0'; X if (strequ(idBuf, "include")) { X while (c != '"' && c != '<') X c = getc(inFILE); X id = idBuf; X *id++ = c = getc(inFILE); X while ((c = getc(inFILE)) != '"' && c != '>') X *id++ = c; X *id = '\0'; X *flagP = IDN_STRING; X return idBuf; X } X if (strnequ(idBuf, "if", 2) X || strequ(idBuf, "define") X || strequ(idBuf, "undef")) X goto next; X while (c != '\n') X c = getc(inFILE); X newLine = TRUE; X goto top; X } X Xnext: X while (ISBORING(c)) X c = getc(inFILE); X X switch (c) X { X case '"': X id = idBuf; X *id++ = c = getc(inFILE); X for (;;) { X while (ISQ2BORING(c)) X *id++ = c = getc(inFILE); X if (c == '\\') { X *id++ = c = getc(inFILE); X continue; X } else if (c != '"') X goto next; X break; X } X *--id = '\0'; X id = idBuf; X while (ISSTRKEEP(*id)) X id++; X if (*id || id == idBuf) { X c = getc(inFILE); X goto next; X } X *flagP = IDN_STRING; X if (eatUnder && idBuf[0] == '_' && idBuf[1]) X return &idBuf[1]; X else X return idBuf; X X case '\'': X c = getc(inFILE); X for (;;) { X while (ISQ1BORING(c)) X c = getc(inFILE); X if (c == '\\') { X c = getc(inFILE); X continue; X } else if (c == '\'') X c = getc(inFILE); X goto next; X } X X case '/': X if ((c = getc(inFILE)) != '*') X goto next; X c = getc(inFILE); X for (;;) { X while (ISCBORING(c)) X c = getc(inFILE); X if ((c = getc(inFILE)) == '/') { X c = getc(inFILE); X goto next; X } else if (ISEOF(c)) { X newLine = TRUE; X return NULL; X } X } X X case '\n': X newLine = TRUE; X goto top; X X default: X if (ISEOF(c)) { X newLine = TRUE; X return NULL; X } X name: X id = idBuf; X *id++ = c; X if (ISID1ST(c)) { X *flagP = IDN_NAME; X while (ISIDREST(c = getc(inFILE))) X *id++ = c; X } else if (ISDIGIT(c)) { X *flagP = IDN_NUMBER; X while (ISNUMBER(c = getc(inFILE))) X *id++ = c; X } else X fprintf(stderr, "junk: `\\%3o'", c); X ungetc(c, inFILE); X *id = '\0'; X *flagP |= IDN_LITERAL; X return idBuf; X } X} X Xstatic void XsetCtype(chars, type) X char *chars; X int type; X{ X short *rct = &idctype[1]; X X while (*chars) X rct[*chars++] |= type; X} Xstatic void XclrCtype(chars, type) X char *chars; X int type; X{ X short *rct = &idctype[1]; X X while (*chars) X rct[*chars++] &= ~type; X} X Xextern char *MyName; Xstatic void Xusage(lang) X char *lang; X{ X fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang); X exit(1); X} Xstatic char *cDocument[] = X{ X"The C scanner arguments take the form -Sc<arg>, where <arg>", X"is one of the following: (<cc> denotes one or more characters)", X" (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.", X" -s<cc> . . . . Allow <cc> in string ids.", XNULL X}; Xvoid XsetCArgs(lang, op, arg) X char *lang; X int op; X char *arg; X{ X if (op == '?') { X document(cDocument); X return; X } X switch (*arg++) X { X case 'u': X eatUnder = (op == '+'); X break; X case 's': X setCtype(arg, SK); X break; X default: X if (lang) X usage(lang); X break; X } X} SHAR_EOF if test 6502 -ne "`wc -c < 'scan-c.c'`" then echo shar: error transmitting "'scan-c.c'" '(should have been 6502 characters)' fi echo shar: extracting "'stoi.c'" '(1883 characters)' sed 's/^X//' << \SHAR_EOF > 'stoi.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)stoi.c 1.1 86/10/09"; X X#include <radix.h> X#include <ctype.h> X Xint dtoi(); Xint otoi(); Xint radix(); Xint stoi(); Xint xtoi(); X X/* X Use the C lexical rules to determine an ascii number's radix. X The radix is returned as a bit map, so that more than one radix X may apply. In particular, it is impossible to determine the X radix of 0, so return all possibilities. X*/ Xint Xradix(name) X register char *name; X{ X if (!isdigit(*name)) X return 0; X if (*name != '0') X return RADIX_DEC; X name++; X if (*name == 'x' || *name == 'X') X return RADIX_HEX; X while (*name && *name == '0') X name++; X return (RADIX_OCT | ((*name)?0:RADIX_DEC)); X} X X/* X Convert an ascii string number to an integer. X Determine the radix before converting. X*/ Xint Xstoi(name) X char *name; X{ X switch (radix(name)) X { X case RADIX_DEC: return(dtoi(name)); X case RADIX_OCT: return(otoi(&name[1])); X case RADIX_HEX: return(xtoi(&name[2])); X case RADIX_DEC|RADIX_OCT: return(0); X default: return(-1); X } X} X X/* X Convert an ascii octal number to an integer. X*/ Xint Xotoi(name) X char *name; X{ X register int n = 0; X X while (*name >= '0' && *name <= '7') { X n *= 010; X n += *name++ - '0'; X } X if (*name == 'l' || *name == 'L') X name++; X return (*name ? -1 : n); X} X X/* X Convert an ascii decimal number to an integer. X*/ Xint Xdtoi(name) X char *name; X{ X register int n = 0; X X while (isdigit(*name)) { X n *= 10; X n += *name++ - '0'; X } X if (*name == 'l' || *name == 'L') X name++; X return (*name ? -1 : n); X} X X/* X Convert an ascii hex number to an integer. X*/ Xint Xxtoi(name) X char *name; X{ X register int n = 0; X X while (isxdigit(*name)) { X n *= 0x10; X if (isdigit(*name)) X n += *name++ - '0'; X else if (islower(*name)) X n += 0xa + *name++ - 'a'; X else X n += 0xA + *name++ - 'A'; X } X if (*name == 'l' || *name == 'L') X name++; X return (*name ? -1 : n); X} SHAR_EOF if test 1883 -ne "`wc -c < 'stoi.c'`" then echo shar: error transmitting "'stoi.c'" '(should have been 1883 characters)' fi echo shar: extracting "'tty.c'" '(1114 characters)' sed 's/^X//' << \SHAR_EOF > 'tty.c' X#ifdef TERMIO X#include <sys/termio.h> X Xstruct termio linemode, charmode, savemode; X Xsavetty() X{ X ioctl(0, TCGETA, &savemode); X charmode = linemode = savemode; X X charmode.c_lflag &= ~(ECHO|ICANON|ISIG); X charmode.c_cc[VMIN] = 1; X charmode.c_cc[VTIME] = 0; X X linemode.c_lflag |= (ECHO|ICANON|ISIG); X linemode.c_cc[VEOF] = 'd'&037; X linemode.c_cc[VEOL] = 0377; X} X Xrestoretty() X{ X ioctl(0, TCSETA, &savemode); X} X Xlinetty() X{ X ioctl(0, TCSETA, &linemode); X} X Xchartty() X{ X ioctl(0, TCSETA, &charmode); X} X X#else X#include <sgtty.h> X Xstruct sgttyb linemode, charmode, savemode; X Xsavetty() X{ X#ifdef TIOCGETP X ioctl(0, TIOCGETP, &savemode); X#else X gtty(0, &savemode); X#endif X charmode = linemode = savemode; X X charmode.sg_flags &= ~ECHO; X charmode.sg_flags |= RAW; X X linemode.sg_flags |= ECHO; X linemode.sg_flags &= ~RAW; X} X Xrestoretty() X{ X#ifdef TIOCSETP X ioctl(0, TIOCSETP, &savemode); X#else X stty(0, &savemode); X#endif X} X Xlinetty() X{ X#ifdef TIOCSETP X ioctl(0, TIOCSETP, &linemode); X#else X stty(0, &savemode); X#endif X} X Xchartty() X{ X#ifdef TIOCSETP X ioctl(0, TIOCSETP, &charmode); X#else X stty(0, &savemode); X#endif X} X#endif SHAR_EOF if test 1114 -ne "`wc -c < 'tty.c'`" then echo shar: error transmitting "'tty.c'" '(should have been 1114 characters)' fi echo shar: extracting "'uerror.c'" '(586 characters)' sed 's/^X//' << \SHAR_EOF > 'uerror.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)uerror.c 1.1 86/10/09"; X X#include <stdio.h> X Xchar *uerror(); Xvoid filerr(); X Xextern int errno; Xextern int sys_nerr; Xextern char *sys_errlist[]; Xextern char *MyName; X Xchar cannot[] = "%s: Cannot %s `%s' (%s)\n"; X Xchar * Xuerror() X{ X static char errbuf[10]; X X if (errno == 0 || errno >= sys_nerr) { X sprintf(errbuf, "error %d", errno); X return(errbuf); X } X return(sys_errlist[errno]); X} X Xvoid Xfilerr(syscall, fileName) X char *syscall; X char *fileName; X{ X fprintf(stderr, cannot, MyName, syscall, fileName, uerror()); X} SHAR_EOF if test 586 -ne "`wc -c < 'uerror.c'`" then echo shar: error transmitting "'uerror.c'" '(should have been 586 characters)' fi echo shar: extracting "'wmatch.c'" '(830 characters)' sed 's/^X//' << \SHAR_EOF > 'wmatch.c' X/* Copyright (c) 1986, Greg McGary */ Xstatic char sccsid[] = "@(#)wmatch.c 1.1 86/10/09"; X X#include <bool.h> X#include <ctype.h> X Xbool wordMatch(); X X/* X Does `name' occur in `line' delimited by non-alphanumerics?? X*/ Xbool XwordMatch(name0, line) X char *name0; X register char *line; X{ X register char *name = name0; X#define IS_ALNUM(c) (isalnum(c) || (c) == '_') X X for (;;) { X /* find an initial-character match */ X while (*line != *name) { X if (*line == '\n') X return FALSE; X line++; X } X /* do we have a word delimiter on the left ?? */ X if (IS_ALNUM(line[-1])) { X line++; X continue; X } X /* march down both strings as long as we match */ X while (*++name == *++line) X ; X /* is this the end of `name', is there a word delimiter ?? */ X if (*name == '\0' && !IS_ALNUM(*line)) X return TRUE; X name = name0; X } X} SHAR_EOF if test 830 -ne "`wc -c < 'wmatch.c'`" then echo shar: error transmitting "'wmatch.c'" '(should have been 830 characters)' fi # End of shell archive exit 0