1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273 |
- /*
- *$Log: parsehdr.c,v $
- */
- /* Code to parse a header (.h) file */
- /* Descended from xansi; thanks Geoff! thanks Glenn! */
- #include "parsehdr.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <algorithm>
- static dword userval;
- namespace {
- /* the IGNORE byte */
- byte slosh;
- byte last_slosh;
- byte quote1;
- byte quote2;
- byte comment;
- byte hash;
- byte ignore1; /* Special: ignore egactly 1 char */
- byte double_slash;
- byte spare;
- int buff_idx;
- char buffer[BUFF_SIZE];
- byte start; /* Started recording to the buffer */
- byte func; /* Function header detected */
- byte hash_ext;
- int curly; /* Level inside curly brackets */
- int xtern; /* Level inside a extern "C" {} situation */
- int round1; /* Level inside () */
- int line, col;
- dword chars;
- char lastch;
- #define NIL -1 /* Used as an illegal index */
- FILE *datFile; /* Stream of the data (output) file */
- char fileName[81]; /* Name of current header file */
- PH_FUNC_STRUCT *pFunc; /* Pointer to the functions array */
- int numFunc; /* How many elements saved so far */
- int allocFunc; /* How many elements allocated so far */
- int headFunc; /* Head of the function name linked list */
- PH_ARG_STRUCT *pArg; /* Pointer to the arguements array */
- int numArg; /* How many elements saved so far */
- int allocArg; /* How many elements allocated so far */
- int headArg; /* Head of the arguements linked list */
- }
- // DO Callback
- boolT phDoCB(int id, char *data) {
- /* return callback(hDCX, id, data, userval);*/
- return true;
- }
- void phError(char *errmsg) {
- char msg[200];
- sprintf(msg, "PH *ERROR*\nFile: %s L=%d C=%d O=%lu\n%s", fileName, line, col,
- chars, errmsg);
- printf(msg);
- }
- void phWarning(char *errmsg) {
- char msg[200];
- sprintf(msg, "PH -warning-\nFile: %s L=%d C=%d O=%lu\n%s\n", fileName, line,
- col, chars, errmsg);
- printf(msg);
- }
- int IsIgnore() {
- return (comment || quote1 || quote2 || slosh || hash || ignore1 ||
- double_slash);
- }
- boolT isAlphaNum(char ch) {
- return (((ch >= 'A') && (ch <= 'Z')) || ((ch >= 'a') && (ch <= 'z')) ||
- ((ch >= '0') && (ch <= '9')) || (ch == '_'));
- }
- boolT AddToBuffer(char ch) {
- if (buff_idx >= BUFF_SIZE) {
- ERR("function buffer overflow (function unterminated?)\n");
- return false;
- } else {
- buffer[buff_idx++] = ch;
- return true;
- }
- }
- boolT remFromBuffer() {
- if (buff_idx == 0) {
- ERR("function buffer underflow (internal error?)\n");
- return false;
- } else {
- buff_idx--;
- return true;
- }
- }
- /*----------------------------------------------*/
- /* This is a function declaration, typedef, etc.*/
- /* Do something with it. */
- /*----------------------------------------------*/
- void ProcessBuffer(int id) {
- if (buff_idx > 0) {
- buffer[buff_idx] = '\0';
- // CALL CALL BACK FUNTION WITH APPRORIATE CODE!
- switch (id) {
- case PH_FUNCTION:
- // eek, but...
- case PH_PROTO:
- // sort out into params etc
- phBuffToFunc(buffer);
- break;
- case PH_TYPEDEF:
- case PH_DEFINE:
- // sort out into defs
- phBuffToDef(buffer);
- break;
- case PH_MPROTO:
- // eek!
- case PH_VAR:
- // eek!
- case PH_JUNK:
- default:
- phDoCB(id, buffer);
- break;
- }
- start = false;
- func = false;
- buff_idx = 0;
- }
- }
- void phInit(char *filename) // filename is for reference only!!!
- {
- slosh = last_slosh = start = func = comment = double_slash = hash = ignore1 =
- quote1 = quote2 = hash_ext = false;
- buff_idx = curly = xtern = col = round1 = 0;
- line = 1;
- chars = 0L;
- lastch = 0;
- }
- boolT phFree(void) {
- // remove atoms etc, free buffers
- return true;
- }
- void phChar(char ch) {
- col++;
- chars++;
- // printf("%d%% done\r", chars*100/filelen);
- if (slosh != last_slosh) {
- DBG("[SLOSH OFF]");
- }
- switch (ch) {
- case ',':
- if (!IsIgnore() && (curly == xtern) && (start) && (func))
- /* must be multi proto */
- {
- if (lastch == ')') /* eg int foo(), bar(); */
- {
- ProcessBuffer(PH_MPROTO);
- DBG("[END OF MULTIPROTOTYPE]")
- }
- }
- break;
- case ';':
- if (!IsIgnore() && (curly == xtern) && (start)) {
- if (func) {
- if (lastch == ')') {
- ProcessBuffer(PH_PROTO);
- DBG("[END OF PROTOTYPE]")
- }
- } else {
- ProcessBuffer(PH_VAR);
- DBG("[END OF VARIABLE]")
- }
- }
- break;
- case 10: /* end of line */
- line++;
- /* chars++; */ /* must have been a CR before it
- methinks */
- col = 0;
- if (double_slash) {
- double_slash = false;
- DBG("[DOUBLE_SLASH_COMMENT OFF]")
- } else if (hash) {
- if (hash_ext) {
- hash_ext = false;
- } else {
- hash = false;
- DBG("[HASH OFF]")
- }
- }
- if (xtern && (strncmp(buffer, "extern", 6) == 0)) {
- start = false; /* Not the start of anything */
- buff_idx = 0; /* Kill the buffer */
- }
- break;
- case '#': /* start of # something at beginning of line */
- if ((!IsIgnore()) && (curly == xtern)) {
- hash = true;
- DBG("[HASH ON]")
- }
- break;
- case '{':
- if (!IsIgnore()) {
- char st[80];
- if ((curly == xtern) && (start) && (func)) {
- ProcessBuffer(PH_FUNCTION);
- DBG("[FUNCTION DECLARED]")
- }
- curly++;
- sprintf(st, "[CURLY++ %d]", curly);
- DBG(st)
- }
- break;
- case '}':
- if (!IsIgnore()) {
- char st[80];
- if (curly > 0) {
- if (xtern && (xtern == curly)) {
- xtern = 0;
- DBG("[EXTERN OFF]");
- }
- curly--;
- sprintf(st, "[CURLY-- %d]", curly);
- DBG(st)
- } else {
- /* match the {s */
- ERR("too many \"}\"\n");
- }
- }
- break;
- case '(':
- if (!IsIgnore()) {
- char st[80];
- if ((curly == xtern) && (round1 == 0) && (start)) {
- func = true;
- DBG("[FUNCTION]")
- }
- round1++;
- sprintf(st, "[ROUND++ %d]", round1);
- DBG(st)
- }
- break;
- case ')':
- if (!IsIgnore()) {
- char st[80];
- if (round1 > 0) {
- round1--;
- sprintf(st, "[ROUND-- %d]", round1);
- DBG(st)
- } else {
- ERR("too many \")\"\n");
- }
- }
- break;
- case '\\':
- if (!slosh && (quote1 || quote2)) {
- last_slosh = true;
- DBG("[SLOSH ON]")
- } else if (hash) {
- hash_ext = true;
- }
- break;
- case '*':
- if (lastch == '/') /* allow nested comments ! */
- {
- char st[80];
- comment++;
- if (start) {
- remFromBuffer();
- }
- sprintf(st, "[COMMENT++ %d]", comment);
- DBG(st)
- }
- break;
- case '/':
- if ((lastch == '*') && (!quote1) && (!quote2)) {
- if (comment > 0) {
- char st[80];
- comment--;
- /* Don't want the closing slash in the buffer */
- ignore1 = true;
- sprintf(st, "[COMMENT-- %d]", comment);
- DBG(st)
- } else {
- ERR("too many \"*/\"\n");
- }
- } else if (lastch == '/') {
- /* Double slash to end of line is a comment. */
- double_slash = true;
- if (start) {
- remFromBuffer();
- }
- DBG("[DOUBLE_SLASH_COMMENT ON]")
- }
- break;
- case '\"':
- if ((!comment) && (!quote1) && (!slosh)) {
- quote2 = (byte)(!quote2);
- if (quote2)
- DBG("[QUOTE2ON]")
- if (!quote2)
- DBG("[QUOTE2OFF]")
- /* We want to catch the extern "C" {} thing... */
- if (!quote2 && start && (lastch == 'C')) {
- if (strcmp(buffer, "extern ") == 0) {
- char st[80];
- xtern = curly + 1; /* The level inside the extern {} */
- sprintf(st, "[EXTERN ON %d]", xtern);
- DBG(st)
- }
- }
- }
- break;
- case '\'':
- if ((!comment) && (!quote2) && (!slosh)) {
- {
- quote1 = (byte)(!quote1);
- if (quote1)
- DBG("[QUOTE1ON]")
- if (!quote1)
- DBG("[QUOTE1OFF]")
- }
- }
- break;
- case '\t':
- ch = ' ';
- break;
- default:
- if ((ch != -1) && !IsIgnore() && (curly == xtern) && (!start) &&
- (ch != ' ')) {
- start = true;
- DBG("[START OF SOMETHING]")
- }
- break;
- }
- if (ch != -1) {
- if (start && !IsIgnore()) {
- AddToBuffer(ch);
- }
- }
- lastch = ch;
- slosh = last_slosh;
- last_slosh = 0;
- ignore1 = false;
- } /* of phChar */
- /* Take a lump of data from a header file, and churn the state machine
- through each char */
- boolT phData(char *buff, int ndata) {
- int i, j;
- #ifdef DEBUG
- char cLine[81];
- char cfLine[90];
- #endif
- if (ndata < 1) {
- ndata = strlen(buff);
- }
- j = 0;
- for (i = 0; i < ndata; i++) {
- phChar(buff[i]);
- #ifdef DEBUG
- if (j < 80)
- cLine[j++] = buff[i];
- if (buff[i] == '\n') {
- cLine[j] = '\0';
- sprintf(cfLine, "\n***%03d %s\n", line, cLine);
- DBG(cfLine);
- j = 0;
- }
- #endif
- }
- return true;
- }
- boolT phPost(void) {
- boolT err = true;
- char msg[80];
- if (quote1) {
- WARN("EOF: \' not closed");
- err = false;
- }
- if (quote2) {
- WARN("EOF: \" not closed");
- err = false;
- }
- if (comment) {
- WARN("EOF: comment not closed");
- err = false;
- }
- if (slosh) {
- WARN("EOF: internal slosh set error");
- err = false;
- }
- if (curly > 0) {
- sprintf(msg, "EOF: { level = %d", curly);
- WARN(msg);
- err = false;
- }
- if (round1 > 0) {
- sprintf(msg, "EOF: ( level = %d", round1);
- WARN(msg);
- err = false;
- }
- if (hash) {
- WARN("warning hash is set on last line ???");
- err = false;
- }
- return err;
- }
- #if 0
- enum FUNC_E { NORM , LEFT , RIGHT, NEXT };
- void
- NamesToLabel(LPPH_FUNC lpF)
- {
- int i, j;
- for (i=0; i < lpF->num_params; i++)
- {
- while (isspace(types[i][0]))
- {
- lstrcdel(types[i], 0);
- }
- j = 0;
- while(names[i][j] != '\0')
- {
- if ((names[i][j] != '*') &&
- (names[i][j] != '[') &&
- (names[i][j] != ']'))
- {
- lstrccat(label[i], names[i][j]);
- }
- j++ ;
- }
- }
- }
- boolT
- MoveLastWord(char *src, char *dest) /* take arg name from type */
- {
- int i, l;
- LPSTR s2;
- if (s2 = strchr(src, '*')) /* if there is a * use it as starting point */
- {
- lstrcpy(dest, s2);
- *s2 = '\0'; /* terminate */
- }
- else
- {
- l = strlen(src);
- i = l-1;
- while ((i > 0) && ((isspace(src[i])) || (src[i] == '[') || (src[i] == ']')))
- /* find last non space or non [] */
- {
- if (isspace(src[i]))
- {
- lstrcdel(src, i);
- } /* remove trailing spaces */
- i--;
- }
- while ((i > 0) && (!isspace(src[i]))) /* find the previous space */
- {
- i--;
- }
- if (i)
- {
- i++;
- lstrcpy(dest, &src[i]);
- src[i] = '\0'; /* terminate */
- }
- else
- {
- /* no type !!! */
- // if ((mode == TOANSI) ||
- // ((mode == FROMANSI) && (strstr(src, "...") == NULL))
- // )
- if (strstr(src, "...") == NULL) // not a var arg perhaps?
- {
- char msg[80];
- // sprintf(msg,"no type for arg # %d, \"%s\"\n",lpF->num_params, (LPSTR) src);
- // ERR(msg);
- return false;
- }
- else // d'oh!
- {
- WARN("looks like a vararg to me!");
- /* maybe it is a ... !!!!!! */
- }
- }
- }
- i = strlen(src) - 1;
- while ((isspace(src[i])) && (i >= 0))
- {
- src[i--] = '\0';
- }
- i = 0;
- while (dest[i] != '\0')
- {
- if (isspace(dest[i]))
- {
- lstrcdel(dest, i);
- }
- i++ ;
- }
- while ((isspace(src[0])) && (src[0] != '\0'))
- {
- lstrcdel(src, 0);
- }
- return true;
- }
- int
- Lookup(char *aname) /* lookup var name in labels and return arg number */
- {
- int i, p;
- char tname[NAMES_L];
- int bstate = false;
- /* eg: lookup *fred[] for match to fred */
- tname[0] = '\0';
- p = -1; /* default return for no match */
- /* tname is aname without puncs etc */
- i = 0;
- while(aname[i] != '\0')
- {
- if (aname[i] == '[')
- {
- bstate = true;
- }
- else
- if (aname[i] == ']')
- {
- bstate = false;
- }
- if ((isalnum(aname[i]) || aname[i] == '-' || aname[i] == '_') && (!bstate))
- {
- lstrccat(tname, aname[i]);
- }
- i++;
- }
- /* lookup tname in the labels and find out which arg it is */
- for (i=0; i < num_params; i++)
- {
- if (lstrcmp(tname, label[i]) == 0)
- {
- p = i; /* this one ! */
- break;
- }
- }
- return p;
- }
- /* put the name and type at correct arg number */
- boolT
- Plop(char *atype, char *aname, int FAR *num_params, int FAR *num_found)
- {
- char msg[80];
- int t;
- if (num_found >= num_params)
- {
- sprintf(msg,"extra argument \"%s\" in func \"%s\"\n", (LPSTR) aname, (LPSTR) func_name);
- ERR(msg);
- return false;
- }
- t = Lookup(aname); /* arg number */
- if (t == -1) /* couldn't find it */
- {
- sprintf(msg,"bad argument \"%s\" in func \"%s\"\n", (LPSTR) aname, (LPSTR) func_name);
- ERR(msg);
- return false;
- }
- if ((strlen(types[t]) > 0) || (strlen(names[t]) > 0)) /* in use ? */
- {
- sprintf(msg,"argument \"%s\" already used in \"%s\"\n", (LPSTR) aname, (LPSTR) func_name);
- ERR(msg);
- return false;
- }
- lstrcpy(types[t], atype);
- lstrcpy(names[t], aname);
- num_found++; /* got another! */
- return true;
- }
- #define IGN \
- ((*chp == '(') || (*chp == ')') || (*chp == ',') || (*chp == ';') || \
- (isspace(*chp)))
- #define IGNP \
- ((*chp == '(') || (*chp == ')') || (*chp == ',') || (*chp == ';') || \
- (*chp == '\n'))
- #endif
- char token[40]; /* Strings that might be types, nodifiers or idents */
- char ident[40]; /* Names of functions or protos go here */
- char lastChar;
- char *p;
- int indirect;
- boolT isLong, isShort, isUnsigned;
- int lastTokPos; /* For "^" in error messages */
- char *buffP;
- int tok; /* Current token */
- baseType bt; /* Type of current param (or return type) */
- int argNum; /* Arg number (in case no name: arg1, arg2...) */
- void initType(void) {
- indirect = 0;
- isLong = isShort = isUnsigned = false;
- bt = BT_INT;
- }
- void errorParse(char *msg) {
- printf("%s: got ", msg);
- if (tok == TOK_NAME)
- printf("<%s>", token);
- else if (tok == TOK_DOTS)
- printf("...");
- else
- printf("%c (%X)", tok, tok);
- printf("\n%s\n", buffP);
- printf("%*c\n", lastTokPos + 1, '^');
- }
- /* Get a token from pointer p */
- int getToken(void) {
- char ch;
- memset(token, 0, sizeof(token));
- while (*p && ((*p == ' ') || (*p == '\n')))
- p++;
- lastTokPos = p - buffP; /* For error messages */
- if (lastChar) {
- ch = lastChar;
- lastChar = '\0';
- return ch;
- }
- while (ch = *p++) {
- switch (ch) {
- case '*':
- case '[':
- case ']':
- case '(':
- case ')':
- case ',':
- case ';':
- case ' ':
- case '\n':
- if (strlen(token)) {
- if ((ch != ' ') && (ch != '\n'))
- lastChar = ch;
- return TOK_NAME;
- } else if ((ch == ' ') || (ch == '\n'))
- break;
- else
- return ch;
- case '.':
- if ((*p == '.') && (p[1] == '.')) {
- p += 2;
- return TOK_DOTS;
- }
- default:
- token[strlen(token)] = ch;
- }
- }
- return TOK_EOL;
- }
- boolT isBaseType(void) {
- if (tok != TOK_NAME)
- return false;
- if (strcmp(token, "int") == 0) {
- bt = BT_INT;
- } else if (strcmp(token, "char") == 0) {
- bt = BT_CHAR;
- } else if (strcmp(token, "void") == 0) {
- bt = BT_VOID;
- } else if (strcmp(token, "float") == 0) {
- bt = BT_FLOAT;
- } else if (strcmp(token, "double") == 0) {
- bt = BT_DOUBLE;
- } else if (strcmp(token, "struct") == 0) {
- bt = BT_STRUCT;
- tok = getToken(); /* The name of the struct */
- /* Do something with the struct name */
- } else if (strcmp(token, "union") == 0) {
- bt = BT_STRUCT; /* Well its still a struct */
- tok = getToken(); /* The name of the union */
- /* Do something with the union name */
- } else if (strcmp(token, "FILE") == 0) {
- bt = BT_STRUCT;
- } else if (strcmp(token, "size_t") == 0) {
- bt = BT_INT;
- isUnsigned = true;
- } else if (strcmp(token, "va_list") == 0) {
- bt = BT_VOID;
- indirect = 1; /* va_list is a void* */
- } else
- return false;
- return true;
- }
- boolT isModifier(void) {
- if (tok != TOK_NAME)
- return false;
- if (strcmp(token, "long") == 0) {
- isLong = true;
- } else if (strcmp(token, "unsigned") == 0) {
- isUnsigned = true;
- } else if (strcmp(token, "short") == 0) {
- isShort = true;
- } else if (strcmp(token, "const") == 0) {
- } else if (strcmp(token, "_far") == 0) {
- } else
- return false;
- return true;
- }
- boolT isAttrib(void) {
- if (tok != TOK_NAME)
- return false;
- if (strcmp(token, "far") == 0) {
- /* Not implemented yet */
- } else if (strcmp(token, "__far") == 0) {
- /* Not implemented yet */
- } else if (strcmp(token, "__interrupt") == 0) {
- /* Not implemented yet */
- } else
- return false;
- return true;
- }
- boolT isCdecl(void) {
- return ((strcmp(token, "__cdecl") == 0) || (strcmp(token, "_Cdecl") == 0) ||
- (strcmp(token, "cdecl") == 0));
- }
- void getTypeAndIdent(void) {
- /* Get a type and ident pair. Complicated by the fact that types are
- actually optional modifiers followed by types, and the identifier
- is also optional. For example:
- myfunc(unsigned footype *foovar);
- declares an arg named foovar, of type unsigned pointer to footype.
- But we don't exand typedefs and #defines, so the footype may not
- be recognised as a type. Then it is not possible to know whether
- footype is an identifier or an unknown type until the next token is
- read (in this case, the star). If it is a comma or paren, then footype
- is actually an identifier. (This function gets called for the function
- return type and name as well, so "(" is possible as well as ")" and
- ",").
- The identifier is copied to ident.
- */
- boolT im = false, ib;
- while (isModifier()) {
- tok = getToken();
- im = true;
- }
- if (!im && (tok != TOK_NAME)) {
- errorParse("Expected type");
- }
- ib = isBaseType();
- if (ib)
- tok = getToken();
- /* Could be modifiers like "far", "interrupt" etc */
- while (isAttrib()) {
- tok = getToken();
- }
- while (tok == '*') {
- indirect++;
- tok = getToken();
- }
- /* Ignore the cdecl's */
- while (isCdecl())
- tok = getToken();
- if (tok == TOK_NAME) {
- /* This could be an ident or an unknown type */
- strcpy(ident, token);
- tok = getToken();
- }
- if (!ib && (tok != ',') && (tok != '(') && (tok != ')')) {
- /* That was (probably) not an ident! Assume it was an unknown type */
- printf("Unknown type %s\n", ident);
- ident[0] = '\0';
- bt = BT_UNKWN;
- while (tok == '*') {
- indirect++;
- tok = getToken();
- }
- /* Ignore the cdecl's */
- while (isCdecl())
- tok = getToken();
- }
- if (tok == TOK_NAME) {
- /* This has to be the ident */
- strcpy(ident, token);
- tok = getToken();
- }
- while (tok == '[') {
- indirect++; /* Treat x[] like *x */
- do {
- tok = getToken(); /* Ignore stuff between the '[' and ']' */
- } while (tok != ']');
- tok = getToken();
- }
- }
- hlType convType(void) {
- /* Convert from base type and signed/unsigned flags, etc, to a htType
- as Cristina currently uses */
- if (indirect >= 1) {
- if (bt == BT_CHAR)
- return TYPE_STR; /* Assume char* is ptr */
- /* Pointer to anything else (even unknown) is type pointer */
- else
- return TYPE_PTR;
- }
- switch (bt) {
- case BT_INT:
- if (isLong) {
- if (isUnsigned)
- return TYPE_LONG_UNSIGN;
- else
- return TYPE_LONG_SIGN;
- } else {
- if (isUnsigned)
- return TYPE_WORD_UNSIGN;
- else
- return TYPE_WORD_SIGN;
- }
- case BT_CHAR:
- if (isUnsigned)
- return TYPE_BYTE_UNSIGN;
- else
- return TYPE_BYTE_SIGN;
- case BT_FLOAT:
- return TYPE_FLOAT;
- case BT_DOUBLE:
- return TYPE_DOUBLE;
- case BT_STRUCT:
- return TYPE_RECORD;
- case BT_VOID:
- default:
- return TYPE_UNKNOWN;
- }
- }
- /* Add a new function to the array of function name and return types. The
- array is logically sorted by a linked list. Note that numArg is filled
- in later */
- boolT addNewFunc(char *name, hlType typ) {
- int i, prev, res;
- /* First see if the name already exists */
- prev = NIL;
- for (i = headFunc; i != NIL; i = pFunc[i].next) {
- res = strcmp(pFunc[i].name, name);
- if (res > 0) {
- break; /* Exit this loop when just past insert point */
- }
- if (res == 0) {
- /* Already have this function name */
- return true;
- }
- prev = i;
- }
- if (numFunc >= allocFunc) {
- allocFunc += DELTA_FUNC;
- pFunc = (PH_FUNC_STRUCT *)realloc(pFunc, allocFunc * sizeof(PH_FUNC_STRUCT));
- if (pFunc == NULL) {
- fprintf(stderr, "Could not allocate %ud bytes for function array\n",
- allocFunc * sizeof(PH_FUNC_STRUCT));
- exit(1);
- }
- memset(&pFunc[allocFunc - DELTA_FUNC], 0,
- DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
- }
- name[SYMLEN - 1] = '\0';
- strcpy(pFunc[numFunc].name, name);
- pFunc[numFunc].typ = typ;
- pFunc[numFunc].firstArg = numArg;
- if (prev == NIL) {
- pFunc[numFunc].next = headFunc;
- headFunc = numFunc;
- } else {
- pFunc[numFunc].next = pFunc[prev].next;
- pFunc[prev].next = numFunc;
- }
- numFunc++;
- return false;
- }
- /* Add a new arguement to the array of arguement name and types. The
- array is logically sorted by a linked list */
- void addNewArg(char *name, hlType typ) {
- if (numArg >= allocArg) {
- allocArg += DELTA_FUNC;
- pArg = (PH_ARG_STRUCT *)realloc(pArg, allocArg * sizeof(PH_ARG_STRUCT));
- if (pArg == NULL) {
- fprintf(stderr, "Could not allocate %ud bytes for arguement array\n",
- allocArg * sizeof(PH_ARG_STRUCT));
- exit(1);
- }
- memset(&pArg[allocArg - DELTA_FUNC], 0, DELTA_FUNC * sizeof(PH_ARG_STRUCT));
- }
- name[SYMLEN - 1] = '\0';
- strcpy(pArg[numArg].name, name);
- pArg[numArg].typ = typ;
- numArg++;
- }
- void parseParam(void) {
- initType();
- if (tok == TOK_DOTS) {
- tok = getToken();
- pFunc[numFunc - 1].bVararg = true;
- return;
- }
- getTypeAndIdent();
- if ((bt == BT_VOID) && (indirect == 0)) {
- /* Just a void arg list. Ignore and pFunc[].numArgs will be set to zero */
- return;
- }
- argNum++;
- if (ident[0]) {
- addNewArg(ident, convType());
- } else {
- sprintf(ident, "arg%d", argNum);
- addNewArg(ident, convType());
- }
- }
- /* Parse the prototype as follows:
- <type> [<cdecl>] ["*"]... <funcName>"("<paramDef> [","<paramDef>]...")"
- where <type> is
- ["const"] [<modifier>] [<basetype>] modifier could be short, long, far
- and where paramdef is
- ["const"] <type> ["*"]... [<paramName>] or "..."
- Note that the closing semicolon is not seen.
- */
- void phBuffToFunc(char *buff) {
- initType();
- p = buffP = buff;
- tok = getToken();
- /* Ignore typedefs, for now */
- if ((tok == TOK_NAME) && (strcmp(token, "typedef") == 0))
- return;
- getTypeAndIdent();
- if (ident[0] == '\0') {
- errorParse("Expected function name");
- return;
- }
- if (addNewFunc(ident, convType())) {
- /* Already have this prototype, so ignore it */
- return;
- }
- if (tok != '(') {
- errorParse("Expected '('");
- return;
- }
- tok = getToken();
- argNum = 0;
- while (tok != TOK_EOL) {
- parseParam();
- if ((tok != ',') && (tok != ')')) {
- errorParse("Expected ',' between parameter defs");
- return;
- }
- tok = getToken();
- }
- pFunc[numFunc - 1].numArg = argNum; /* Number of args this func */
- }
- void phBuffToDef(char *buff) {}
- void writeFile(char *buffer, int len) {
- if ((int)fwrite(buffer, 1, len, datFile) != len) {
- printf("Could not write to file\n");
- exit(1);
- }
- }
- void writeFileShort(word w) {
- byte b;
- b = (byte)(w & 0xFF);
- writeFile((char *)&b, 1); /* Write a short little endian */
- b = (byte)(w >> 8);
- writeFile((char *)&b, 1);
- }
- void saveFile(void) {
- int i;
- fprintf(datFile, "dccp"); /* Signature */
- fprintf(datFile, "FN"); /* Function name tag */
- writeFileShort(numFunc); /* Number of func name records */
- for (i = headFunc; i != NIL; i = pFunc[i].next) {
- writeFile(pFunc[i].name, SYMLEN);
- writeFileShort((word)pFunc[i].typ);
- writeFileShort((word)pFunc[i].numArg);
- writeFileShort((word)pFunc[i].firstArg);
- writeFile((char *)&pFunc[i].bVararg, 1);
- }
- fprintf(datFile, "PM"); /* Parameter Name tag */
- writeFileShort(numArg); /* Number of args */
- for (i = 0; i < numArg; i++) {
- // writeFile(pArg[i].name, SYMLEN); // Don't want names yet
- writeFileShort((word)pArg[i].typ);
- }
- }
- int main(int argc, char *argv[]) {
- char *buf;
- long fSize;
- int ndata;
- FILE *f, *fl;
- int i;
- char *p;
- if (argc != 2) {
- printf("Usage: parsehdr <listfile>\n"
- "where <listfile> is a file of header file names to parse.\n"
- "The file dcclibs.dat will be written\n");
- exit(1);
- }
- fl = fopen(argv[1], "rt");
- if (fl == NULL) {
- printf("Could not open file list file %s\n", argv[1]);
- exit(1);
- }
- datFile = fopen("dcclibs.dat", "wb");
- if (datFile == NULL) {
- printf("Could not open output file dcclibs.dat\n");
- exit(2);
- }
- /* Allocate the arrys for function and proto names and types */
- pFunc = (PH_FUNC_STRUCT *)malloc(DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
- if (pFunc == 0) {
- fprintf(stderr, "Could not malloc %ud bytes for function name array\n",
- DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
- exit(1);
- }
- memset(pFunc, 0, DELTA_FUNC * sizeof(PH_FUNC_STRUCT));
- allocFunc = DELTA_FUNC;
- numFunc = 0;
- pArg = (PH_ARG_STRUCT *)malloc(DELTA_FUNC * sizeof(PH_ARG_STRUCT));
- if (pArg == 0) {
- fprintf(stderr, "Could not malloc %ud bytes for arguement array\n",
- DELTA_FUNC * sizeof(PH_ARG_STRUCT));
- exit(1);
- }
- memset(pArg, 0, DELTA_FUNC * sizeof(PH_ARG_STRUCT));
- allocArg = DELTA_FUNC;
- numArg = 0;
- headFunc = headArg = NIL;
- buf = NULL;
- while (!feof(fl)) {
- /* Get another filename from the file list */
- p = fgets(fileName, 80, fl);
- if (p == NULL)
- break; /* Otherwise read last filename twice */
- i = strlen(fileName) - 1;
- if (fileName[i] == '\n')
- fileName[i] = '\0';
- f = fopen(fileName, "rt");
- if (f == NULL) {
- printf("Could not open header file %s\n", fileName);
- exit(1);
- }
- printf("Processing %s...\n", fileName);
- fseek(f, 0, SEEK_END);
- fSize = ftell(f);
- fseek(f, 0, SEEK_SET);
- ndata = std::min<int>(fSize, FBUF_SIZE);
- if (buf)
- free(buf);
- buf = (char *)malloc(ndata);
- if (buf == 0) {
- printf("Could not malloc input file buffer of %d bytes\n", ndata);
- exit(1);
- }
- while (!feof(f)) {
- ndata = fread(buf, 1, ndata, f);
- phData(buf, ndata);
- }
- phPost();
- fclose(f);
- }
- saveFile();
- fclose(datFile);
- fclose(fl);
- free(buf);
- free(pFunc);
- free(pArg);
- }
- #if CHECK_HEAP
- void checkHeap(char *msg)
- /* HEAPCHK.C: This program checks the heap for
- * consistency and prints an appropriate message.
- */
- {
- int heapstatus;
- printf("%s\n", msg);
- /* Check heap status */
- heapstatus = _heapchk();
- switch (heapstatus) {
- case _HEAPOK:
- printf(" OK - heap is fine\n");
- break;
- case _HEAPEMPTY:
- printf(" OK - heap is empty\n");
- break;
- case _HEAPBADBEGIN:
- printf("ERROR - bad start of heap\n");
- break;
- case _HEAPBADNODE:
- printf("ERROR - bad node in heap\n");
- break;
- }
- }
- #endif
|