#ident "@(#)parser.c 1.8 91/04/01 XGRASP" /*- * parser.c - grasp language file parser. * * Copyright (c) 1991 by Patrick J. Naughton * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation. * * This file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * Comments and additions should be sent to the author: * * Patrick J. Naughton * Sun Microsystems * 2550 Garcia Ave, MS 10-20 * Mountain View, CA 94043 * (415) 336-1080 * */ #include "grasp.h" char *tokens[] = { "notoken", "box", "break", "call", "cfade", "cfree", "cgetbuf", "chgcolor", "circle", "clearscr", "cload", "closegl", "color", "cycle", "data", "databegin", "dataend", "dataskip", "dfree", "dload", "edge", "else", "endlfloat", "endif", "exec", "exit", "ffree", "fgaps", "fload", "float", "fly", "font", "fstyle", "getcolor", "getkey", "gosub", "goto", "if", "ifkey", "ifmem", "ifmouse", "ifvideo", "int", "line", "link", "local", "loop", "mark", "merge", "mode", "mouse", "move", "noise", "note", "offset", "opengl", "out", "palette", "pan", "pfade", "pfree", "pgetbuf", "pload", "pnewbuf", "point", "poke", "pokel", "pokew", "pop", "position", "psave", "psetbuf", "putoff", "putup", "rect", "resetgl", "resetscr", "return", "revpage", "send", "set", "setcolor", "setpage", "setrgb", "setupscr", "split", "spread", "text", "tile", "timer", "tran", "video", "waitkey", "when", "window", "fade", "wait", }; static char * sows(ptr) char *ptr; { int incomment = 0; while (incomment || *ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == ',' || *ptr == ';') { if (*ptr == ';') incomment = 1; else if (*ptr == '\n') break; ptr++; } return ptr; } static char * sowsanl(ptr) char *ptr; { int incomment = 0; while (incomment || *ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == ',' || *ptr == ';' || *ptr == '\n') { if (*ptr == ';') incomment = 1; else if (*ptr == '\n') incomment = 0; ptr++; } return ptr; } static char * copytoken(src, dst) char *src; char *dst; { src = sowsanl(src); if (*src == '"') { src++; while (*src != '"' && *src != '\n' && *src != '\r') *dst++ = *src++; if (*src != '\n') src++; } else while (*src != ' ' && *src != '\t' && *src != '\r' && *src != ',' && *src != '\n' && *src != 26) { if (*src >= 'A' && *src <= 'Z') *dst++ = *src++ + 'a' - 'A'; /* tolower */ else *dst++ = *src++; } *dst = 0; src = sows(src); return src; } static int lookuptoken(ptr) char *ptr; { int i; if (ptr[strlen(ptr) - 1] != ':') for (i = 1; i < NTOKENS; i++) if (!strcmp(ptr, tokens[i])) return i; return NOTOKEN; } static int tokentoint(s, ret) char *s; int *ret; { int i; for (i = 0; i < strlen(s); i++) if (!isdigit(s[i]) && s[i] != '-') return 0; sscanf(s, "%d", ret); return 1; } static void addlabel(ex, s) ExecStruct *ex; char *s; { ex->label[ex->numlabels].string = strdup(s); ex->label[ex->numlabels].ipaddr = ex->numcodes; if (++(ex->numlabels) >= MAXLABELS) error("%s: too many labels!"); } static void addargcount(ex, tokenaddr) ExecStruct *ex; int tokenaddr; { ex->Code[tokenaddr].val.i = ex->numcodes - tokenaddr - 1; } static void addtoken(ex, t) ExecStruct *ex; int t; { ex->Code[ex->numcodes].token = t; if (++(ex->numcodes) >= MAXCODES) error("%s: text file too large. can only have %d tokens\n", MAXCODES); } static void addstring(ex, string) ExecStruct *ex; char *string; { ex->Code[ex->numcodes].val.s = strdup(string); addtoken(ex, STRING); } static void addint(token, arg, ex, string, integer) int token; int arg; ExecStruct *ex; char *string; int integer; { /* * make sure we don't convert a string that happens to parse as a number * such as a filename, or keyname, or video mode, into an integer */ if (((token == CLOAD || token == PLOAD || token == FLOAD) && (arg == 1)) || (token == TEXT && arg == 3) || (token == VIDEO || token == IFKEY)) addstring(ex, string); else { ex->Code[ex->numcodes].val.i = integer; addtoken(ex, INTEGER); } } void parsefile(ex, ptr) ExecStruct *ex; char *ptr; { char buffer[100]; int tokenaddr; ex->numcodes = 0; ex->numlabels = 0; do { int i; int token; ptr = copytoken(ptr, buffer); if (buffer[0] == 0) break; if (buffer[strlen(buffer) - 1] == ':') { buffer[strlen(buffer) - 1] = 0; addlabel(ex, buffer); while (*ptr != '\n' && *ptr != 26) ptr++; } else { int range; int start; token = lookuptoken(buffer); if (token == NOTOKEN) { if (tokentoint(buffer, &i)) addint(token, 0, ex, buffer, i); else addstring(ex, buffer); tokenaddr = -1; } else { tokenaddr = ex->numcodes; addtoken(ex, token); } range = 0; while (*ptr != '\n' && *ptr != 26) { int arg = ex->numcodes - tokenaddr; ptr = copytoken(ptr, buffer); if (range) { if (tokentoint(buffer, &i)) { int val; if (i >= start) for (val = start; val <= i; val++) addint(token, arg, ex, buffer, val); else for (val = start; val >= i; val--) addint(token, arg, ex, buffer, val); range = 0; } else error("%s: parse error on int range\n"); } else { if (buffer[0] == '-' && buffer[1] == 0) { range = 1; } else { if (tokentoint(buffer, &i)) { addint(token, arg, ex, buffer, i); start = i; } else addstring(ex, buffer); } } } if (tokenaddr != -1) addargcount(ex, tokenaddr); } if (*ptr == 26) break; ptr++; } while (*ptr != 26); }