home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
dirs
/
mkid_448.lzh
/
Mkid
/
src
/
scan-c.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-01
|
7KB
|
294 lines
/* Copyright (c) 1986, Greg McGary */
static char sccsid[] = "@(#)scan-c.c 1.1 86/10/09";
#include "bool.h"
#include <stdio.h>
#include "string.h"
#include "id.h"
char *getCId();
void setCArgs();
static void clrCtype();
static void setCtype();
#define I1 0x0001 /* 1st char of an identifier [a-zA-Z_] */
#define DG 0x0002 /* decimal digit [0-9] */
#define NM 0x0004 /* extra chars in a hex or long number [a-fA-FxXlL] */
#define C1 0x0008 /* C comment introduction char: / */
#define C2 0x0010 /* C comment termination char: * */
#define Q1 0x0020 /* single quote: ' */
#define Q2 0x0040 /* double quote: " */
#define ES 0x0080 /* escape char: \ */
#define NL 0x0100 /* newline: \n */
#define EF 0x0200 /* EOF */
#define SK 0x0400 /* Make these chars valid for names within strings */
/*
character class membership macros:
*/
#define ISDIGIT(c) ((rct)[c]&(DG)) /* digit */
#define ISNUMBER(c) ((rct)[c]&(DG|NM)) /* legal in a number */
#define ISEOF(c) ((rct)[c]&(EF)) /* EOF */
#define ISID1ST(c) ((rct)[c]&(I1)) /* 1st char of an identifier */
#define ISIDREST(c) ((rct)[c]&(I1|DG)) /* rest of an identifier */
#define ISSTRKEEP(c) ((rct)[c]&(I1|DG|SK)) /* keep contents of string */
/*
The `BORING' classes should be skipped over
until something interesting comes along...
*/
#define ISBORING(c) (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1))) /* fluff */
#define ISCBORING(c) (!((rct)[c]&(EF|C2))) /* comment fluff */
#define ISQ1BORING(c) (!((rct)[c]&(EF|NL|Q1|ES))) /* char const fluff */
#define ISQ2BORING(c) (!((rct)[c]&(EF|NL|Q2|ES))) /* quoted str fluff */
static short 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, Q2, 0, 0, 0, 0, Q1,
/*050*/ 0, 0, C2, 0, 0, 0, 0, C1,
/*060*/ DG, DG, DG, DG, DG, DG, DG, DG,
/*070*/ DG, DG, 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, ES, 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;
/*
Grab the next identifier the C source
file opened with the handle `inFILE'.
This state machine is built for speed, not elegance.
*/
char *
getCId(inFILE, flagP)
FILE *inFILE;
int *flagP;
{
static char idBuf[BUFSIZ];
static bool newLine = TRUE;
register short *rct = &idctype[1];
register int c;
register char *id = idBuf;
top:
c = getc(inFILE);
if (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 (strcmp(idBuf, "include") == 0) {
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 (strncmp(idBuf, "if", 2) == 0
|| strcmp(idBuf, "define") == 0
|| strcmp(idBuf, "undef") == 0)
goto next;
while (c != '\n')
c = getc(inFILE);
newLine = TRUE;
goto top;
}
next:
while (ISBORING(c))
c = getc(inFILE);
switch (c)
{
case '"':
id = idBuf;
*id++ = c = getc(inFILE);
for (;;) {
while (ISQ2BORING(c))
*id++ = c = getc(inFILE);
if (c == '\\') {
*id++ = c = getc(inFILE);
continue;
} else if (c != '"')
goto next;
break;
}
*--id = '\0';
id = idBuf;
while (ISSTRKEEP(*id))
id++;
if (*id || id == idBuf) {
c = getc(inFILE);
goto next;
}
*flagP = IDN_STRING;
if (eatUnder && idBuf[0] == '_' && idBuf[1])
return &idBuf[1];
else
return idBuf;
case '\'':
c = getc(inFILE);
for (;;) {
while (ISQ1BORING(c))
c = getc(inFILE);
if (c == '\\') {
c = getc(inFILE);
continue;
} else if (c == '\'')
c = getc(inFILE);
goto next;
}
case '/':
if ((c = getc(inFILE)) != '*')
goto next;
c = getc(inFILE);
for (;;) {
while (ISCBORING(c))
c = getc(inFILE);
if ((c = getc(inFILE)) == '/') {
c = getc(inFILE);
goto next;
} else if (ISEOF(c)) {
newLine = TRUE;
return NULL;
}
}
case '\n':
newLine = TRUE;
goto top;
default:
if (ISEOF(c)) {
newLine = TRUE;
return NULL;
}
name:
id = idBuf;
*id++ = c;
if (ISID1ST(c)) {
*flagP = IDN_NAME;
while (ISIDREST(c = getc(inFILE)))
*id++ = c;
} else if (ISDIGIT(c)) {
*flagP = IDN_NUMBER;
while (ISNUMBER(c = getc(inFILE)))
*id++ = c;
} else
fprintf(stderr, "junk: `\\%3o'", c);
ungetc(c, inFILE);
*id = '\0';
*flagP |= IDN_LITERAL;
return idBuf;
}
}
static void
setCtype(chars, type)
char *chars;
int type;
{
short *rct = &idctype[1];
while (*chars)
rct[*chars++] |= type;
}
static void
clrCtype(chars, type)
char *chars;
int type;
{
short *rct = &idctype[1];
while (*chars)
rct[*chars++] &= ~type;
}
extern char *MyName;
static void
usage(lang)
char *lang;
{
fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang);
exit(1);
}
static char *cDocument[] =
{
"The C scanner arguments take the form -Sc<arg>, where <arg>",
"is one of the following: (<cc> denotes one or more characters)",
" (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.",
" -s<cc> . . . . Allow <cc> in string ids.",
NULL
};
void
setCArgs(lang, op, arg)
char *lang;
int op;
char *arg;
{
if (op == '?') {
document(cDocument);
return;
}
switch (*arg++)
{
case 'u':
eatUnder = (op == '+');
break;
case 's':
setCtype(arg, SK);
break;
default:
if (lang)
usage(lang);
break;
}
}