/* * token.c : piddle with tokens */ /* Copyright 1990, 1991, 1992 Craig Durland * Distributed under the terms of the GNU General Public License. * Distributed "as is", without warranties of any kind, but comments, * suggestions and bug reports are welcome. */ #include #include #include #include #include "mc.h" #include "mm.h" #include "opcode.h" extern char ebuf[], *malloc(), *savestr(), *spoof(); /*********************************************************************** ********************* Token tables ************************************* ***********************************************************************/ MuttCmd /* holes: 22, 30, 32-41, 44-59, 74 */ muttcmds[] = /* biggest # = 81 */ { "!=", 0, "*", 65, "*=", 66, "+", 3, "+=", 63, "-", 67, "-=", 68, "/", 69, "/=", 70, "<", 11, "<=", 10, "==", 12, ">", 13, ">=", 14, "and", 80, "arg", 43, "array", 73, "ask-user", 26, "bool", 62, "break", 7, "byte", 75, "cond", 1, "const", 77, "continue", 71, "convert-to", 20, "defun", 2, "done", 9, "extract-element", 24, "extract-elements", 25, "floc", 78, "for", 76, "goto", 6, "halt", 16, "if", 23, "include", 64, "insert-object", 18, "int", 31, "label", 8, "length-of", 19, "list", 27, "loc", 79, "nargs", 42, "not", 28, "novalue", 29, "or", 81, "pointer", 72, "push-arg", 17, "push-args", 15, "remove-elements", 21, "small-int", 61, "string", 60, "switch", 4, "while", 5, }, modifiers[] = /* the pgm modifiers */ { "HIDDEN", HIDDEN, "MAIN", MAIN, }; oMuttCmd omuttcmds[] = /* the other Mutt commands, see other_Mutt_cmd() */ { "ask", ASK, STRING, "concat", CONCAT, STRING, "extract-element", EXTRACT_EL, UNKNOWN, "extract-elements", EXTRACT_ELS,UNKNOWN, /* !!!actually, same as first arg */ "insert-object", INSERT_OBJ, UNKNOWN, "msg", MSG, STRING, "remove-elements", REMOVE_ELS, VOID, }; int msize = NITEMS(muttcmds), omsize = NITEMS(omuttcmds), moders = NITEMS(modifiers); /* ******************************************************************** */ /* ************************* External Tokens ************************** */ /* ******************************************************************** */ /* * A token table is stored in a file. * Format: * */ static declare_and_init_dTable(ext_token_table,MuttCmd); static int num_ext_tokens = 0; void load_ext_token_table(fname) char *fname; { char buf[90], *ptr; int t; FILE *fptr; new_ext(buf,fname,".tok"); if ((fptr = fopen(buf,"r")) == NULL) bitch(spoof(ebuf,"Can't open token file %s!",buf)); while ((ptr = fgets(buf,80,fptr))) { if (!xpand_dTable(&ext_token_table, 1, 100,50)) { printf("Out of memory! Can't expand external token table.\n"); exit(1); } buf[strlen(buf)-1] = '\0'; t = atoi(ptr); while (*ptr++!=' ') ; if (NULL == (ptr = savestr(ptr))) bail("Can't malloc external token name"); ext_token_table.table[num_ext_tokens].name = ptr; ext_token_table.table[num_ext_tokens].token = t; num_ext_tokens++; } } /* Look for an external token by name. Returns value. * Input: * name: name of the token to search for. If NULL, search by value. * Returns: * -1 : name not found. * val : token value. */ lookup_ext_token_by_name(name) char *name; { return lookup(name, ext_token_table.table, num_ext_tokens); } /* Look for an external token by value. Returns name. * Input: * val: token value to search for if name is NULL. * Returns: * NULL : val not found * pointer to the token name */ char *lookup_ext_token_by_value(val) { int j; for (j = 0; j < num_ext_tokens; j++) if (ext_token_table.table[j].token == val) return ext_token_table.table[j].name; return NULL; } /* ******************************************************************** */ /* ******************* Mutt Table Look Up Routines ******************** */ /* ******************************************************************** */ /* Use binary search table to find name * returns: token (if name in table) else -1 */ /* ??? use bsearch */ lookup(name,table,n) char *name; MuttCmd *table; { register int j, lower = 0, upper = n-1, x; while (lower <= upper) { j = (lower+upper)/2; if ((x = strcmp(name,table[j].name))>0) lower = j +1; else if (x<0) upper = j -1; else return table[j].token; } return -1; } /* ??? use bsearch */ oMuttCmd *olookup(name,table,n) char *name; oMuttCmd *table; { register int j, lower = 0, upper = n-1, x; while (lower<=upper) { j = (lower+upper)/2; if ((x = strcmp(name,table[j].name))>0) lower = j +1; else if (x<0) upper = j -1; else return &table[j]; } return NULL; } /*********************************************************************** ********************* Conversion routines ****************************** ***********************************************************************/ int32 atoN(a) char *a; /* convert string to NUMBER */ { char c, *b=a; int minus = FALSE, base = 10, z; int32 n = 0; if (*a == '-') { a++; minus = TRUE; } if (*a == '0' && a[1] == 'x') { base = 16; a += 2; } for (; *a; a++) { c = *a; z = 1000; if ('0' <= c && c <= '9') z = c -'0'; else if ('a' <= c && c <= 'f') z = c -'a' +10; else if ('A' <= c && c <= 'F') z = c -'A' +10; if (z >= base) { moan(spoof(ebuf,"Invalid digit in %s",b)); break; } n = n*base +z; } return minus ? -n : n; } /*********************************************************************** ********************* Scanning routines ******************************** ***********************************************************************/ #include extern char token[]; /* in mc.c */ extern FILE *lstfile, *srcfile; /* in mc.c */ extern int srcline; /* in mc.c */ extern unsigned int class; static char pgmtext[514], *xptr; static int looked = FALSE; static unsigned int proclass; int btv = FALSE; /* boolean token value - returned by get_token() */ /* move the pc to the next nonwhite character * returns: TRUE if ok, FALSE if EoF */ getsrc() { char *ptr; if ((xptr = fgets(pgmtext,512,srcfile)) == NULL) return FALSE; if (*(ptr = xptr + strlen(xptr) -1) == '\n') *ptr = '\0'; srcline++; if (lstfile) fprintf(lstfile,"LINE %d: %s\n",srcline,xptr); return TRUE; } /* skip comment => skip to next line */ /* EoF: Ok if comment is last thing in buffer/file */ #define nocomment() getsrc() static scan() { top: /* incase got to get a new line */ while (isspace(*xptr)) xptr++; /* delete leading white space */ if (*xptr == '\0' || *xptr == '\n') if (getsrc()) goto top; else return FALSE; if (*xptr == ';') if (nocomment()) goto top; else return FALSE; return TRUE; } /* returns: TRUE (all ok), FALSE (something screwed up) */ void get_token() { register char *ptr; if (looked) { looked = FALSE; class = proclass; return; } *(ptr = token) = '\0'; class = TOKEN; if (!scan()) { class = proclass = SEOF; return; } switch (*xptr) { case '\'': /* string literal: 'string', ''=>' */ for (xptr++; *xptr && ptr < (token +250); xptr++) if (*xptr == '\'' && *++xptr != '\'') goto uggg; else *ptr++ = *xptr; if (*xptr == '\0') bitch("String not terminated!"); uggg: class = STRING; break; case '\"': /* "string": knows about \ (quote), ^ (control) */ for (xptr++; *xptr && *xptr != '\"' && ptr < (token +250); xptr++) switch (*xptr) { case '\\': *ptr++ = *++xptr; break; /* \ : quote next char */ case '^': *ptr++ = *++xptr ^ 0x40; break; /* ^ => cntl char */ default: *ptr++ = *xptr; } if (*xptr == '\0') bitch("String not terminated!"); xptr++; class = STRING; break; default: /* get a token or number */ while (*xptr && !isspace(*xptr)) { if (strchr("(){};",*xptr)) { if (ptr == token) { class = DELIMITER; *ptr++ = *xptr++; } break; } *ptr++ = *xptr++; } } *ptr = '\0'; if (class == TOKEN) { if ((isdigit(*token) || (*token == '-' && isdigit(*(token+1))))) class = NUMBER; else if (strcmp(token,"FALSE") == 0) { class = BOOLEAN; btv = FALSE; } else if (strcmp(token,"TRUE") == 0) { class = BOOLEAN; btv = TRUE; } } proclass = class; return; } /* Note: gotta be careful class don't get trashed between * lookahead() & get_token() */ void lookahead() { if (looked) { class = proclass; return; } get_token(); looked = TRUE; } typedef struct Inca { struct Inca *next; char fname[1]; } Inca; static Inca *inchead = NULL; include(fname) char *fname; { register Inca *ptr; for (ptr = inchead; ptr; ptr = ptr->next) if (strcmp(ptr->fname,fname) == 0) { gripe(spoof(ebuf,"Already included: %s. Ignoring.",fname)); nocomment(); /* bloto rest of line */ return UNKNOWN; } if (NULL == (ptr = (Inca *)malloc(sizeof(Inca) +strlen(fname)))) bail("Out of memory in include()"); strcpy(ptr->fname,fname); ptr->next = inchead; inchead = ptr; pilefile(fname,TRUE); getsrc(); /* prime scan() */ return UNKNOWN; }