home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1986, Greg McGary */
- static char sccsid[] = "@(#)scan-asm.c 1.2 86/11/06";
-
- #include <bool.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <id.h>
-
- char *getAsmId();
- void setAsmArgs();
-
- static void clrCtype();
- static void setCtype();
-
- #define I1 0x01 /* 1st char of an identifier [a-zA-Z_] */
- #define NM 0x02 /* digit [0-9a-fA-FxX] */
- #define NL 0x04 /* newline: \n */
- #define CM 0x08 /* assembler comment char: usually # or | */
- #define IG 0x10 /* ignore `identifiers' with these chars in them */
- #define C1 0x20 /* C comment introduction char: / */
- #define C2 0x40 /* C comment termination char: * */
- #define EF 0x80 /* EOF */
-
- /* Assembly Language character classes */
- #define ISID1ST(c) ((rct)[c]&(I1))
- #define ISIDREST(c) ((rct)[c]&(I1|NM))
- #define ISNUMBER(c) ((rct)[c]&(NM))
- #define ISEOF(c) ((rct)[c]&(EF))
- #define ISCOMMENT(c) ((rct)[c]&(CM))
- #define ISBORING(c) (!((rct)[c]&(EF|NL|I1|NM|CM|C1)))
- #define ISCBORING(c) (!((rct)[c]&(EF|NL)))
- #define ISCCBORING(c) (!((rct)[c]&(EF|C2)))
- #define ISIGNORE(c) ((rct)[c]&(IG))
-
- static char idctype[] = {
-
- EF,
-
- /* 0 1 2 3 4 5 6 7 */
- /* ----- ----- ----- ----- ----- ----- ----- ----- */
-
- /*000*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*010*/ 0, 0, NL, 0, 0, 0, 0, 0,
- /*020*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*030*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*040*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*050*/ 0, 0, C2, 0, 0, 0, 0, C1,
- /*060*/ NM, NM, NM, NM, NM, NM, NM, NM,
- /*070*/ NM, NM, 0, 0, 0, 0, 0, 0,
- /*100*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1,
- /*110*/ I1, I1, I1, I1, I1|NM, I1, I1, I1,
- /*120*/ I1, I1, I1, I1, I1, I1, I1, I1,
- /*130*/ I1|NM, I1, I1, 0, 0, 0, 0, I1,
- /*140*/ 0, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1|NM, I1,
- /*150*/ I1, I1, I1, I1, I1|NM, I1, I1, I1,
- /*160*/ I1, I1, I1, I1, I1, I1, I1, I1,
- /*170*/ I1|NM, I1, I1, 0, 0, 0, 0, 0,
-
- /*200*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*210*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*220*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*230*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*240*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*250*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*260*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*270*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*300*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*310*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*320*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*330*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*340*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*350*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*360*/ 0, 0, 0, 0, 0, 0, 0, 0,
- /*370*/ 0, 0, 0, 0, 0, 0, 0, 0,
-
- };
-
- static bool eatUnder = TRUE;
- static bool preProcess = TRUE;
-
- /*
- Grab the next identifier the assembly language
- source file opened with the handle `inFILE'.
- This state machine is built for speed, not elegance.
- */
- char *
- getAsmId(inFILE, flagP)
- FILE *inFILE;
- int *flagP;
- {
- static char idBuf[BUFSIZ];
- register char *rct = &idctype[1];
- register int c;
- register char *id = idBuf;
- static bool newLine = TRUE;
-
- top:
- c = getc(inFILE);
- if (preProcess > 0 && newLine) {
- newLine = FALSE;
- if (c != '#')
- goto next;
- while (ISBORING(c))
- c = getc(inFILE);
- if (!ISID1ST(c))
- goto next;
- id = idBuf;
- *id++ = c;
- while (ISIDREST(c = getc(inFILE)))
- *id++ = c;
- *id = '\0';
- if (strequ(idBuf, "include")) {
- while (c != '"' && c != '<')
- c = getc(inFILE);
- id = idBuf;
- *id++ = c = getc(inFILE);
- while ((c = getc(inFILE)) != '"' && c != '>')
- *id++ = c;
- *id = '\0';
- *flagP = IDN_STRING;
- return idBuf;
- }
- if (strnequ(idBuf, "if", 2)
- || strequ(idBuf, "define")
- || strequ(idBuf, "undef"))
- goto next;
- while (c != '\n')
- c = getc(inFILE);
- newLine = TRUE;
- goto top;
- }
-
- next:
- while (ISBORING(c))
- c = getc(inFILE);
-
- if (ISCOMMENT(c)) {
- while (ISCBORING(c))
- c = getc(inFILE);
- newLine = TRUE;
- }
-
- if (ISEOF(c)) {
- newLine = TRUE;
- return NULL;
- }
-
- if (c == '\n') {
- newLine = TRUE;
- goto top;
- }
-
- if (c == '/') {
- if ((c = getc(inFILE)) != '*')
- goto next;
- c = getc(inFILE);
- for (;;) {
- while (ISCCBORING(c))
- c = getc(inFILE);
- if ((c = getc(inFILE)) == '/') {
- c = getc(inFILE);
- break;
- } else if (ISEOF(c)) {
- newLine = TRUE;
- return NULL;
- }
- }
- goto next;
- }
-
- id = idBuf;
- if (eatUnder && c == '_' && !ISID1ST(c = getc(inFILE))) {
- ungetc(c, inFILE);
- return "_";
- }
- *id++ = c;
- if (ISID1ST(c)) {
- *flagP = IDN_NAME;
- while (ISIDREST(c = getc(inFILE)))
- *id++ = c;
- } else if (ISNUMBER(c)) {
- *flagP = IDN_NUMBER;
- while (ISNUMBER(c = getc(inFILE)))
- *id++ = c;
- } else {
- if (isprint(c))
- fprintf(stderr, "junk: `%c'", c);
- else
- fprintf(stderr, "junk: `\\%03o'", c);
- goto next;
- }
-
- *id = '\0';
- for (id = idBuf; *id; id++)
- if (ISIGNORE(*id))
- goto next;
- ungetc(c, inFILE);
- *flagP |= IDN_LITERAL;
- return idBuf;
- }
-
- static void
- setCtype(chars, type)
- char *chars;
- int type;
- {
- char *rct = &idctype[1];
-
- while (*chars)
- rct[*chars++] |= type;
- }
- static void
- clrCtype(chars, type)
- char *chars;
- int type;
- {
- char *rct = &idctype[1];
-
- while (*chars)
- rct[*chars++] &= ~type;
- }
-
- extern char *MyName;
- static void
- usage(lang)
- char *lang;
- {
- fprintf(stderr, "Usage: %s -S%s([-c<cc>] [-u] [(+|-)a<cc>] [(+|-)p] [(+|-)C])\n", MyName, lang);
- exit(1);
- }
- static char *asmDocument[] =
- {
- "The Assembler scanner arguments take the form -Sasm<arg>, where",
- "<arg> is one of the following: (<cc> denotes one or more characters)",
- " -c<cc> . . . . <cc> introduce(s) a comment until end-of-line.",
- " (+|-)u . . . . (Do|Don't) strip a leading `_' from ids.",
- " (+|-)a<cc> . . Allow <cc> in ids, and (keep|ignore) those ids.",
- " (+|-)p . . . . (Do|Don't) handle C-preprocessor directives.",
- " (+|-)C . . . . (Do|Don't) handle C-style comments. (/* */)",
- NULL
- };
- void
- setAsmArgs(lang, op, arg)
- char *lang;
- int op;
- char *arg;
- {
- if (op == '?') {
- document(asmDocument);
- return;
- }
- switch (*arg++)
- {
- case 'a':
- setCtype(arg, I1|((op == '-') ? IG : 0));
- break;
- case 'c':
- setCtype(arg, CM);
- break;
- case 'u':
- eatUnder = (op == '+');
- break;
- case 'p':
- preProcess = (op == '+');
- break;
- case 'C':
- if (op == '+') {
- setCtype("/", C1);
- setCtype("*", C2);
- } else {
- clrCtype("/", C1);
- clrCtype("*", C2);
- }
- break;
- default:
- if (lang)
- usage(lang);
- break;
- }
- }
-