1 #include "cc.h" 2 #include "y.tab.h" 3 4 enum 5 { 6 Fnone = 0, 7 Fl, 8 Fvl, 9 Fignor, 10 Fstar, 11 Fadj, 12 13 Fverb = 10, 14 }; 15 16 typedef struct Tprot Tprot; 17 struct Tprot 18 { 19 Type* type; 20 Bits flag; 21 Tprot* link; 22 }; 23 24 typedef struct Tname Tname; 25 struct Tname 26 { 27 char* name; 28 int param; 29 Tname* link; 30 }; 31 32 static Type* indchar; 33 static uchar flagbits[512]; 34 static char fmtbuf[100]; 35 static int lastadj; 36 static int lastverb; 37 static int nstar; 38 static Tprot* tprot; 39 static Tname* tname; 40 41 void 42 argflag(int c, int v) 43 { 44 45 switch(v) { 46 case Fignor: 47 case Fstar: 48 case Fl: 49 case Fvl: 50 flagbits[c] = v; 51 break; 52 case Fverb: 53 flagbits[c] = lastverb; 54 /*print("flag-v %c %d\n", c, lastadj);*/ 55 lastverb++; 56 break; 57 case Fadj: 58 flagbits[c] = lastadj; 59 /*print("flag-l %c %d\n", c, lastadj);*/ 60 lastadj++; 61 break; 62 } 63 } 64 65 Bits 66 getflag(char *s) 67 { 68 Bits flag; 69 int f; 70 char *fmt; 71 Rune c; 72 73 fmt = fmtbuf; 74 flag = zbits; 75 nstar = 0; 76 for(;;) { 77 s += chartorune(&c, s); 78 if(c == 0 || c >= nelem(flagbits)) 79 break; 80 fmt += runetochar(fmt, &c); 81 f = flagbits[c]; 82 switch(f) { 83 case Fnone: 84 argflag(c, Fverb); 85 f = flagbits[c]; 86 break; 87 case Fstar: 88 nstar++; 89 case Fignor: 90 continue; 91 case Fl: 92 if(bset(flag, Fl)) 93 flag = bor(flag, blsh(Fvl)); 94 } 95 flag = bor(flag, blsh(f)); 96 if(f >= Fverb) 97 break; 98 } 99 *fmt = 0; 100 return flag; 101 } 102 103 void 104 newprot(Sym *m, Type *t, char *s) 105 { 106 Bits flag; 107 Tprot *l; 108 109 if(t == T) { 110 warn(Z, "%s: newprot: type not defined", m->name); 111 return; 112 } 113 flag = getflag(s); 114 for(l=tprot; l; l=l->link) 115 if(beq(flag, l->flag) && sametype(t, l->type)) 116 return; 117 l = alloc(sizeof(*l)); 118 l->type = t; 119 l->flag = flag; 120 l->link = tprot; 121 tprot = l; 122 } 123 124 void 125 newname(char *s, int p) 126 { 127 Tname *l; 128 129 for(l=tname; l; l=l->link) 130 if(strcmp(l->name, s) == 0) { 131 if(l->param != p) 132 yyerror("vargck %s already defined\n", s); 133 return; 134 } 135 l = alloc(sizeof(*l)); 136 l->name = s; 137 l->param = p; 138 l->link = tname; 139 tname = l; 140 } 141 142 void 143 arginit(void) 144 { 145 int i; 146 147 /* debug['F'] = 1;*/ 148 /* debug['w'] = 1;*/ 149 150 lastadj = Fadj; 151 lastverb = Fverb; 152 indchar = typ(TIND, types[TCHAR]); 153 154 memset(flagbits, Fnone, sizeof(flagbits)); 155 156 for(i='0'; i<='9'; i++) 157 argflag(i, Fignor); 158 argflag('.', Fignor); 159 argflag('#', Fignor); 160 argflag('u', Fignor); 161 argflag('h', Fignor); 162 argflag('+', Fignor); 163 argflag('-', Fignor); 164 165 argflag('*', Fstar); 166 argflag('l', Fl); 167 168 argflag('o', Fverb); 169 flagbits['x'] = flagbits['o']; 170 flagbits['X'] = flagbits['o']; 171 } 172 173 void 174 pragvararg(void) 175 { 176 Sym *s; 177 int n, c; 178 char *t; 179 Rune r; 180 Type *ty; 181 182 if(!debug['F']) 183 goto out; 184 s = getsym(); 185 if(s && strcmp(s->name, "argpos") == 0) 186 goto ckpos; 187 if(s && strcmp(s->name, "type") == 0) 188 goto cktype; 189 if(s && strcmp(s->name, "flag") == 0) 190 goto ckflag; 191 yyerror("syntax in #pragma varargck"); 192 goto out; 193 194 ckpos: 195 /*#pragma varargck argpos warn 2*/ 196 s = getsym(); 197 if(s == S) 198 goto bad; 199 n = getnsn(); 200 if(n < 0) 201 goto bad; 202 newname(s->name, n); 203 goto out; 204 205 ckflag: 206 /*#pragma varargck flag 'c'*/ 207 c = getnsc(); 208 if(c != '\'') 209 goto bad; 210 c = getr(); 211 if(c == '\\') 212 c = getr(); 213 else if(c == '\'') 214 goto bad; 215 if(c == '\n') 216 goto bad; 217 if(getc() != '\'') 218 goto bad; 219 argflag(c, Fignor); 220 goto out; 221 222 cktype: 223 /*#pragma varargck type O int*/ 224 c = getnsc(); 225 if(c != '"') 226 goto bad; 227 t = fmtbuf; 228 for(;;) { 229 r = getr(); 230 if(r == ' ' || r == '\n') 231 goto bad; 232 if(r == '"') 233 break; 234 t += runetochar(t, &r); 235 } 236 *t = 0; 237 t = strdup(fmtbuf); 238 s = getsym(); 239 if(s == S) 240 goto bad; 241 ty = s->type; 242 while((c = getnsc()) == '*') 243 ty = typ(TIND, ty); 244 unget(c); 245 newprot(s, ty, t); 246 goto out; 247 248 bad: 249 yyerror("syntax in #pragma varargck"); 250 251 out: 252 while(getnsc() != '\n') 253 ; 254 } 255 256 Node* 257 nextarg(Node *n, Node **a) 258 { 259 if(n == Z) { 260 *a = Z; 261 return Z; 262 } 263 if(n->op == OLIST) { 264 *a = n->left; 265 return n->right; 266 } 267 *a = n; 268 return Z; 269 } 270 271 void 272 checkargs(Node *nn, char *s, int pos) 273 { 274 Node *a, *n; 275 Bits flag; 276 Tprot *l; 277 278 if(!debug['F']) 279 return; 280 n = nn; 281 for(;;) { 282 s = strchr(s, '%'); 283 if(s == 0) { 284 nextarg(n, &a); 285 if(a != Z) 286 warn(nn, "more arguments than format %T", 287 a->type); 288 return; 289 } 290 s++; 291 flag = getflag(s); 292 while(nstar > 0) { 293 n = nextarg(n, &a); 294 pos++; 295 nstar--; 296 if(a == Z) { 297 warn(nn, "more format than arguments %s", 298 fmtbuf); 299 return; 300 } 301 if(a->type == T) 302 continue; 303 if(!sametype(types[TINT], a->type) && 304 !sametype(types[TUINT], a->type)) 305 warn(nn, "format mismatch '*' in %s %T, arg %d", 306 fmtbuf, a->type, pos); 307 } 308 for(l=tprot; l; l=l->link) 309 if(sametype(types[TVOID], l->type)) { 310 if(beq(flag, l->flag)) { 311 s++; 312 goto loop; 313 } 314 } 315 316 n = nextarg(n, &a); 317 pos++; 318 if(a == Z) { 319 warn(nn, "more format than arguments %s", 320 fmtbuf); 321 return; 322 } 323 if(a->type == 0) 324 continue; 325 for(l=tprot; l; l=l->link) 326 if(sametype(a->type, l->type)) { 327 /*print("checking %T/%ulx %T/%ulx\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/ 328 if(beq(flag, l->flag)) 329 goto loop; 330 } 331 warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos); 332 loop:; 333 } 334 } 335 336 void 337 dpcheck(Node *n) 338 { 339 char *s; 340 Node *a, *b; 341 Tname *l; 342 int i; 343 344 if(n == Z) 345 return; 346 b = n->left; 347 if(b == Z || b->op != ONAME) 348 return; 349 s = b->sym->name; 350 for(l=tname; l; l=l->link) 351 if(strcmp(s, l->name) == 0) 352 break; 353 if(l == 0) 354 return; 355 356 i = l->param; 357 b = n->right; 358 while(i > 0) { 359 b = nextarg(b, &a); 360 i--; 361 } 362 if(a == Z) { 363 warn(n, "cant find format arg"); 364 return; 365 } 366 if(!sametype(indchar, a->type)) { 367 warn(n, "format arg type %T", a->type); 368 return; 369 } 370 if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) { 371 /* warn(n, "format arg not constant string");*/ 372 return; 373 } 374 s = a->left->cstring; 375 checkargs(b, s, l->param); 376 } 377 378 void 379 pragpack(void) 380 { 381 Sym *s; 382 383 packflg = 0; 384 s = getsym(); 385 if(s) { 386 packflg = atoi(s->name+1); 387 if(strcmp(s->name, "on") == 0 || 388 strcmp(s->name, "yes") == 0) 389 packflg = 1; 390 } 391 while(getnsc() != '\n') 392 ; 393 if(debug['f']) 394 if(packflg) 395 print("%4ld: pack %d\n", lineno, packflg); 396 else 397 print("%4ld: pack off\n", lineno); 398 } 399 400 void 401 pragfpround(void) 402 { 403 Sym *s; 404 405 fproundflg = 0; 406 s = getsym(); 407 if(s) { 408 fproundflg = atoi(s->name+1); 409 if(strcmp(s->name, "on") == 0 || 410 strcmp(s->name, "yes") == 0) 411 fproundflg = 1; 412 } 413 while(getnsc() != '\n') 414 ; 415 if(debug['f']) 416 if(fproundflg) 417 print("%4ld: fproundflg %d\n", lineno, fproundflg); 418 else 419 print("%4ld: fproundflg off\n", lineno); 420 } 421 422 void 423 pragprofile(void) 424 { 425 Sym *s; 426 427 profileflg = 0; 428 s = getsym(); 429 if(s) { 430 profileflg = atoi(s->name+1); 431 if(strcmp(s->name, "on") == 0 || 432 strcmp(s->name, "yes") == 0) 433 profileflg = 1; 434 } 435 while(getnsc() != '\n') 436 ; 437 if(debug['f']) 438 if(profileflg) 439 print("%4ld: profileflg %d\n", lineno, profileflg); 440 else 441 print("%4ld: profileflg off\n", lineno); 442 } 443 444 void 445 pragincomplete(void) 446 { 447 Sym *s; 448 Type *t; 449 int istag, w, et; 450 451 istag = 0; 452 s = getsym(); 453 if(s == nil) 454 goto out; 455 et = 0; 456 w = s->lexical; 457 if(w == LSTRUCT) 458 et = TSTRUCT; 459 else if(w == LUNION) 460 et = TUNION; 461 if(et != 0){ 462 s = getsym(); 463 if(s == nil){ 464 yyerror("missing struct/union tag in pragma incomplete"); 465 goto out; 466 } 467 if(s->lexical != LNAME && s->lexical != LTYPE){ 468 yyerror("invalid struct/union tag: %s", s->name); 469 goto out; 470 } 471 dotag(s, et, 0); 472 istag = 1; 473 }else if(strcmp(s->name, "_off_") == 0){ 474 debug['T'] = 0; 475 goto out; 476 }else if(strcmp(s->name, "_on_") == 0){ 477 debug['T'] = 1; 478 goto out; 479 } 480 t = s->type; 481 if(istag) 482 t = s->suetag; 483 if(t == T) 484 yyerror("unknown type %s in pragma incomplete", s->name); 485 else if(!typesu[t->etype]) 486 yyerror("not struct/union type in pragma incomplete: %s", s->name); 487 else 488 t->garb |= GINCOMPLETE; 489 out: 490 while(getnsc() != '\n') 491 ; 492 if(debug['f']) 493 print("%s incomplete\n", s->name); 494 } 495