Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

init.c

Go to the documentation of this file.
00001 #include "c.h"
00002 
00003 
00004 static int curseg;      /* current segment */
00005 
00006 /* defpointer - initialize a pointer to p or to 0 if p==0 */
00007 void defpointer(Symbol p) {
00008     if (p) {
00009         (*IR->defaddress)(p);
00010         p->ref++;
00011     } else {
00012         static Value v;
00013         (*IR->defconst)(P, voidptype->size, v);
00014     }
00015 }
00016 
00017 /* genconst - generate/check constant expression e; return size */
00018 static int genconst(Tree e, int def) {
00019     for (;;)
00020         switch (generic(e->op)) {
00021         case ADDRG:
00022             if (def)
00023                 (*IR->defaddress)(e->u.sym);
00024             return e->type->size;
00025         case CNST:
00026             if (e->op == CNST+P && isarray(e->type)) {
00027                 e = cvtconst(e);
00028                 continue;
00029             }
00030             if (def)
00031                 (*IR->defconst)(e->type->op, e->type->size, e->u.v);
00032             return e->type->size;
00033         case RIGHT:
00034             assert(e->kids[0] || e->kids[1]);
00035             if (e->kids[1] && e->kids[0])
00036                 error("initializer must be constant\n");
00037             e = e->kids[1] ? e->kids[1] : e->kids[0];
00038             continue;
00039         case CVP:
00040             if (isarith(e->type))
00041                 error("cast from `%t' to `%t' is illegal in constant expressions\n",
00042                     e->kids[0]->type, e->type);
00043             /* fall thru */
00044         case CVI: case CVU: case CVF:
00045             e = e->kids[0];
00046             continue;
00047         default:
00048             error("initializer must be constant\n");
00049             if (def)
00050                 genconst(consttree(0, inttype), def);
00051             return inttype->size;
00052         }
00053 }
00054 
00055 /* initvalue - evaluate a constant expression for a value of integer type ty */
00056 static Tree initvalue(Type ty) {
00057     Type aty;
00058     Tree e;
00059 
00060     needconst++;
00061     e = expr1(0);
00062     if ((aty = assign(ty, e)) != NULL)
00063         e = cast(e, aty);
00064     else {
00065         error("invalid initialization type; found `%t' expected `%t'\n",
00066             e->type,  ty);
00067         e = retype(consttree(0, inttype), ty);
00068     }
00069     needconst--;
00070     if (generic(e->op) != CNST) {
00071         error("initializer must be constant\n");
00072         e = retype(consttree(0, inttype), ty);
00073     }
00074     return e;
00075 }
00076 
00077 /* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
00078 static int initarray(int len, Type ty, int lev) {
00079     int n = 0;
00080 
00081     do {
00082         initializer(ty, lev);
00083         n += ty->size;
00084         if (len > 0 && n >= len || t != ',')
00085             break;
00086         t = gettok();
00087     } while (t != '}');
00088     return n;
00089 }
00090 
00091 /* initchar - initialize array of <= len ty characters; if len == 0, go to } */
00092 static int initchar(int len, Type ty) {
00093     int n = 0;
00094     char buf[16], *s = buf;
00095 
00096     do {
00097         *s++ = initvalue(ty)->u.v.i;
00098         if (++n%inttype->size == 0) {
00099             (*IR->defstring)(inttype->size, buf);
00100             s = buf;
00101         }
00102         if (len > 0 && n >= len || t != ',')
00103             break;
00104         t = gettok();
00105     } while (t != '}');
00106     if (s > buf)
00107         (*IR->defstring)(s - buf, buf);
00108     return n;
00109 }
00110 
00111 /* initend - finish off an initialization at level lev; accepts trailing comma */
00112 static void initend(int lev, char follow[]) {
00113     if (lev == 0 && t == ',')
00114         t = gettok();
00115     test('}', follow);
00116 }
00117 
00118 /* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
00119 static int initfields(Field p, Field q) {
00120     unsigned int bits = 0;
00121     int i, n = 0;
00122 
00123     do {
00124         i = initvalue(inttype)->u.v.i;
00125         if (fieldsize(p) < 8*p->type->size) {
00126             if (p->type == inttype &&
00127                (i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1))
00128             ||  p->type == unsignedtype && (i&~fieldmask(p)) !=  0)
00129                 warning("initializer exceeds bit-field width\n");
00130             i &= fieldmask(p);
00131         }
00132         bits |= i<<fieldright(p);
00133         if (IR->little_endian) {
00134             if (fieldsize(p) + fieldright(p) > n)
00135                 n = fieldsize(p) + fieldright(p);
00136         } else {
00137             if (fieldsize(p) + fieldleft(p) > n)
00138                 n = fieldsize(p) + fieldleft(p);
00139         }
00140         if (p->link == q)
00141             break;
00142         p = p->link;
00143     } while (t == ',' && (t = gettok()) != 0);
00144     n = (n + 7)/8;
00145     for (i = 0; i < n; i++) {
00146         Value v;
00147         if (IR->little_endian) {
00148             v.u = (unsigned char)bits;
00149             bits >>= 8;
00150         } else {    /* a big endian */
00151             v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1)));
00152             bits <<= 8;
00153         }
00154         (*IR->defconst)(U, unsignedchar->size, v);
00155     }
00156     return n;
00157 }
00158 
00159 /* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
00160 static int initstruct(int len, Type ty, int lev) {
00161     int a, n = 0;
00162     Field p = ty->u.sym->u.s.flist;
00163 
00164     do {
00165         if (p->offset > n) {
00166             (*IR->space)(p->offset - n);
00167             n += p->offset - n;
00168         }
00169         if (p->lsb) {
00170             Field q = p;
00171             while (q->link && q->link->offset == p->offset)
00172                 q = q->link;
00173             n += initfields(p, q->link);
00174             p = q;
00175         } else {
00176             initializer(p->type, lev);
00177             n += p->type->size;
00178         }
00179         if (p->link) {
00180             p = p->link;
00181             a = p->type->align;
00182         } else
00183             a = ty->align;
00184         if (a && n%a) {
00185             (*IR->space)(a - n%a);
00186             n = roundup(n, a);
00187         }
00188         if (len > 0 && n >= len || t != ',')
00189             break;
00190         t = gettok();
00191     } while (t != '}');
00192     return n;
00193 }
00194 
00195 /* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
00196 Type initializer(Type ty, int lev) {
00197     int n = 0;
00198     Tree e;
00199     Type aty = NULL;
00200     static char follow[] = { IF, CHAR, STATIC, 0 };
00201 
00202     ty = unqual(ty);
00203     if (isscalar(ty)) {
00204         needconst++;
00205         if (t == '{') {
00206             t = gettok();
00207             e = expr1(0);
00208             initend(lev, follow);
00209         } else
00210             e = expr1(0);
00211         e = pointer(e);
00212         if ((aty = assign(ty, e)) != NULL)
00213             e = cast(e, aty);
00214         else
00215             error("invalid initialization type; found `%t' expected `%t'\n",
00216                 e->type, ty);
00217         n = genconst(e, 1);
00218         deallocate(STMT);
00219         needconst--;
00220     }
00221     if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
00222         static char follow[] = { CHAR, STATIC, 0 };
00223         error("cannot initialize undefined `%t'\n", ty);
00224         skipto(';', follow);
00225         return ty;
00226     } else if (isunion(ty)) {
00227         if (t == '{') {
00228             t = gettok();
00229             n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
00230             initend(lev, follow);
00231         } else {
00232             if (lev == 0)
00233                 error("missing { in initialization of `%t'\n", ty);
00234             n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
00235         }
00236     } else if (isstruct(ty)) {
00237         if (t == '{') {
00238             t = gettok();
00239             n = initstruct(0, ty, lev + 1);
00240             test('}', follow);
00241         } else if (lev > 0)
00242             n = initstruct(ty->size, ty, lev + 1);
00243         else {
00244             error("missing { in initialization of `%t'\n", ty);
00245             n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
00246         }
00247     }
00248     if (isarray(ty))
00249         aty = unqual(ty->type);
00250     if (isarray(ty) && ischar(aty)) {
00251         if (t == SCON) {
00252             if (ty->size > 0 && ty->size == tsym->type->size - 1)
00253                 tsym->type = array(chartype, ty->size, 0);
00254             n = tsym->type->size;
00255             (*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
00256             t = gettok();
00257         } else if (t == '{') {
00258             t = gettok();
00259             if (t == SCON) {
00260                 ty = initializer(ty, lev + 1);
00261                 initend(lev, follow);
00262                 return ty;
00263             }
00264             n = initchar(0, aty);
00265             test('}', follow);
00266         } else if (lev > 0 && ty->size > 0)
00267             n = initchar(ty->size, aty);
00268         else {  /* eg, char c[] = 0; */
00269             error("missing { in initialization of `%t'\n", ty);
00270             n = initchar(1, aty);
00271         }
00272     } else if (isarray(ty)) {
00273         if (t == SCON && aty == widechar) {
00274             int i;
00275             unsigned int *s = tsym->u.c.v.p;
00276             if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)
00277                 tsym->type = array(widechar, ty->size/widechar->size, 0);
00278             n = tsym->type->size;
00279             for (i = 0; i < n; i += widechar->size) {
00280                 Value v;
00281                 v.u = *s++;
00282                 (*IR->defconst)(widechar->op, widechar->size, v);
00283             }
00284             t = gettok();
00285         } else if (t == '{') {
00286             t = gettok();
00287             if (t == SCON && aty == widechar) {
00288                 ty = initializer(ty, lev + 1);
00289                 initend(lev, follow);
00290                 return ty;
00291             }
00292             n = initarray(0, aty, lev + 1);
00293             test('}', follow);
00294         } else if (lev > 0 && ty->size > 0)
00295             n = initarray(ty->size, aty, lev + 1);
00296         else {
00297             error("missing { in initialization of `%t'\n", ty);
00298             n = initarray(aty->size, aty, lev + 1);
00299         }
00300     }   
00301     if (ty->size) {
00302         if (n > ty->size)
00303             error("too many initializers\n");
00304         else if (n < ty->size)
00305             (*IR->space)(ty->size - n);
00306     } else if (isarray(ty) && ty->type->size > 0)
00307         ty = array(ty->type, n/ty->type->size, 0);
00308     else
00309         ty->size = n;
00310     return ty;
00311 }
00312 
00313 /* swtoseg - switch to segment seg, if necessary */
00314 void swtoseg(int seg) {
00315     if (curseg != seg)
00316         (*IR->segment)(seg);
00317     curseg = seg;
00318 }

Generated on Thu Aug 25 12:38:14 2005 for Quake III Arena by  doxygen 1.3.9.1