static OBJECT load(FULL_CHAR *xstr, unsigned xpre, BOOLEAN xleft, BOOLEAN xright, BOOLEAN xindef, unsigned char xprec) { OBJECT s; s = InsertSym(xstr, LOCAL, no_fpos, xprec, xindef, FALSE, xpre, StartSym, nilobj); if( xleft ) InsertSym( AsciiToFull("pa"), LPAR, no_fpos, DEFAULT_PREC, FALSE, FALSE, 0, s, nilobj); if( xright ) InsertSym( AsciiToFull("pb"), RPAR, no_fpos, DEFAULT_PREC, FALSE, FALSE, 0, s, nilobj); if( xleft && xright && xpre != PLUS && xpre != MINUS ) right_assoc(s) = TRUE; return s; } /* end load */
OBJECT InsertSym(FULL_CHAR *str, unsigned char xtype, FILE_POS *xfpos, unsigned char xprecedence, BOOLEAN xindefinite, BOOLEAN xrecursive, unsigned xpredefined, OBJECT xenclosing, OBJECT xbody) { register int sum, rlen; register unsigned char *x; OBJECT p, q, s, tmp, link, entry, plink; int len; debug3(DST, DD, "InsertSym( %s, %s, in %s )", Image(xtype), str, SymName(xenclosing)); if( !LexLegalName(str) ) Error(29, 3, "invalid symbol name %s", WARN, xfpos, str); New(s, xtype); FposCopy(fpos(s), *xfpos); has_body(s) = FALSE; filter(s) = nilobj; use_invocation(s) = nilobj; imports(s) = nilobj; imports_encl(s) = FALSE; right_assoc(s) = TRUE; precedence(s) = xprecedence; indefinite(s) = xindefinite; recursive(s) = xrecursive; predefined(s) = xpredefined; enclosing(s) = xenclosing; sym_body(s) = xbody; base_uses(s) = nilobj; uses(s) = nilobj; marker(s) = nilobj; cross_sym(s) = nilobj; is_extern_target(s) = FALSE; uses_extern_target(s)= FALSE; visible(s) = FALSE; uses_galley(s) = FALSE; horiz_galley(s) = ROWM; has_compulsory(s) = 0; is_compulsory(s) = FALSE; uses_count(s) = 0; dirty(s) = FALSE; if( enclosing(s) != nilobj && type(enclosing(s)) == NPAR ) dirty(s) = dirty(enclosing(s)) = TRUE; has_par(s) = FALSE; has_lpar(s) = FALSE; has_rpar(s) = FALSE; if( is_par(type(s)) ) has_par(enclosing(s)) = TRUE; if( type(s) == LPAR ) has_lpar(enclosing(s)) = TRUE; if( type(s) == RPAR ) has_rpar(enclosing(s)) = TRUE; /* assign a code letter between a and z to any NPAR symbol */ if( type(s) == NPAR ) { if( LastDown(enclosing(s)) != enclosing(s) ) { Child(tmp, LastDown(enclosing(s))); if( type(tmp) == NPAR ) { if( npar_code(tmp) == 'z' || npar_code(tmp) == ' ' ) npar_code(s) = ' '; else npar_code(s) = npar_code(tmp)+1; } else npar_code(s) = 'a'; } else npar_code(s) = 'a'; } has_target(s) = FALSE; force_target(s) = FALSE; if( !StringEqual(str, KW_TARGET) ) is_target(s) = FALSE; else { is_target(s) = has_target(enclosing(s)) = TRUE; /* if @Target is found after @Key, take note of external target */ if( has_key(enclosing(s)) && xbody != nilobj && is_cross(type(xbody)) ) { if( LastDown(xbody) != Down(xbody) ) { OBJECT sym; Child(sym, Down(xbody)); if( type(sym) == CLOSURE ) { is_extern_target(actual(sym)) = TRUE; uses_extern_target(actual(sym)) = TRUE; } } } } has_tag(s) = is_tag(s) = FALSE; has_key(s) = is_key(s) = FALSE; has_optimize(s) = is_optimize(s) = FALSE; has_merge(s) = is_merge(s) = FALSE; has_enclose(s) = is_enclose(s) = FALSE; if( enclosing(s) != nilobj && type(enclosing(s)) == LOCAL ) { if( StringEqual(str, KW_TAG) ) is_tag(s) = has_tag(enclosing(s)) = dirty(enclosing(s)) = TRUE; if( StringEqual(str, KW_OPTIMIZE) ) is_optimize(s) = has_optimize(enclosing(s)) = TRUE; if( StringEqual(str, KW_KEY) ) { is_key(s) = has_key(enclosing(s)) = dirty(enclosing(s)) = TRUE; /* if @Key is found after @Target, take note of external target */ for( link=Down(enclosing(s)); link!=enclosing(s); link=NextDown(link) ) { Child(p, link); if( is_target(p) && sym_body(p)!=nilobj && is_cross(type(sym_body(p))) ) { OBJECT sym; Child(sym, Down(sym_body(p))); if( type(sym) == CLOSURE ) { is_extern_target(actual(sym)) = TRUE; uses_extern_target(actual(sym)) = TRUE; } } } } if( StringEqual(str, KW_MERGE) ) is_merge(s) = has_merge(enclosing(s)) = TRUE; if( StringEqual(str, KW_ENCLOSE) ) is_enclose(s) = has_enclose(enclosing(s)) = TRUE; } if( StringEqual(str, KW_FILTER) ) { if( type(s) != LOCAL || enclosing(s) == StartSym ) Error(29, 4, "%s must be a local definition", WARN, &fpos(s), str); else if( !has_rpar(enclosing(s)) ) Error(29, 14, "%s must lie within a symbol with a right parameter", WARN, &fpos(s), KW_FILTER); else { filter(enclosing(s)) = s; precedence(enclosing(s)) = FILTER_PREC; } } if( type(s) == RPAR && has_body(enclosing(s)) && (is_tag(s) || is_key(s) || is_optimize(s)) ) Error(29, 5, "a body parameter may not be named %s", WARN, &fpos(s), str); if( type(s) == RPAR && has_target(enclosing(s)) && (is_tag(s) || is_key(s) || is_optimize(s)) ) Error(29, 6, "the right parameter of a galley may not be called %s", WARN, &fpos(s), str); len = StringLength(str); hash(str, len, sum); ifdebug(DST, D, sym_spread[sum]++; sym_count++); entry = (OBJECT) &symtab[sum]; for( plink = Down(entry); plink != entry; plink = NextDown(plink) ) { Child(p, plink); if( length(p) == len && StringEqual(str, string(p)) ) { for( link = Down(p); link != p; link = NextDown(link) ) { Child(q, link); if( enclosing(s) == enclosing(q) ) { Error(29, 7, "symbol %s previously defined at%s", WARN, &fpos(s), str, EchoFilePos(&fpos(q)) ); if( AltErrorFormat ) { Error(29, 13, "symbol %s previously defined here", WARN, &fpos(q), str); } break; } } goto wrapup; } } /* need a new OBJECT as well as s */ NewWord(p, WORD, len, xfpos); length(p) = len; StringCopy(string(p), str); Link(entry, p); wrapup: Link(p, s); if( enclosing(s) != nilobj ) Link(enclosing(s), s); debug2(DST, DD, "InsertSym Link(%s, %s) and returning.", SymName(enclosing(s)), SymName(s)); return s; } /* end InsertSym */
void ReadDefinitions(OBJECT *token, OBJECT encl, unsigned char res_type) { OBJECT t, res, res_target, export_list, import_list, link, y, z; OBJECT curr_encl; BOOLEAN compulsory_par, has_import_encl; t = *token; while( res_type==LOCAL || is_string(t, KW_NAMED) || is_string(t, KW_IMPORT) ) { curr_encl = encl; if( is_string(t, KW_LANGDEF) ) { ReadLangDef(encl); t = LexGetToken(); continue; /* next definition */ } else if( type(t) == PREPEND || type(t) == SYS_PREPEND ) { ReadPrependDef(type(t), encl); Dispose(t); t = LexGetToken(); continue; /* next definition */ } else if( type(t) == INCG_REPEATED || type(t) == SINCG_REPEATED ) { ReadIncGRepeatedDef(type(t), encl); Dispose(t); t = LexGetToken(); continue; /* next definition */ } else if( type(t) == DATABASE || type(t) == SYS_DATABASE ) { ReadDatabaseDef(type(t), encl); Dispose(t); t = LexGetToken(); continue; /* next definition */ } if( !is_string(t, KW_DEF) && !is_string(t, KW_MACRO) && !is_string(t, KW_NAMED) && !is_string(t, KW_IMPORT) && !is_string(t, KW_EXTEND) && !is_string(t, KW_EXPORT) ) break; /* get import or extend list and change scope appropriately */ BodyParNotAllowed(); New(import_list, ACAT); has_import_encl = FALSE; if( is_string(t, KW_IMPORT) ) { Dispose(t); t = LexGetToken(); while( type(t) == CLOSURE || (type(t)==WORD && !is_string(t,KW_EXPORT) && !is_string(t,KW_DEF) && !is_string(t, KW_MACRO) && !is_string(t, KW_NAMED)) ) { if( type(t) == CLOSURE ) { if( type(actual(t)) == LOCAL ) { /* *** letting this through now if( res_type == NPAR && has_par(actual(t)) ) { Error(5, 46, "named parameter import %s has parameters", WARN, &fpos(t), SymName(actual(t))); } else { *** */ PushScope(actual(t), FALSE, TRUE); if( actual(t) == encl ) has_import_encl = TRUE; Link(import_list, t); /* *** } *** */ } else { Error(5, 26, "import name expected here", WARN, &fpos(t)); Dispose(t); } } else { Error(5, 27, "import %s not in scope", WARN, &fpos(t), string(t)); Dispose(t); } t = LexGetToken(); } } else if( is_string(t, KW_EXTEND) ) { Dispose(t); t = LexGetToken(); while( type(t) == CLOSURE || (type(t)==WORD && !is_string(t,KW_EXPORT) && !is_string(t,KW_DEF) && !is_string(t, KW_MACRO)) ) { if( type(t) == CLOSURE ) { if( imports(actual(t)) != nilobj ) { Error(5, 48, "%s has %s clause, so cannot be extended", WARN, &fpos(t), SymName(actual(t)), KW_IMPORT); } else if( type(actual(t)) == LOCAL ) { PushScope(actual(t), FALSE, FALSE); curr_encl = actual(t); debug1(DRD, D, " curr_encl = %s", SymName(curr_encl)); Link(import_list, t); } else { Error(5, 28, "%s symbol name expected here", WARN, &fpos(t), KW_EXTEND); Dispose(t); } } else { Error(5, 29, "extend symbol %s not in scope", WARN,&fpos(t),string(t)); Dispose(t); } t = LexGetToken(); } } /* get export list and store for setting visible flags below */ New(export_list, ACAT); if( is_string(t, KW_EXPORT) ) { Dispose(t); SuppressScope(); t = LexGetToken(); while( is_word(type(t)) && !is_string(t, KW_DEF) && !is_string(t, KW_IMPORT) && !is_string(t, KW_MACRO) && !is_string(t, KW_EXTEND) ) { Link(export_list, t); t = LexGetToken(); } UnSuppressScope(); } if( res_type == LOCAL && !is_string(t, KW_DEF) && !is_string(t, KW_MACRO) ) { Error(5, 30, "keyword %s or %s expected here", WARN, &fpos(t), KW_DEF, KW_MACRO); break; } if( res_type == NPAR && !is_string(t, KW_NAMED) ) { Error(5, 31, "keyword %s expected here", WARN, &fpos(t), KW_NAMED); break; } if( is_string(t, KW_MACRO) ) { if( Down(export_list) != export_list ) Error(5, 32, "ignoring export list of macro", WARN, &fpos(t)); res = ReadMacro(&t, curr_encl, encl); } else { SuppressScope(); Dispose(t); t = LexGetToken(); /* check for compulsory keyword */ if( res_type == NPAR && is_string(t, KW_COMPULSORY) ) { compulsory_par = TRUE; Dispose(t); t = LexGetToken(); } else compulsory_par = FALSE; /* find name of symbol and insert it */ if( !is_word(type(t)) ) { Error(5, 33, "symbol name expected here", WARN, &fpos(t)); debug1(ANY, D, "offending type is %s", Image(type(t))); UnSuppressScope(); *token = t; return; } res = InsertSym(string(t), res_type, &fpos(t), DEFAULT_PREC, FALSE, FALSE, 0, curr_encl, nilobj); if( curr_encl != encl ) visible(res) = TRUE; if( has_import_encl ) { imports_encl(res) = TRUE; debug1(DCE, D, " setting import_encl(%s) to TRUE", SymName(res)); } if( compulsory_par ) { has_compulsory(encl)++; is_compulsory(res) = TRUE; } Dispose(t); t = LexGetToken(); /* find alternative names for this symbol */ while( is_word(type(t)) && !is_string(t, KW_NAMED) && !is_string(t, KW_IMPORT) && !is_string(t, KW_FORCE) && !is_string(t, KW_INTO) && !is_string(t, KW_HORIZ) && !is_string(t, KW_PRECEDENCE) && !is_string(t, KW_ASSOC) && !is_string(t, KW_LEFT) && !is_string(t, KW_RIGHT) && !is_string(t, KW_BODY) && !is_string(t, KW_LBR) && !is_string(t, KW_BEGIN) ) { InsertAlternativeName(string(t), res, &fpos(t)); Dispose(t); t = LexGetToken(); } /* find force, if any */ if( is_string(t, KW_FORCE) ) { force_target(res) = TRUE; Dispose(t); t = LexGetToken(); if( !is_string(t, KW_INTO) && !is_string(t, KW_HORIZ) ) Error(5, 34, "%s expected here", WARN, &fpos(t), KW_INTO); } /* find horizontally, if any */ if( is_string(t, KW_HORIZ) ) { horiz_galley(res) = COLM; Dispose(t); t = LexGetToken(); /* *** want to allow KW_HORIZ with @Target form now if( !is_string(t, KW_INTO) ) Error(5, 35, "%s expected here", WARN, &fpos(t), KW_INTO); *** */ } /* find into clause, if any */ res_target = nilobj; if( is_string(t, KW_INTO) ) { UnSuppressScope(); Dispose(t); t = LexGetToken(); if( type(t) != LBR ) { Error(5, 36, "%s expected here", WARN, &fpos(t), KW_LBR); debug1(ANY, D, "offending type is %s", Image(type(t))); UnSuppressScope(); *token = t; return; } res_target = Parse(&t, curr_encl, FALSE, FALSE); SuppressScope(); if( t == nilobj ) t = LexGetToken(); } /* find precedence clause, if any */ if( is_string(t, KW_PRECEDENCE) ) { int prec = 0; UnSuppressScope(); Dispose(t); t = LexGetToken(); while( type(t) == WORD && decimaldigit(string(t)[0]) ) { prec = prec * 10 + digitchartonum(string(t)[0]); Dispose(t); t = LexGetToken(); } SuppressScope(); if( prec < MIN_PREC ) { Error(5, 37, "precedence is too low (%d substituted)", WARN, &fpos(t), MIN_PREC); prec = MIN_PREC; } else if( prec > MAX_PREC ) { Error(5, 38, "precedence is too high (%d substituted)", WARN, &fpos(t), MAX_PREC); prec = MAX_PREC; } precedence(res) = prec; } /* find associativity clause, if any */ if( is_string(t, KW_ASSOC) ) { UnSuppressScope(); Dispose(t); t = LexGetToken(); if( is_string(t, KW_LEFT) ) right_assoc(res) = FALSE; else if( !is_string(t, KW_RIGHT) ) Error(5, 39, "associativity altered to %s", WARN, &fpos(t), KW_RIGHT); SuppressScope(); Dispose(t); t = LexGetToken(); } /* find left parameter, if any */ if( is_string(t, KW_LEFT) ) { Dispose(t); t = LexGetToken(); if( type(t) != WORD ) { Error(5, 40, "cannot find %s parameter name", WARN, &fpos(t), KW_LEFT); debug1(ANY, D, "offending type is %s", Image(type(t))); UnSuppressScope(); *token = t; return; } InsertSym(string(t), LPAR, &fpos(t), DEFAULT_PREC, FALSE, FALSE, 0, res, nilobj); Dispose(t); t = LexGetToken(); } /* find named parameters, if any */ UnSuppressScope(); ReadDefinitions(&t, res, NPAR); /* find right or body parameter, if any */ if( is_string(t, KW_RIGHT) || is_string(t, KW_BODY) ) { has_body(res) = is_string(t, KW_BODY); SuppressScope(); Dispose(t); t = LexGetToken(); if( type(t) != WORD ) { Error(5, 41, "cannot find %s parameter name", WARN,&fpos(t),KW_RIGHT); debug1(ANY, D, "offending type is %s", Image(type(t))); UnSuppressScope(); *token = t; return; } InsertSym(string(t), RPAR, &fpos(t), DEFAULT_PREC, FALSE, FALSE, 0, res, nilobj); UnSuppressScope(); Dispose(t); t = LexGetToken(); } /* read local definitions and body */ if( res_target != nilobj ) InsertSym(KW_TARGET, LOCAL, &fpos(res_target), DEFAULT_PREC, FALSE, FALSE, 0, res, res_target); if( type(t) == WORD && StringEqual(string(t), KW_LBR) ) { z = NewToken(LBR, &fpos(t), 0, 0, LBR_PREC, StartSym); Dispose(t); t = z; } else if( type(t) == WORD && StringEqual(string(t), KW_BEGIN) ) { z = NewToken(BEGIN, &fpos(t), 0, 0, BEGIN_PREC, StartSym); Dispose(t); t = z; } else if( type(t) != LBR && type(t) != BEGIN ) Error(5, 42, "opening left brace or @Begin of %s expected", FATAL, &fpos(t), SymName(res)); if( type(t) == BEGIN ) actual(t) = res; PushScope(res, FALSE, FALSE); BodyParAllowed(); sym_body(res) = Parse(&t, res, TRUE, FALSE); /* set visible flag of the exported symbols */ for( link=Down(export_list); link != export_list; link=NextDown(link) ) { Child(y, link); z = SearchSym(string(y), StringLength(string(y))); if( z == nilobj || enclosing(z) != res ) Error(5, 43, "exported symbol %s is not defined in %s", WARN, &fpos(y), string(y), SymName(res)); else if( has_body(res) && type(z) == RPAR ) Error(5, 44, "body parameter %s may not be exported", WARN, &fpos(y), string(y)); else if( visible(z) ) Error(5, 45, "symbol %s exported twice", WARN, &fpos(y), string(y)); else visible(z) = TRUE; } DisposeObject(export_list); /* pop scope of res */ PopScope(); } /* pop import scopes and store imports in sym tab */ for( link=Down(import_list); link != import_list; link=NextDown(link) ) { PopScope(); } if( Down(import_list) == import_list || curr_encl != encl ) { DisposeObject(import_list); import_list = nilobj; } else { imports(res) = import_list; } BodyParAllowed(); if( t == nilobj ) t = LexGetToken(); } /* end while */ *token = t; return; } /* end ReadDefinitions */