1da2e3ebdSchin /*********************************************************************** 2da2e3ebdSchin * * 3da2e3ebdSchin * This software is part of the ast package * 4*7c2fbfb3SApril Chin * Copyright (c) 1986-2008 AT&T Intellectual Property * 5da2e3ebdSchin * and is licensed under the * 6da2e3ebdSchin * Common Public License, Version 1.0 * 7*7c2fbfb3SApril Chin * by AT&T Intellectual Property * 8da2e3ebdSchin * * 9da2e3ebdSchin * A copy of the License is available at * 10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt * 11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12da2e3ebdSchin * * 13da2e3ebdSchin * Information and Software Systems Research * 14da2e3ebdSchin * AT&T Research * 15da2e3ebdSchin * Florham Park NJ * 16da2e3ebdSchin * * 17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> * 18da2e3ebdSchin * * 19da2e3ebdSchin ***********************************************************************/ 20da2e3ebdSchin #pragma prototyped 21da2e3ebdSchin /* 22da2e3ebdSchin * Glenn Fowler 23da2e3ebdSchin * AT&T Research 24da2e3ebdSchin * 25da2e3ebdSchin * miscellaneous preprocessor support 26da2e3ebdSchin */ 27da2e3ebdSchin 28da2e3ebdSchin #include "pplib.h" 29da2e3ebdSchin 30da2e3ebdSchin /* 31da2e3ebdSchin * macro symbol def|ref 32da2e3ebdSchin */ 33da2e3ebdSchin 34da2e3ebdSchin struct ppsymbol* 35da2e3ebdSchin pprefmac(char* name, int ref) 36da2e3ebdSchin { 37da2e3ebdSchin register struct ppsymbol* sym; 38da2e3ebdSchin 39da2e3ebdSchin if (!(sym = ppsymget(pp.symtab, name)) && (ref <= REF_NORMAL && pp.macref || ref == REF_CREATE || ref == REF_DELETE && (pp.mode & (INIT|READONLY)))) 40da2e3ebdSchin { 41da2e3ebdSchin if ((pp.state & COMPILE) && pp.truncate && strlen(name) > pp.truncate) 42da2e3ebdSchin name[pp.truncate] = 0; 43da2e3ebdSchin sym = ppsymset(pp.symtab, NiL); 44da2e3ebdSchin } 45da2e3ebdSchin if (sym && ref <= REF_NORMAL) 46da2e3ebdSchin { 47da2e3ebdSchin if (pp.macref) (*pp.macref)(sym, error_info.file, error_info.line, ref == REF_NORMAL && (pp.state & CONDITIONAL) ? REF_IF : ref, 0L); 48da2e3ebdSchin if (!sym->macro) sym = 0; 49da2e3ebdSchin } 50da2e3ebdSchin #if COMPATIBLE 51da2e3ebdSchin if (!(pp.state & COMPATIBILITY)) 52da2e3ebdSchin #endif 53da2e3ebdSchin if (ref == REF_IF && sym && (sym->flags & SYM_PREDEFINED) && *name != '_' && !(pp.mode & (HOSTED|INACTIVE))) 54da2e3ebdSchin { 55da2e3ebdSchin if (pp.state & STRICT) 56da2e3ebdSchin { 57da2e3ebdSchin error(1, "%s: obsolete predefined symbol reference disabled", name); 58da2e3ebdSchin return(0); 59da2e3ebdSchin } 60da2e3ebdSchin error(1, "%s: obsolete predefined symbol referenced", name); 61da2e3ebdSchin } 62da2e3ebdSchin return(sym); 63da2e3ebdSchin } 64da2e3ebdSchin 65da2e3ebdSchin /* 66da2e3ebdSchin * common predicate assertion operations 67da2e3ebdSchin * op is DEFINE or UNDEF 68da2e3ebdSchin */ 69da2e3ebdSchin 70da2e3ebdSchin void 71da2e3ebdSchin ppassert(int op, char* pred, char* args) 72da2e3ebdSchin { 73da2e3ebdSchin register struct pplist* a; 74da2e3ebdSchin register struct ppsymbol* sym; 75da2e3ebdSchin register struct pplist* p; 76da2e3ebdSchin register struct pplist* q; 77da2e3ebdSchin 78da2e3ebdSchin if (!args) switch (op) 79da2e3ebdSchin { 80da2e3ebdSchin case DEFINE: 81da2e3ebdSchin goto mark; 82da2e3ebdSchin case UNDEF: 83da2e3ebdSchin a = 0; 84da2e3ebdSchin goto unmark; 85da2e3ebdSchin } 86da2e3ebdSchin if (a = (struct pplist*)hashget(pp.prdtab, pred)) 87da2e3ebdSchin { 88da2e3ebdSchin p = 0; 89da2e3ebdSchin q = a; 90da2e3ebdSchin while (q) 91da2e3ebdSchin { 92da2e3ebdSchin if (streq(q->value, args)) 93da2e3ebdSchin { 94da2e3ebdSchin if (op == DEFINE) return; 95da2e3ebdSchin q = q->next; 96da2e3ebdSchin if (p) p->next = q; 97da2e3ebdSchin else a = q; 98da2e3ebdSchin } 99da2e3ebdSchin else 100da2e3ebdSchin { 101da2e3ebdSchin p = q; 102da2e3ebdSchin q = q->next; 103da2e3ebdSchin } 104da2e3ebdSchin } 105da2e3ebdSchin if (op == UNDEF) 106da2e3ebdSchin { 107da2e3ebdSchin unmark: 108da2e3ebdSchin hashput(pp.prdtab, pred, a); 109da2e3ebdSchin if (sym = ppsymref(pp.symtab, pred)) 110da2e3ebdSchin sym->flags &= ~SYM_PREDICATE; 111da2e3ebdSchin return; 112da2e3ebdSchin } 113da2e3ebdSchin } 114da2e3ebdSchin if (op == DEFINE) 115da2e3ebdSchin { 116da2e3ebdSchin p = newof(0, struct pplist, 1, 0); 117da2e3ebdSchin p->next = a; 118da2e3ebdSchin p->value = strdup(args); 119da2e3ebdSchin hashput(pp.prdtab, NiL, p); 120da2e3ebdSchin mark: 121da2e3ebdSchin if ((pp.state & COMPILE) && pp.truncate) return; 122da2e3ebdSchin if (sym = ppsymset(pp.symtab, pred)) 123da2e3ebdSchin sym->flags |= SYM_PREDICATE; 124da2e3ebdSchin } 125da2e3ebdSchin } 126da2e3ebdSchin 127da2e3ebdSchin /* 128da2e3ebdSchin * parse a predicate argument list 129da2e3ebdSchin * the args are placed in pp.args 130da2e3ebdSchin * the first non-space/paren argument token type is returned 131da2e3ebdSchin * forms: 132da2e3ebdSchin * 133da2e3ebdSchin * predicate <identifier> type=T_ID 134da2e3ebdSchin * predicate ( <identifier> ) type=T_ID 135da2e3ebdSchin * predicate ( ) type=0 136da2e3ebdSchin * predicate ( <balanced-paren-list> ) type=T_STRING 137da2e3ebdSchin * otherwise type=<other> 138da2e3ebdSchin */ 139da2e3ebdSchin 140da2e3ebdSchin int 141da2e3ebdSchin pppredargs(void) 142da2e3ebdSchin { 143da2e3ebdSchin register int c; 144da2e3ebdSchin register int n; 145da2e3ebdSchin register int type; 146da2e3ebdSchin char* pptoken; 147da2e3ebdSchin 148da2e3ebdSchin pptoken = pp.token; 149da2e3ebdSchin pp.token = pp.args; 150da2e3ebdSchin switch (type = pplex()) 151da2e3ebdSchin { 152da2e3ebdSchin case '(': 153da2e3ebdSchin type = 0; 154da2e3ebdSchin n = 1; 155da2e3ebdSchin pp.state |= HEADER; 156da2e3ebdSchin pp.state &= ~STRIP; 157da2e3ebdSchin c = pplex(); 158da2e3ebdSchin pp.state &= ~NOSPACE; 159da2e3ebdSchin for (;;) 160da2e3ebdSchin { 161da2e3ebdSchin switch (c) 162da2e3ebdSchin { 163da2e3ebdSchin case '(': 164da2e3ebdSchin n++; 165da2e3ebdSchin break; 166da2e3ebdSchin case '\n': 167da2e3ebdSchin ungetchr(c); 168da2e3ebdSchin error(2, "missing %d )%s in predicate argument list", n, n == 1 ? "" : "'s"); 169da2e3ebdSchin type = 0; 170da2e3ebdSchin goto done; 171da2e3ebdSchin case ')': 172da2e3ebdSchin if (!--n) goto done; 173da2e3ebdSchin break; 174da2e3ebdSchin } 175da2e3ebdSchin pp.token = pp.toknxt; 176da2e3ebdSchin if (c != ' ') 177da2e3ebdSchin { 178da2e3ebdSchin if (type) type = T_STRING; 179da2e3ebdSchin else type = (c == T_ID) ? T_ID : T_STRING; 180da2e3ebdSchin } 181da2e3ebdSchin c = pplex(); 182da2e3ebdSchin } 183da2e3ebdSchin done: 184da2e3ebdSchin pp.state &= ~HEADER; 185da2e3ebdSchin pp.state |= NOSPACE|STRIP; 186da2e3ebdSchin if (pp.token > pp.args && *(pp.token - 1) == ' ') pp.token--; 187da2e3ebdSchin *pp.token = 0; 188da2e3ebdSchin break; 189da2e3ebdSchin case '\n': 190da2e3ebdSchin ungetchr('\n'); 191da2e3ebdSchin type = 0; 192da2e3ebdSchin break; 193da2e3ebdSchin } 194da2e3ebdSchin pp.token = pptoken; 195da2e3ebdSchin return(type); 196da2e3ebdSchin } 197da2e3ebdSchin 198da2e3ebdSchin /* 199da2e3ebdSchin * sync output line number 200da2e3ebdSchin */ 201da2e3ebdSchin 202da2e3ebdSchin int 203da2e3ebdSchin ppsync(void) 204da2e3ebdSchin { 205da2e3ebdSchin long m; 206da2e3ebdSchin 207da2e3ebdSchin if ((pp.state & (ADD|HIDDEN))) 208da2e3ebdSchin { 209da2e3ebdSchin if (pp.state & ADD) 210da2e3ebdSchin { 211da2e3ebdSchin pp.state &= ~ADD; 212da2e3ebdSchin m = pp.addp - pp.addbuf; 213da2e3ebdSchin pp.addp = pp.addbuf; 214da2e3ebdSchin ppprintf("%-.*s", m, pp.addbuf); 215da2e3ebdSchin } 216da2e3ebdSchin if (pp.linesync) 217da2e3ebdSchin { 218da2e3ebdSchin if ((pp.state & SYNCLINE) || pp.hidden >= MAXHIDDEN) 219da2e3ebdSchin { 220da2e3ebdSchin pp.hidden = 0; 221da2e3ebdSchin pp.state &= ~(HIDDEN|SYNCLINE); 222da2e3ebdSchin if (error_info.line) 223da2e3ebdSchin (*pp.linesync)(error_info.line, error_info.file); 224da2e3ebdSchin } 225da2e3ebdSchin else 226da2e3ebdSchin { 227da2e3ebdSchin m = pp.hidden; 228da2e3ebdSchin pp.hidden = 0; 229da2e3ebdSchin pp.state &= ~HIDDEN; 230da2e3ebdSchin while (m-- > 0) 231da2e3ebdSchin ppputchar('\n'); 232da2e3ebdSchin } 233da2e3ebdSchin } 234da2e3ebdSchin else 235da2e3ebdSchin { 236da2e3ebdSchin pp.hidden = 0; 237da2e3ebdSchin pp.state &= ~HIDDEN; 238da2e3ebdSchin ppputchar('\n'); 239da2e3ebdSchin } 240da2e3ebdSchin } 241da2e3ebdSchin return 0; 242da2e3ebdSchin } 243