void parserule(Rule *r) { r->qarg = estrdup(expand(nil, r->arg, nil)); switch(r->obj){ case OArg: case OAttr: case OData: case ODst: case OType: case OWdir: case OSrc: if(r->verb==VClient || r->verb==VStart || r->verb==VTo) parseerror("%s not valid verb for object %s", verbs[r->verb], objects[r->obj]); if(r->obj!=OAttr && (r->verb==VAdd || r->verb==VDelete)) parseerror("%s not valid verb for object %s", verbs[r->verb], objects[r->obj]); if(r->verb == VMatches){ r->regex = regcomp(r->qarg); return; } break; case OPlumb: if(r->verb!=VClient && r->verb!=VStart && r->verb!=VTo) parseerror("%s not valid verb for object %s", verbs[r->verb], objects[r->obj]); break; } }
int include(char *s) { char *t, *args[3], buf[128]; int n, fd; if(strncmp(s, "include", 7) != 0) return 0; /* either an include or an error */ n = tokenize(s, args, nelem(args)); if(n < 2) goto Err; if(strcmp(args[0], "include") != 0) goto Err; if(args[1][0] == '#') goto Err; if(n>2 && args[2][0] != '#') goto Err; t = args[1]; fd = open(t, OREAD); if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){ snprint(buf, sizeof buf, "/sys/lib/plumb/%s", t); t = buf; fd = open(t, OREAD); } if(fd < 0) parseerror("can't open %s for inclusion", t); pushinput(t, fd, nil); return 1; Err: parseerror("malformed include statement"); return 0; }
static Cell *maketypevariable(char name[]) { Cell *temp; int k = strlen(name), l; for(l=0; l<k; l++) if(name[l] != '*') parseerror(6); switch(checktypevariable) { case COLLECT: push(typevariables); push(temp = newcell(TYPEVAR)); temp->value = k; make(LIST); typevariables = pop(); return temp; case CHECK: temp = typevariables; while(temp->tag==LIST && temp->left->value != k) temp = temp->right; if(temp->tag != LIST) parseerror(7); return temp->left; default: temp = newcell(TYPEVAR); temp->value = k; return temp; } }
char * read_capability(isieve_t *obj) { lexstate_t state; char *cap = NULL; obj->version = NEW_VERSION; while (yylex(&state,obj->pin)==STRING) { char *attr = state.str; char *val; val = NULL; if (yylex(&state,obj->pin)==' ') { if (yylex(&state,obj->pin)!=STRING) { parseerror("STRING"); } val = state.str; if (yylex(&state,obj->pin)!=EOL) { parseerror("EOL1"); } } if (strcasecmp(attr,"SASL")==0) { free(cap); cap = xstrdupnull(val); } else if (strcasecmp(attr,"SIEVE")==0) { } else if (strcasecmp(attr,"IMPLEMENTATION")==0) { } else if (strcasecmp(attr,"STARTTLS")==0) { /* TODO */ } else if (val && strncmp(val,"SASL=",5)==0) { obj->version = OLD_VERSION; free(cap); cap = xstrdup(val+5); free(val); return cap; } else { /* unknown capability */ } free(val); } if (yylex(&state,obj->pin)!=EOL) { parseerror("EOL2"); } return cap; }
static Cell *extenddefinition(Cell *definition, Cell *c) { if(definition == NULL) parseerror(4); if(definition->tag == ERROR) return c; if(definition->tag == _IF) { definition->right->right = extenddefinition(definition->right->right, c); return definition; } parseerror(4); return definition; }
/********************************************************************* everything between a list bar and a rbrack is transformed in a generator structure: GENERATOR ---- GENERATOR ---- ... NULL | | GENERATOR -- | in case of an ordinary expression the right part is NULL in case of a generator the variable(list) is left and the list-expr(list) right **********************************************************************/ static void parsegenerators(int *count) { Cell *temp; for(;;) { int varcount = 0, exprcount = 0; while(tokentype == SEP) gettoken(); if(tokentype == RBRACK) break; push(temp = newcell(GENERATOR)); temp->value = getPositionCode(); (*count)++; for(;;) { parseexpression(MAXPRIO); varcount++; if(tokentype != COMMA) break; gettoken(); } if(tokentype == GENER || tokentype == ASSIGNMENT) { bool assignment = tokentype == ASSIGNMENT; do { gettoken(); parseexpression(MAXPRIO); exprcount++; if(assignment) { push(template_nil); makeinverse(LIST); } } while(tokentype == COMMA); if(exprcount != varcount) parseerror(32); push(template_nil); while(exprcount-- > 0) makeinverse(LIST); temp->right = pop(); push(template_nil); while(varcount-- > 0) makeinverse(LIST); checkpattern(temp->left = pop()); } else if(varcount > 1) parseerror(31); else temp->left = pop(); } }
bool parseinput(char s[]) { bool result = False; setchecktypevariables(NOCHECK); openinput(s); checkmemlarge(); storefunctionname(""); tokenoffside = 0; gettoken(); if(tokentype == empty) { push(template_nil); return result; } parseexpression(MAXPRIO); if(tokentype == WHERE) { gettoken(); parsewhereclause(); } if(tokentype == COLONS) result = True; else if(tokentype != empty) parseerror(19); closeinput(); initrename(""); settop(renamerec(EXP, top())); return result; }
void regerror(char *msg) { if(parsing){ parsing = 0; parseerror("%s", msg); } error("%s", msg); }
static void makerecordfield(Cell *recordtype, Cell *field, Cell *fieldtype) { char *fieldname = getfunction(field->value)->name; Cell *var = newcell(VARIABLE); var->value = 1; var->left = field; push(fieldtype); push(recordtype); make(APPLY); if(!inserttypeexpr(fieldname, pop())) parseerror(12); push(var); push(var); push(field); make(ALIAS); makecompound(RECORD, 1); push(field); make(APPLY); make(LIST); if(!insert(fieldname, 1, FUNC, pop(), NULL)) parseerror(18); }
static char makehex(char ch) { if(ch >= '0' && ch <= '9') return ch - '0'; else if(ch >= 'A' && ch <= 'F') return ch - 'A' + 10; else if(ch >= 'a' && ch <= 'f') return ch - 'a' + 10; else parseerror(24); return ch; }
static void parsetypesynonym(void) { Cell *head = pop(); setchecktypevariables(COLLECT); push(template_match); for(; head->tag==APPLY; head=head->left) { if(head->right->tag != UNDEFINED && head->right->tag != FUNC) parseerror(9); push(maketypevariable(getfunction(head->right->value)->name)); make(STRUCT); } if(head->tag != UNDEFINED && head->tag != FUNC) parseerror(10); makeconstant(FUNC, head->value); make(STRUCT); setchecktypevariables(CHECK); gettoken(); parsetype(TYPEEXPR); makeinverse(TYPESYNONYM); if(!inserttypeexpr(getfunction(head->value)->name, pop())) parseerror(12); setchecktypevariables(NOCHECK); }
void openfileinput(char filename[]) { if(inputstate != CLOSED && inputstate != FILEINPUT) parseerror(20); if(inputstate == FILEINPUT) { InputFile *i = malloc(sizeof(InputFile)); if(!i) parseerror(21); i->link = current; current = i; i->next = inputFiles; inputFiles = i; } inputstate = FILEINPUT; strncat(strcpy(current->name, ""), filename, stringsize-1); current->linenr = current->columnnr = 0; current->fp = fopen(current->name, "r"); if(current->fp == NULL) Write("\nWARNING: file %s not found\n", current->name); inputbuffer[0] = '\0'; inputputbackcount = 0; }
static void pushinput(char *name, int fd, uchar *str) { Input *in; int depth; depth = 0; for(in=input; in; in=in->next) if(depth++ >= 10) /* prevent deep C stack in plumber and bad include structure */ parseerror("include stack too deep; max 10"); in = emalloc(sizeof(Input)); in->file = estrdup(name); in->next = input; input = in; if(str) in->s = str; else{ in->fd = emalloc(sizeof(Biobuf)); if(Binit(in->fd, fd, OREAD) < 0) parseerror("can't initialize Bio for rules file: %r"); } }
static void parselefthandside(void) { parseapplication(); for(;;) if(tokentype == OPERATOR && strcmp(tokenval, "=") != 0) { parsename(); makeinverse(APPLY); } else if(tokentype == LPAR) { gettoken(); parseexpression(MAXPRIO); makeinverse(APPLY); if(tokentype != RPAR) parseerror(2); gettoken(); } else break; }
static void parseexpressionclause(void) { Cell *definition = makeerror(); if(strcmp(tokenval, "=") != 0) parseerror(5); do { gettoken(); parseexpression(MAXPRIO); if(tokentype == COMMA) { gettoken(); if(strcmp(tokenval, "if") == 0) gettoken(); if(tokentype == OTHERWISE) gettoken(); else { push(makeerror()); makeinverse(_IF); parseexpression(MAXPRIO); make(_IF); } } definition = extenddefinition(definition, pop()); while(tokentype == SEP) gettoken(); if(tokentype == offside) { tokenoffside--; gettoken(); tokenoffside++; } } while(strcmp(tokenval, "=") == 0); push(definition); }
static void parseabstype(void) { Cell *head, *abstype; int globaltokenoffside; gettoken(); parselefthandside(); abstype = pop(); while(abstype->tag == APPLY) abstype = abstype->left; if(abstype->tag != UNDEFINED && abstype->tag != FUNC) parseerror(13); if(!insertabstype(getfunction(abstype->value)->name, abstype)) parseerror(12); if(tokentype != WITH) parseerror(14); globaltokenoffside = tokenoffside; tokenoffside = tokenindent + 1; gettoken(); while(tokentype == IDENTIFIER || tokentype == OPERATOR || tokentype == LPAR) { int temptokenoffside = tokenoffside; parselefthandside(); tokenoffside = tokenindent + 1; if(tokentype != COLONS) parseerror(15); head = pop(); if(head->tag != UNDEFINED && head->tag != FUNC) parseerror(13); gettoken(); parsetype(TYPEEXPR); if(!inserttypeexpr(getfunction(head->value)->name, pop())) parseerror(12); if(!insertabstype(getfunction(head->value)->name, abstype)) parseerror(12); while(tokentype == SEP) gettoken(); tokenoffside = temptokenoffside; if(tokentype == offside) gettoken(); } tokenoffside = globaltokenoffside; if(tokentype == offside) gettoken(); }
static void parseterm(void) { int count; switch(tokentype) { case NUMBER: if(strchr(tokenval, '.') == NULL) makeINT(atol(tokenval)); else makeREAL(atof(tokenval)); gettoken(); break; case IDENTIFIER: parsename(); break; case TYPEID: push(gettemplate(tokenval)); makecompound(STRUCT, 1); gettoken(); break; case CHARACTER: makeconstant(CHAR, tokenval[0]); gettoken(); break; case STRING: buildstring(tokenval); gettoken(); break; case LPAR: gettoken(); if(tokentype == OPERATOR && strcmp(tokenval, "-") != 0) { parsename(); if(tokentype != RPAR) { parseexpression(MAXPRIO); rotatestack(); push(gettemplate("_section")); make(APPLY); make(APPLY); } } else if(tokentype == RPAR) makeconstant(NULLTUPLE, 0); else { parseexpression(MAXPRIO); if(tokentype == COMMA) { count = 1; while(tokentype == COMMA) { gettoken(); parseexpression(MAXPRIO); count++; } makecompound(PAIR, count); } } if(tokentype != RPAR) parseerror(2); gettoken(); break; case LBRACK: parselist(); break; case LACC: count = 0; do { gettoken(); if(tokentype != IDENTIFIER) parseerror(25); push(gettemplate(tokenval)); gettoken(); if(strcmp(tokenval, "=") != 0) parseerror(5); gettoken(); parseexpression(MAXPRIO); makeinverse(ALIAS); count++; } while(tokentype == COMMA); makecompound(RECORD, count); if(tokentype != RACC) parseerror(33); gettoken(); break; default: parseerror(3); } }
static void parsestructdef(void) { char structname[stringsize]; char *headname; int count; Cell *head = pop(); setchecktypevariables(COLLECT); push(template_match); for(; head->tag==APPLY; head=head->left) { if(head->right->tag != UNDEFINED && head->right->tag != FUNC) parseerror(9); push(maketypevariable(getfunction(head->right->value)->name)); make(STRUCT); } if(head->tag != UNDEFINED && head->tag != FUNC) parseerror(10); headname = getfunction(head->value)->name; makeconstant(FUNC, head->value); make(STRUCT); setchecktypevariables(CHECK); gettoken(); head = top(); if(tokentype == LACC) { count = 0; do { gettoken(); if(tokentype != IDENTIFIER) parseerror(25); push(gettemplate(tokenval)); gettoken(); if(tokentype != COLONS) parseerror(15); gettoken(); parsetype(TYPEEXPR); makerecordfield(head, getN(2), getN(1)); makeinverse(TYPEDEF); count++; } while(tokentype == COMMA); makecompound(RECORD, count); makeinverse(TYPEDEF); if(tokentype != RACC) parseerror(33); gettoken(); } else { for(;;) { if(tokentype != TYPEID) parseerror(11); strcpy(structname, tokenval); count = 0; gettoken(); while(tokentype == IDENTIFIER || tokentype == OPERATOR || tokentype == LBRACK || tokentype == LPAR) { parsetype(TYPETERM); count++; } push(head); while(count-- > 0) makeinverse(APPLY); if(!inserttypeexpr(structname, pop())) parseerror(12); if(tokentype != BAR) break; gettoken(); } } if(!inserttypeexpr(headname, pop())) parseerror(12); setchecktypevariables(NOCHECK); }
static void getprimarytoken(void) { static int wildcard = 0; int count = 0, ch; while(isspace(ch=getnext())); tokenindent = current->columnnr; if(tokenindent < tokenoffside) { ungetnext(ch); tokentype = offside; tokenval[count++] = '\0'; return; } if(isdigit(ch)) { tokentype = NUMBER; while(isdigit(ch)) { tokenval[count++] = ch; ch = getnext(); } if(ch == '.') { ch = getnext(); if(isdigit(ch)) tokenval[count++] = '.'; else { ungetnext(ch); ch = '.'; } while(isdigit(ch)) { tokenval[count++] = ch; ch = getnext(); } } tokenval[count++] = '\0'; ungetnext(ch); return; } if(isalpha(ch) || ch == '_') { if('A' <= ch && ch <= 'Z') tokentype = TYPEID; else tokentype = IDENTIFIER; while(isalpha(ch) || isdigit(ch) || ch == '_') { tokenval[count++] = ch; ch = getnext(); } tokenval[count++] = '\0'; ungetnext(ch); if(strcmp(tokenval, "where") == 0) tokentype = WHERE; if(strcmp(tokenval, "otherwise") == 0) tokentype = OTHERWISE; if(strcmp(tokenval, "abstype") == 0) tokentype = ABSTYPE; if(strcmp(tokenval, "with") == 0) tokentype = WITH; if(strcmp(tokenval, "generic") == 0) tokentype = GENERIC; if(strcmp(tokenval, "True") == 0) tokentype = IDENTIFIER; if(strcmp(tokenval, "False") == 0) tokentype = IDENTIFIER; if(strcmp(tokenval, "Nil") == 0) tokentype = IDENTIFIER; if(strcmp(tokenval, "_") == 0) sprintf(tokenval, "_??_%d", wildcard++); return; } if(ch == '$') { ch = getnext(); if(('a' <= ch && ch <= 'z') || ch == '_') { tokentype = OPERATOR; while(isalpha(ch) || isdigit(ch) || ch == '_') { tokenval[count++] = ch; ch = getnext(); } tokenval[count++] = '\0'; ungetnext(ch); } else parseerror(25); return; } if(ch == '\'') { tokentype = CHARACTER; ch = getnext(); if(!isprint(ch)) parseerror(26); if(ch == '\\') { ch = getnext(); switch(ch) { case 'a': ch = '\a'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case 'v': ch = '\v'; break; case 'e': ch = 27; break; case 'x': ch = 16 * makehex(getnext()) + makehex(getnext()); break; } } tokenval[count++] = ch; ch = getnext(); if(ch != '\'') parseerror(27); tokenval[count++] = '\0'; return; } if(ch == '\"') { tokentype = STRING; ch = getnext(); while(isprint(ch) && ch != '\"') { if(ch == '\\') { ch = getnext(); switch(ch) { case 'a': ch = '\a'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case 'v': ch = '\v'; break; case 'e': ch = 27; break; case 'x': ch = 16 * makehex(getnext()) + makehex(getnext()); break; } } tokenval[count++] = ch; ch = getnext(); } if(ch != '\"') parseerror(28); tokenval[count++] = '\0'; return; } if(ch == '(') { tokentype = LPAR; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == ')') { tokentype = RPAR; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == ';') { tokentype = SEP; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == ',') { tokentype = COMMA; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == '[') { tokentype = LBRACK; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == ']') { tokentype = RBRACK; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == '{') { tokentype = LACC; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == '}') { tokentype = RACC; tokenval[count++] = ch; tokenval[count++] = '\0'; return; } if(ch == '|') { tokentype = BAR; tokenval[count++] = ch; ch = getnext(); if(ch == '|') { while(ch != '\n') { ch = getnext(); if(ch == EOF) { tokentype = empty; tokenval[count++] = '\0'; return; } } gettoken(); return; } tokenval[count++] = '\0'; ungetnext(ch); return; } if(ch == '.') { tokentype = OPERATOR; tokenval[count++] = ch; ch = getnext(); if(ch == '.') { tokentype = POINTS; tokenval[count++] = ch; ch = getnext(); } tokenval[count++] = '\0'; ungetnext(ch); return; } if(ch == '/') { ch = getnext(); if(ch == '*') { int comments = 1; while(comments > 0) { ch = getnext(); if(ch == EOF) parseerror(29); else if(ch == '/') { ch = getnext(); if(ch == '*') comments++; else ungetnext(ch); } else if(ch == '*') { ch = getnext(); if(ch == '/') comments--; else ungetnext(ch); } } gettoken(); return; } tokentype = OPERATOR; tokenval[count++] = '/'; while(ispunct(ch) && ch!='(' && ch!=')' && ch!='[' && ch!=']' && ch!='{' && ch!='}' && ch!='|' && ch!=';' && ch!=',' && ch!='\'' && ch!='\"' && ch!='.' && ch!='_') { tokenval[count++] = ch; ch = getnext(); } tokenval[count++] = '\0'; ungetnext(ch); return; } if(ispunct(ch)) { tokentype = OPERATOR; while(ispunct(ch) && ch!='(' && ch!=')' && ch!='[' && ch!=']' && ch!='{' && ch!='}' && ch!='|' && ch!=';' && ch!=',' && ch!='\'' && ch!='\"' && ch!='.' && ch!='_') { tokenval[count++] = ch; ch = getnext(); } tokenval[count++] = '\0'; ungetnext(ch); if (strcmp(tokenval, "<-") == 0) tokentype = GENER; else if(strcmp(tokenval, ":=") == 0) tokentype = ASSIGNMENT; else if(strcmp(tokenval, "->") == 0) tokentype = ARROW; else if(strcmp(tokenval, "::") == 0) tokentype = COLONS; else if(strcmp(tokenval, "::=") == 0) tokentype = DEF; else if(strcmp(tokenval, "==") == 0) tokentype = SYN; else if(strcmp(tokenval, "~") == 0) tokentype = IDENTIFIER; else if(strcmp(tokenval, "#") == 0) tokentype = IDENTIFIER; return; } tokentype = empty; tokenval[count++] = '\0'; ungetnext(ch); }
/*********************************************************************** renamerec renames variables (function argument patterns, patterns of simple local definitions, names of local functions, patterns of generators of listcomprehensions) every variable is replaced by a cell of type VARIABLE with a unique value moreover local definitions of simple where clauses are lifted upward local definitions of the form (x = y) are removed ************************************************************************/ static Cell *renamerec(ExpressionType exprtype, Cell *c) { Cell *renamelist = template_nil, *temp, *head; if(c == NULL) return NULL; switch(exprtype) { case FUN: c->right = renamerec(EXP, c->right); for(head=c->left; head->tag==APPLY; head=head->left) renamelist = appendrenamelistrec(renamelist, True, head->right); c = replacerenamelist(renamelist, c); break; case EXP: if(c->tag == GENERATOR) { for(head=c->right; head->tag==GENERATOR && head->left->right==NULL; head=head->right) head->left->left = renamerec(EXP, head->left->left); if(head->tag == GENERATOR) { temp = c->right; c->right = head->right; c = renamerec(EXP, c); c->right = temp; head->left->right = renamerec(EXP, head->left->right); renamelist = appendrenamelistrec(renamelist, True, head->left->left); c->left = replacerenamelist(renamelist, c->left); head->right = replacerenamelist(renamelist, head->right); head->left->left = replacerenamelist(renamelist, head->left->left); } else c->left = renamerec(EXP, c->left); } else if(c->tag == LETREC) { c->right = renamerec(EXP, c->right); for(temp=c->left; temp->tag==LIST; temp=temp->right) { head = temp->left = renamerec(FUN, temp->left); if(head->left->tag == APPLY) { while(head->left->tag==APPLY) head = head->left; renamelist = appendrenamelistrec(renamelist, False, head->left); } else renamelist = appendrenamelistrec(renamelist, True, head->left); } c = replacerenamelist(renamelist, c); for(temp=c->left; temp->tag==LIST; temp=temp->right) { head = temp->left; if(head->left->tag != APPLY && head->right->tag == LETREC) { Cell *last = temp; while(last->right->tag == LIST) last = last->right; last->right = head->right->left; head->right = head->right->right; } if(head->left->tag == VARIABLE && head->right->tag == VARIABLE) { Cell *directors = appenddirectors(template_nil, head->right, head->left, LAZYDIRECTOR); if(head->left->value == head->right->value) parseerror(16); if(temp == c->left) c->left = temp->right; else { Cell *before = c->left; while(before->right != temp) before = before->right; before->right = temp->right; } c = replacedirectors(directors, c); } } } else if(c->tag == LAMBDA) { c->right = renamerec(EXP, c->right); renamelist = appendrenamelistrec(renamelist, True, c->left); c = replacerenamelist(renamelist, c); } else if(c->tag > compositetag) { c->left = renamerec(EXP, c->left); c->right = renamerec(EXP, c->right); } break; } return c; }
static void ungetnext(int ch) { if(inputputbackcount >= INPUTPUTBACKSIZE) parseerror(23); inputputback[inputputbackcount++] = ch; (current->columnnr)--; }
static void parsedefinition(bool globallevel) { Cell *head; int globaltokenoffside = tokenindent, posCode; bool generic = False; if(tokentype == ABSTYPE && globallevel) { parseabstype(); while(tokentype == SEP) gettoken(); return; } else if(tokentype == GENERIC && globallevel) { generic = True; gettoken(); } parselefthandside(); posCode = getPositionCode(); tokenoffside = tokenindent + 1; if(tokentype == COLONS && globallevel) { head = pop(); if(head->tag != UNDEFINED && head->tag != FUNC) parseerror(13); gettoken(); parsetype(TYPEEXPR); if(!inserttypeexpr(getfunction(head->value)->name, pop())) parseerror(12); getfunction(head->value)->generic = generic; while(tokentype == SEP) gettoken(); } else if(tokentype == DEF && globallevel) { parsestructdef(); while(tokentype == SEP) gettoken(); } else if(tokentype == SYN && globallevel) { parsetypesynonym(); while(tokentype == SEP) gettoken(); } else { head = top(); if(head->tag == APPLY || globallevel) { for(; head->tag==APPLY; head=head->left) checkpattern(head->right); if(head->tag != UNDEFINED && head->tag != FUNC) parseerror(17); if(globallevel) storefunctionname(getfunction(head->value)->name); } else checkpattern(head); parseexpressionclause(); if(tokentype == WHERE) { gettoken(); parsewhereclause(); } else if(tokentype == offside) { tokenoffside = globaltokenoffside; gettoken(); if(tokentype == WHERE) { tokenoffside = tokenindent + 1; gettoken(); parsewhereclause(); } } makeinverse(LIST); top()->value = posCode; if(globallevel) { Cell *def = pop(); int argcount = 0; char *funname; head = def; for(head=head->left; head->tag==APPLY; head=head->left) argcount++; funname = getfunction(head->value)->name; initrename(funname); def = renamerec(FUN, def); if(!insert(funname, argcount, FUNC, def, NULL)) parseerror(18); } } }
static void parselist(void) { int count = 0; gettoken(); if(tokentype != RBRACK) { parseexpression(MAXPRIO); count++; } while(tokentype == COMMA) { gettoken(); parseexpression(MAXPRIO); count++; } if(tokentype == RBRACK) { push(template_nil); while(count-->0) makeinverse(LIST); } else if(tokentype == BAR && count >= 1) { push(template_nil); while(count-->0) makeinverse(LIST); count = 1; gettoken(); parsegenerators(&count); push(template_nil); while(count-->0) makeinverse(GENERATOR); } else if(tokentype == POINTS && count == 1) { gettoken(); if(tokentype == RBRACK) { push(gettemplate("nats")); make(APPLY); } else { push(gettemplate("nat")); make(APPLY); parseexpression(MAXPRIO); makeinverse(APPLY); } } else if(tokentype == POINTS && count == 2) { gettoken(); if(tokentype == RBRACK) { rotatestack(); push(gettemplate("gennats")); make(APPLY); make(APPLY); } else { rotatestack(); push(gettemplate("gennat")); make(APPLY); make(APPLY); parseexpression(MAXPRIO); makeinverse(APPLY); } } if(tokentype != RBRACK) parseerror(1); gettoken(); }
Rule* readrule(int *eof) { Rule *rp; char *line, *p; char *word; Top: line = getline(); if(line == nil){ /* * if input is from string, and bytes remain (input->end is within string), * morerules() will pop input and save remaining data. otherwise pop * the stack here, and if there's more input, keep reading. */ if((input!=nil && input->end==nil) && popinput()) goto Top; *eof = 1; return nil; } input->lineno++; for(p=line; *p==' ' || *p=='\t'; p++) ; if(*p=='\0' || *p=='#') /* empty or comment line */ return nil; if(include(p)) goto Top; if(assignment(p)) return nil; rp = emalloc(sizeof(Rule)); /* object */ for(word=p; *p!=' ' && *p!='\t'; p++) if(*p == '\0') parseerror("malformed rule"); *p++ = '\0'; rp->obj = lookup(word, objects); if(rp->obj < 0){ if(strcmp(word, "kind") == 0) /* backwards compatibility */ rp->obj = OType; else parseerror("unknown object %s", word); } /* verb */ while(*p==' ' || *p=='\t') p++; for(word=p; *p!=' ' && *p!='\t'; p++) if(*p == '\0') parseerror("malformed rule"); *p++ = '\0'; rp->verb = lookup(word, verbs); if(rp->verb < 0) parseerror("unknown verb %s", word); /* argument */ while(*p==' ' || *p=='\t') p++; if(*p == '\0') parseerror("malformed rule"); rp->arg = estrdup(p); parserule(rp); return rp; }
Ruleset* readruleset(void) { Ruleset *rs; Rule *r; int eof, inrule, i, ncmd; Again: eof = 0; rs = emalloc(sizeof(Ruleset)); rs->pat = emalloc(sizeof(Rule*)); rs->act = emalloc(sizeof(Rule*)); inrule = 0; ncmd = 0; for(;;){ r = readrule(&eof); if(eof) break; if(r==nil){ if(inrule) break; continue; } inrule = 1; switch(r->obj){ case OArg: case OAttr: case OData: case ODst: case OType: case OWdir: case OSrc: rs->npat++; rs->pat = erealloc(rs->pat, (rs->npat+1)*sizeof(Rule*)); rs->pat[rs->npat-1] = r; rs->pat[rs->npat] = nil; break; case OPlumb: rs->nact++; rs->act = erealloc(rs->act, (rs->nact+1)*sizeof(Rule*)); rs->act[rs->nact-1] = r; rs->act[rs->nact] = nil; if(r->verb == VTo){ if(rs->npat>0 && rs->port != nil) /* npat==0 implies port declaration */ parseerror("too many ports"); if(lookup(r->qarg, badports) >= 0) parseerror("illegal port name %s", r->qarg); if(rs->port) free(rs->port); rs->port = estrdup(r->qarg); }else ncmd++; /* start or client rule */ break; } } if(ncmd > 1){ freeruleset(rs); parseerror("ruleset has more than one client or start action"); } if(rs->npat>0 && rs->nact>0) return rs; if(rs->npat==0 && rs->nact==0){ freeruleset(rs); return nil; } if(rs->nact==0 || rs->port==nil){ freeruleset(rs); parseerror("ruleset must have patterns and actions"); return nil; } /* declare ports */ for(i=0; i<rs->nact; i++) if(rs->act[i]->verb != VTo){ freeruleset(rs); parseerror("ruleset must have actions"); return nil; } for(i=0; i<rs->nact; i++) addport(rs->act[i]->qarg); freeruleset(rs); goto Again; }
static bool preprocess(void) { int globaltokenoffside = tokenoffside; char *s = inputbuffer; if(strncmp(s, "####", 4) == 0) { char *t = inputbuffer; int k = 0; s = inputbuffer+4; while(*s) { *t = 0 < *s && *s <= 26 ? *s : *s - 1 - k % 10; t++; s++; k++; } *t = '\0'; } s = inputbuffer; while(isspace(*s)) s++; if(strncmp(s, "#import", 7) == 0) { InputFile *i = inputFiles; tokenoffside = current->columnnr = s-inputbuffer+7; gettoken(); if(tokentype != STRING) parseerror(22); tokenoffside = globaltokenoffside; inputbuffer[0] = '\0'; current->columnnr = 0; while(i->next && strcmp(tokenval, i->name) != 0) i = i->next; if(!(i->next)) openfileinput(tokenval); return True; } else if(strncmp(s, "#synonym", 8) == 0) { Synonym *syn = malloc(sizeof(Synonym)); if(syn == NULL) systemerror(4); syn->next = synonyms; synonyms = syn; tokenoffside = current->columnnr = s-inputbuffer+8; getprimarytoken(); strcpy(syn->synonym, tokenval); gettoken(); strcpy(syn->name, tokenval); syn->type = tokentype; tokenoffside = globaltokenoffside; inputbuffer[0] = '\0'; current->columnnr = 0; return True; } else if(strncmp(s, "#operator", 9) == 0) { Assoc assoc; int prio; tokenoffside = current->columnnr = s-inputbuffer+9; gettoken(); if(strcmp(tokenval, "r") == 0) assoc = Right; else if(strcmp(tokenval, "l") == 0) assoc = Left; else parseerror(34); gettoken(); if(tokentype != NUMBER) parseerror(34); prio = atoi(tokenval); gettoken(); if(tokentype != OPERATOR) parseerror(34); insertoperator(tokenval, prio, assoc); tokenoffside = globaltokenoffside; inputbuffer[0] = '\0'; current->columnnr = 0; return True; } else return False; }
int handle_response(int res,int version,struct protstream *pin, char **refer_to, char **errstr) { lexstate_t state; int r = 0; *refer_to = NULL; if (res == -1) parseerror("lost connection"); if ((res!=TOKEN_OK) && (res!=TOKEN_NO) && (res!=TOKEN_BYE)) parseerror("ATOM"); if(res == TOKEN_BYE) { if (yylex(&state, pin)!=' ') parseerror("expected space"); res = yylex(&state, pin); /* additional error response */ if (res == '(') { /* '(' string [SP string] ')' */ /* we only support the REFERRAL response with BYE */ if (yylex(&state, pin)==TOKEN_REFERRAL) { if (yylex(&state, pin)!=' ') parseerror("expected space"); if (yylex(&state, pin)!=STRING) parseerror("expected string"); *refer_to = state.str; if (yylex(&state, pin)!=')') parseerror("expected RPAREN"); } else { res = 0; while(res != ')' && res != -1) { res = yylex(&state, pin); } if(res != ')') { parseerror("expected RPAREN"); } } res = yylex(&state, pin); if (res == ' ') res = yylex(&state, pin); } if (res != STRING && res != EOL) parseerror("expected string2"); if (errstr) *errstr = state.str; r = -2; } else if (res==TOKEN_NO) { if (yylex(&state, pin)!=' ') parseerror("expected space"); res = yylex(&state, pin); /* additional error response */ if (res == '(') { /* '(' string [SP string] ')' */ res = 0; while(res != ')' && res != -1) { res = yylex(&state, pin); } if(res != ')') { parseerror("expected RPAREN"); } res = yylex(&state, pin); if (res == ' ') res = yylex(&state, pin); } if (res != STRING) parseerror("expected string"); if (errstr) *errstr = state.str; r = -1; } else { /* ok */ int res; /* SASL response */ res = yylex(&state, pin); if(res == ' ') { if (yylex(&state, pin) != '(') parseerror("expected LPAREN"); if (yylex(&state, pin)==TOKEN_SASL) { if (yylex(&state, pin)!=' ') parseerror("expected space"); if (yylex(&state, pin)!=STRING) parseerror("expected string"); *refer_to = xstrdup(state.str); if (yylex(&state, pin)!=')') parseerror("expected RPAREN"); } else { parseerror("unexpected response code with OK response"); } } else if (version != OLD_VERSION && res == EOL) { return r; } /* old version of protocol had strings with ok responses too */ if (version == OLD_VERSION) { if (res !=' ') parseerror("expected sp"); if (yylex(&state, pin)!=STRING) parseerror("expected string"); } } if (yylex(&state, pin)!=EOL) parseerror("expected EOL"); return r; }
static void parsetype(TypeType typetype) { switch(tokentype) { case IDENTIFIER: if(strcmp(tokenval, "num") == 0) { push(newcell(INT)); gettoken(); } else if(strcmp(tokenval, "char") == 0) { push(newcell(CHAR)); gettoken(); } else if(strcmp(tokenval, "bool") == 0) { push(newcell(BOOLEAN)); gettoken(); } else { int count = 1; push(gettemplate(tokenval)); gettoken(); if(typetype == TYPEEXPR) while(tokentype == IDENTIFIER || tokentype == OPERATOR || tokentype == LBRACK || tokentype == LPAR) { parsetype(TYPETERM); count++; } makecompound(STRUCT, count); } break; case OPERATOR: push(maketypevariable(tokenval)); gettoken(); break; case LPAR: gettoken(); if(tokentype == RPAR) push(newcell(NULLTUPLE)); else { parsetype(TYPEEXPR); if(tokentype == COMMA) { int count = 1; while(tokentype == COMMA) { gettoken(); parsetype(TYPEEXPR); count++; } makecompound(PAIR, count); } } if(tokentype != RPAR) parseerror(2); gettoken(); break; case LBRACK: gettoken(); parsetype(TYPEEXPR); push(template_nil); makeinverse(LIST); if(tokentype != RBRACK) parseerror(1); gettoken(); break; default: parseerror(8); } if(typetype == TYPEEXPR && tokentype == ARROW) { gettoken(); parsetype(TYPEEXPR); makeinverse(APPLY); } }