123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- #include "cc.h"
- #include "y.tab.h"
- enum
- {
- Fnone = 0,
- Fl,
- Fvl,
- Fignor,
- Fstar,
- Fadj,
- Fverb = 10,
- };
- typedef struct Tprot Tprot;
- struct Tprot
- {
- Type* type;
- Bits flag;
- Tprot* link;
- };
- typedef struct Tname Tname;
- struct Tname
- {
- char* name;
- int param;
- Tname* link;
- };
- static Type* indchar;
- static uchar flagbits[512];
- static char fmtbuf[100];
- static int lastadj;
- static int lastverb;
- static int nstar;
- static Tprot* tprot;
- static Tname* tname;
- void
- argflag(int c, int v)
- {
- switch(v) {
- case Fignor:
- case Fstar:
- case Fl:
- case Fvl:
- flagbits[c] = v;
- break;
- case Fverb:
- flagbits[c] = lastverb;
- /*print("flag-v %c %d\n", c, lastadj);*/
- lastverb++;
- break;
- case Fadj:
- flagbits[c] = lastadj;
- /*print("flag-l %c %d\n", c, lastadj);*/
- lastadj++;
- break;
- }
- }
- Bits
- getflag(char *s)
- {
- Bits flag;
- int f;
- char *fmt;
- Rune c;
- fmt = fmtbuf;
- flag = zbits;
- nstar = 0;
- for(;;) {
- s += chartorune(&c, s);
- if(c == 0 || c >= nelem(flagbits))
- break;
- fmt += runetochar(fmt, &c);
- f = flagbits[c];
- switch(f) {
- case Fnone:
- argflag(c, Fverb);
- f = flagbits[c];
- break;
- case Fstar:
- nstar++;
- case Fignor:
- continue;
- case Fl:
- if(bset(flag, Fl))
- flag = bor(flag, blsh(Fvl));
- }
- flag = bor(flag, blsh(f));
- if(f >= Fverb)
- break;
- }
- *fmt = 0;
- return flag;
- }
- void
- newprot(Sym *m, Type *t, char *s)
- {
- Bits flag;
- Tprot *l;
- if(t == T) {
- warn(Z, "%s: newprot: type not defined", m->name);
- return;
- }
- flag = getflag(s);
- for(l=tprot; l; l=l->link)
- if(beq(flag, l->flag) && sametype(t, l->type))
- return;
- l = alloc(sizeof(*l));
- l->type = t;
- l->flag = flag;
- l->link = tprot;
- tprot = l;
- }
- void
- newname(char *s, int p)
- {
- Tname *l;
- for(l=tname; l; l=l->link)
- if(strcmp(l->name, s) == 0) {
- if(l->param != p)
- yyerror("vargck %s already defined\n", s);
- return;
- }
- l = alloc(sizeof(*l));
- l->name = s;
- l->param = p;
- l->link = tname;
- tname = l;
- }
- void
- arginit(void)
- {
- int i;
- /* debug['F'] = 1;*/
- /* debug['w'] = 1;*/
- lastadj = Fadj;
- lastverb = Fverb;
- indchar = typ(TIND, types[TCHAR]);
- memset(flagbits, Fnone, sizeof(flagbits));
- for(i='0'; i<='9'; i++)
- argflag(i, Fignor);
- argflag('.', Fignor);
- argflag('#', Fignor);
- argflag('u', Fignor);
- argflag('h', Fignor);
- argflag('+', Fignor);
- argflag('-', Fignor);
- argflag('*', Fstar);
- argflag('l', Fl);
- argflag('o', Fverb);
- flagbits['x'] = flagbits['o'];
- flagbits['X'] = flagbits['o'];
- }
- void
- pragvararg(void)
- {
- Sym *s;
- int n, c;
- char *t;
- Rune r;
- Type *ty;
- if(!debug['F'])
- goto out;
- s = getsym();
- if(s && strcmp(s->name, "argpos") == 0)
- goto ckpos;
- if(s && strcmp(s->name, "type") == 0)
- goto cktype;
- if(s && strcmp(s->name, "flag") == 0)
- goto ckflag;
- yyerror("syntax in #pragma varargck");
- goto out;
- ckpos:
- /*#pragma varargck argpos warn 2*/
- s = getsym();
- if(s == S)
- goto bad;
- n = getnsn();
- if(n < 0)
- goto bad;
- newname(s->name, n);
- goto out;
- ckflag:
- /*#pragma varargck flag 'c'*/
- c = getnsc();
- if(c != '\'')
- goto bad;
- c = getr();
- if(c == '\\')
- c = getr();
- else if(c == '\'')
- goto bad;
- if(c == '\n')
- goto bad;
- if(getc() != '\'')
- goto bad;
- argflag(c, Fignor);
- goto out;
- cktype:
- /*#pragma varargck type O int*/
- c = getnsc();
- if(c != '"')
- goto bad;
- t = fmtbuf;
- for(;;) {
- r = getr();
- if(r == ' ' || r == '\n')
- goto bad;
- if(r == '"')
- break;
- t += runetochar(t, &r);
- }
- *t = 0;
- t = strdup(fmtbuf);
- s = getsym();
- if(s == S)
- goto bad;
- ty = s->type;
- while((c = getnsc()) == '*')
- ty = typ(TIND, ty);
- unget(c);
- newprot(s, ty, t);
- goto out;
- bad:
- yyerror("syntax in #pragma varargck");
- out:
- while(getnsc() != '\n')
- ;
- }
- Node*
- nextarg(Node *n, Node **a)
- {
- if(n == Z) {
- *a = Z;
- return Z;
- }
- if(n->op == OLIST) {
- *a = n->left;
- return n->right;
- }
- *a = n;
- return Z;
- }
- void
- checkargs(Node *nn, char *s, int pos)
- {
- Node *a, *n;
- Bits flag;
- Tprot *l;
- if(!debug['F'])
- return;
- n = nn;
- for(;;) {
- s = strchr(s, '%');
- if(s == 0) {
- nextarg(n, &a);
- if(a != Z)
- warn(nn, "more arguments than format %T",
- a->type);
- return;
- }
- s++;
- flag = getflag(s);
- while(nstar > 0) {
- n = nextarg(n, &a);
- pos++;
- nstar--;
- if(a == Z) {
- warn(nn, "more format than arguments %s",
- fmtbuf);
- return;
- }
- if(a->type == T)
- continue;
- if(!sametype(types[TINT], a->type) &&
- !sametype(types[TUINT], a->type))
- warn(nn, "format mismatch '*' in %s %T, arg %d",
- fmtbuf, a->type, pos);
- }
- for(l=tprot; l; l=l->link)
- if(sametype(types[TVOID], l->type)) {
- if(beq(flag, l->flag)) {
- s++;
- goto loop;
- }
- }
- n = nextarg(n, &a);
- pos++;
- if(a == Z) {
- warn(nn, "more format than arguments %s",
- fmtbuf);
- return;
- }
- if(a->type == 0)
- continue;
- for(l=tprot; l; l=l->link)
- if(sametype(a->type, l->type)) {
- /*print("checking %T/%ulx %T/%ulx\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
- if(beq(flag, l->flag))
- goto loop;
- }
- warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos);
- loop:;
- }
- }
- void
- dpcheck(Node *n)
- {
- char *s;
- Node *a, *b;
- Tname *l;
- int i;
- if(n == Z)
- return;
- b = n->left;
- if(b == Z || b->op != ONAME)
- return;
- s = b->sym->name;
- for(l=tname; l; l=l->link)
- if(strcmp(s, l->name) == 0)
- break;
- if(l == 0)
- return;
- i = l->param;
- b = n->right;
- while(i > 0) {
- b = nextarg(b, &a);
- i--;
- }
- if(a == Z) {
- warn(n, "cant find format arg");
- return;
- }
- if(!sametype(indchar, a->type)) {
- warn(n, "format arg type %T", a->type);
- return;
- }
- if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
- /* warn(n, "format arg not constant string");*/
- return;
- }
- s = a->left->cstring;
- checkargs(b, s, l->param);
- }
- void
- pragpack(void)
- {
- Sym *s;
- packflg = 0;
- s = getsym();
- if(s) {
- packflg = atoi(s->name+1);
- if(strcmp(s->name, "on") == 0 ||
- strcmp(s->name, "yes") == 0)
- packflg = 1;
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- if(packflg)
- print("%4ld: pack %d\n", lineno, packflg);
- else
- print("%4ld: pack off\n", lineno);
- }
- void
- pragfpround(void)
- {
- Sym *s;
- fproundflg = 0;
- s = getsym();
- if(s) {
- fproundflg = atoi(s->name+1);
- if(strcmp(s->name, "on") == 0 ||
- strcmp(s->name, "yes") == 0)
- fproundflg = 1;
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- if(fproundflg)
- print("%4ld: fproundflg %d\n", lineno, fproundflg);
- else
- print("%4ld: fproundflg off\n", lineno);
- }
- void
- pragprofile(void)
- {
- Sym *s;
- profileflg = 0;
- s = getsym();
- if(s) {
- profileflg = atoi(s->name+1);
- if(strcmp(s->name, "on") == 0 ||
- strcmp(s->name, "yes") == 0)
- profileflg = 1;
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- if(profileflg)
- print("%4ld: profileflg %d\n", lineno, profileflg);
- else
- print("%4ld: profileflg off\n", lineno);
- }
- void
- pragincomplete(void)
- {
- Sym *s;
- Type *t;
- int istag, w, et;
- istag = 0;
- s = getsym();
- if(s == nil)
- goto out;
- et = 0;
- w = s->lexical;
- if(w == LSTRUCT)
- et = TSTRUCT;
- else if(w == LUNION)
- et = TUNION;
- if(et != 0){
- s = getsym();
- if(s == nil){
- yyerror("missing struct/union tag in pragma incomplete");
- goto out;
- }
- if(s->lexical != LNAME && s->lexical != LTYPE){
- yyerror("invalid struct/union tag: %s", s->name);
- goto out;
- }
- dotag(s, et, 0);
- istag = 1;
- }else if(strcmp(s->name, "_off_") == 0){
- debug['T'] = 0;
- goto out;
- }else if(strcmp(s->name, "_on_") == 0){
- debug['T'] = 1;
- goto out;
- }
- t = s->type;
- if(istag)
- t = s->suetag;
- if(t == T)
- yyerror("unknown type %s in pragma incomplete", s->name);
- else if(!typesu[t->etype])
- yyerror("not struct/union type in pragma incomplete: %s", s->name);
- else
- t->garb |= GINCOMPLETE;
- out:
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- print("%s incomplete\n", s->name);
- }
|