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