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