/ * phoneman -- telephone manager A.J. Fisher March 1996 parse -- parse script */ #include <stdio.h> #include "phoneman.h" #define REC_DURATION 40 /* dflt max record duration is 40 secs */ static FILE *scriptfile; static int linenum, ch; static bool anyerrors; static symbol symb; static char *item; struct resvdwd { char *wd; symbol sy; }; static resvdwd resvdwds[] = { { "chdir", s_chdir }, { "error", s_error }, { "print", s_print }, { "speak", s_speak }, { "record", s_record }, { "seize", s_seize }, { "release", s_release }, { "wtring", s_wtring }, { "sleep", s_sleep }, { "loop", s_loop }, { "accept", s_accept }, { "fax", s_fax }, { "run", s_run }, { "connect", s_connect }, { "end", s_end }, { NULL }, /* stopper */ }; static pnode *parsesequence(), *parsestmt(); static void checkfor(symbol), nextsymb(), string(); static void identifier(); static char *substp(char*), *symbformat(symbol), *charformat(int); static void scripterror(char*, word = 0, word = 0); static void nextchar(); global pnode *parsescript(char *fn) { scriptfile = fopen(fn, "r"); if (scriptfile == NULL) giveup("can't open %s", fn); anyerrors = false; linenum = 0; ch = '\n'; item = ""; /* always points to a valid string */ nextchar(); nextsymb(); while (symb == s_chdir) /* do "chdir" at parse time, so file access checks work */ { nextsymb(); int code = chdir(item); unless (code == 0) scripterror("chdir to %s failed", item); checkfor(s_string); } pnode *x = parsesequence(); checkfor(s_eof); fclose(scriptfile); if (anyerrors) exit(2); return x; } static pnode *parsesequence() { pnode *x = NULL; until (symb == s_eof || symb == s_end || symb == s_number) { pnode *y = parsestmt(); x = (x == NULL) ? y : new pnode(s_seq, x, y); } return x; } static pnode *parsestmt() { top: switch (symb) { default: scripterror("%s found where statement expected", symbformat(symb)); nextsymb(); goto top; case s_error: nextsymb(); return new pnode(s_accept); /* "error" is signalled as empty "accept" */ case s_print: { char *s = NULL; nextsymb(); if (symb == s_string) { s = item; nextsymb(); } return new pnode(s_print, s); } case s_speak: case s_record: { symbol sy = symb; nextsymb(); char *s = item; if (sy == s_speak) { unless (exists(s)) scripterror("can't access file %s", s); } checkfor(s_string); pnode *x = new pnode(sy, s); if (symb == s_number && ch != ':') /* careful! */ { x -> num = atoi(item); nextsymb(); } else x -> num = (sy == s_speak) ? 1 : REC_DURATION; return x; } case s_seize: case s_release: case s_wtring: { symbol sy = symb; nextsymb(); return new pnode(sy); } case s_sleep: { nextsymb(); pnode *x = new pnode(s_sleep, atoi(item)); checkfor(s_number); return x; } case s_loop: { nextsymb(); pnode *x = parsesequence(); checkfor(s_end); if (x == NULL) scripterror("body of loop is empty"); return new pnode(s_loop, x); } case s_accept: { nextsymb(); pnode *x = NULL; int maxd = 0; while (symb == s_number || symb == s_fax) { char *num = (symb == s_number) ? item : "f"; int nd = strlen(num); if (nd > maxd) maxd = nd; nextsymb(); checkfor(s_colon); pnode *y = new pnode(s_branch, parsesequence()); y -> str1 = num; x = (x == NULL) ? y : new pnode(s_or, x, y); } checkfor(s_end); x = new pnode(s_accept, x); x -> num = maxd; return x; } case s_run: { nextsymb(); char *s = item; checkfor(s_string); pnode *x = new pnode(s_run, s); if (symb == s_redirect) { nextsymb(); x -> str2 = item; checkfor(s_string); } return x; } case s_connect: { nextsymb(); char *s = item; checkfor(s_string); return new pnode(s_connect, s); } } } static void checkfor(symbol sy) { if (symb == sy) { unless (symb == s_eof) nextsymb(); } else scripterror("%s found where %s expected", symbformat(symb), symbformat(sy)); } static void nextsymb() { top: switch (ch) { default: scripterror("ilgl char %s", charformat(ch)); nextchar(); goto top; case ' ': case '\t': case '\n': nextchar(); goto top; case '/': do nextchar(); until (ch == '\n' || ch == EOF); goto top; case ':': nextchar(); symb = s_colon; break; case EOF: symb = s_eof; break; case '>': nextchar(); symb = s_redirect; break; case '\'': case '"': string(); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': identifier(); break; } } static void string() { char str[MAXSTR+1]; int n = 0; int qu = ch; nextchar(); until (ch == qu || ch == '\n' || ch == EOF || n >= MAXSTR) { str[n++] = ch; nextchar(); } if (ch == qu) nextchar(); else scripterror("%s found where %s expected", charformat(ch), charformat(qu)); str[n] = '\0'; symb = s_string; item = substp(copystr(str)); } static void identifier() { char vec[MAXSTR+1]; int n = 0; bool numok = true; while (n < MAXSTR && ((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9'))) { vec[n++] = ch; unless ((ch >= '0' && ch <= '9') || (ch == 'x')) numok = false; nextchar(); } vec[n] = '\0'; int k = 0; until (resvdwds[k].wd == NULL || seq(resvdwds[k].wd, vec)) k++; if (resvdwds[k].wd != NULL) symb = resvdwds[k].sy; else { unless (numok) scripterror("illegal number or unknown reserved word: %s", vec); symb = s_number; item = substp(copystr(vec)); } } static char *substp(char *v1) { /* subst for all vars except $num, $uid, $time, which are left until obey time */ return substparams(v1, scripterror, NULL, NULL, NULL); } static char *symbformat(symbol sy) { switch (sy) { default: return "???"; case s_number: return "<number>"; case s_string: return "<string>"; case s_eof: return "<end of file>"; case s_redirect: return "'>'"; case s_colon: return "':'"; case s_chdir: return "'chdir'"; case s_print: return "'print'"; case s_speak: return "'speak'"; case s_record: return "'record'"; case s_seize: return "'seize'"; case s_release: return "'release'"; case s_wtring: return "'wtring'"; case s_sleep: return "'sleep'"; case s_loop: return "'loop'"; case s_accept: return "'accept'"; case s_fax: return "'fax'"; case s_run: return "'run'"; case s_connect: return "'connect'"; case s_end: return "'end'"; } } static char *charformat(int c) { char *str = new char[5]; sprintf(str, (c < 0) ? "EOF" : (c >= 040 && c <= 0176) ? "'%c'" : (c <= 0377) ? "\\%03o" : "???", c); return str; } static void scripterror(char *msg, word p1, word p2) { fprintf(stderr, "phoneman: line %d: ", linenum); fprintf(stderr, msg, p1, p2); putc('\n', stderr); anyerrors = true; } static void nextchar() { if (ch == '\n') linenum++; ch = getc(scriptfile); }
file: /Techref/uk/ac/york/cs/www-users/http/~fisher/software/voicemail/phoneman/current/parse.C, 7KB, , updated: 2000/4/4 11:11, local time: 2025/2/11 11:56,
3.144.108.220:LOG IN
|
©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://sxlist.com/techref/uk/ac/york/cs/www-users/http/~fisher/software/voicemail/phoneman/current/parse.C"> uk ac york cs www-users http ~fisher software voicemail phoneman current parse</A> |
Did you find what you needed? |
Welcome to sxlist.com!sales, advertizing, & kind contributors just like you! Please don't rip/copy (here's why Copies of the site on CD are available at minimal cost. |
Welcome to sxlist.com! |
.