Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

init.c (7788B)


      1 #include "c.h"
      2 
      3 
      4 static int curseg;		/* current segment */
      5 
      6 /* defpointer - initialize a pointer to p or to 0 if p==0 */
      7 void defpointer(Symbol p) {
      8 	if (p) {
      9 		(*IR->defaddress)(p);
     10 		p->ref++;
     11 	} else {
     12 		static Value v;
     13 		(*IR->defconst)(P, voidptype->size, v);
     14 	}
     15 }
     16 
     17 /* genconst - generate/check constant expression e; return size */
     18 static int genconst(Tree e, int def) {
     19 	for (;;)
     20 		switch (generic(e->op)) {
     21 		case ADDRG:
     22 			if (def)
     23 				(*IR->defaddress)(e->u.sym);
     24 			return e->type->size;
     25 		case CNST:
     26 			if (e->op == CNST+P && isarray(e->type)) {
     27 				e = cvtconst(e);
     28 				continue;
     29 			}
     30 			if (def)
     31 				(*IR->defconst)(e->type->op, e->type->size, e->u.v);
     32 			return e->type->size;
     33 		case RIGHT:
     34 			assert(e->kids[0] || e->kids[1]);
     35 			if (e->kids[1] && e->kids[0])
     36 				error("initializer must be constant\n");
     37 			e = e->kids[1] ? e->kids[1] : e->kids[0];
     38 			continue;
     39 		case CVP:
     40 			if (isarith(e->type))
     41 				error("cast from `%t' to `%t' is illegal in constant expressions\n",
     42 					e->kids[0]->type, e->type);
     43 			/* fall thru */
     44 		case CVI: case CVU: case CVF:
     45 			e = e->kids[0];
     46 			continue;
     47 		default:
     48 			error("initializer must be constant\n");
     49 			if (def)
     50 				genconst(consttree(0, inttype), def);
     51 			return inttype->size;
     52 		}
     53 }
     54 
     55 /* initvalue - evaluate a constant expression for a value of integer type ty */
     56 static Tree initvalue(Type ty) {
     57 	Type aty;
     58 	Tree e;
     59 
     60 	needconst++;
     61 	e = expr1(0);
     62 	if ((aty = assign(ty, e)) != NULL)
     63 		e = cast(e, aty);
     64 	else {
     65 		error("invalid initialization type; found `%t' expected `%t'\n",
     66 			e->type,  ty);
     67 		e = retype(consttree(0, inttype), ty);
     68 	}
     69 	needconst--;
     70 	if (generic(e->op) != CNST) {
     71 		error("initializer must be constant\n");
     72 		e = retype(consttree(0, inttype), ty);
     73 	}
     74 	return e;
     75 }
     76 
     77 /* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
     78 static int initarray(int len, Type ty, int lev) {
     79 	int n = 0;
     80 
     81 	do {
     82 		initializer(ty, lev);
     83 		n += ty->size;
     84 		if (len > 0 && n >= len || t != ',')
     85 			break;
     86 		t = gettok();
     87 	} while (t != '}');
     88 	return n;
     89 }
     90 
     91 /* initchar - initialize array of <= len ty characters; if len == 0, go to } */
     92 static int initchar(int len, Type ty) {
     93 	int n = 0;
     94 	char buf[16], *s = buf;
     95 
     96 	do {
     97 		*s++ = initvalue(ty)->u.v.i;
     98 		if (++n%inttype->size == 0) {
     99 			(*IR->defstring)(inttype->size, buf);
    100 			s = buf;
    101 		}
    102 		if (len > 0 && n >= len || t != ',')
    103 			break;
    104 		t = gettok();
    105 	} while (t != '}');
    106 	if (s > buf)
    107 		(*IR->defstring)(s - buf, buf);
    108 	return n;
    109 }
    110 
    111 /* initend - finish off an initialization at level lev; accepts trailing comma */
    112 static void initend(int lev, char follow[]) {
    113 	if (lev == 0 && t == ',')
    114 		t = gettok();
    115 	test('}', follow);
    116 }
    117 
    118 /* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
    119 static int initfields(Field p, Field q) {
    120 	unsigned int bits = 0;
    121 	int i, n = 0;
    122 
    123 	do {
    124 		i = initvalue(inttype)->u.v.i;
    125 		if (fieldsize(p) < 8*p->type->size) {
    126 			if (p->type == inttype &&
    127 			   (i < -(int)(fieldmask(p)>>1)-1 || i > (int)(fieldmask(p)>>1))
    128 			||  p->type == unsignedtype && (i&~fieldmask(p)) !=  0)
    129 				warning("initializer exceeds bit-field width\n");
    130 			i &= fieldmask(p);
    131 		}
    132 		bits |= i<<fieldright(p);
    133 		if (IR->little_endian) {
    134 			if (fieldsize(p) + fieldright(p) > n)
    135 				n = fieldsize(p) + fieldright(p);
    136 		} else {
    137 			if (fieldsize(p) + fieldleft(p) > n)
    138 				n = fieldsize(p) + fieldleft(p);
    139 		}
    140 		if (p->link == q)
    141 			break;
    142 		p = p->link;
    143 	} while (t == ',' && (t = gettok()) != 0);
    144 	n = (n + 7)/8;
    145 	for (i = 0; i < n; i++) {
    146 		Value v;
    147 		if (IR->little_endian) {
    148 			v.u = (unsigned char)bits;
    149 			bits >>= 8;
    150 		} else {	/* a big endian */
    151 			v.u = (unsigned char)(bits>>(8*(unsignedtype->size - 1)));
    152 			bits <<= 8;
    153 		}
    154 		(*IR->defconst)(U, unsignedchar->size, v);
    155 	}
    156 	return n;
    157 }
    158 
    159 /* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
    160 static int initstruct(int len, Type ty, int lev) {
    161 	int a, n = 0;
    162 	Field p = ty->u.sym->u.s.flist;
    163 
    164 	do {
    165 		if (p->offset > n) {
    166 			(*IR->space)(p->offset - n);
    167 			n += p->offset - n;
    168 		}
    169 		if (p->lsb) {
    170 			Field q = p;
    171 			while (q->link && q->link->offset == p->offset)
    172 				q = q->link;
    173 			n += initfields(p, q->link);
    174 			p = q;
    175 		} else {
    176 			initializer(p->type, lev);
    177 			n += p->type->size;
    178 		}
    179 		if (p->link) {
    180 			p = p->link;
    181 			a = p->type->align;
    182 		} else
    183 			a = ty->align;
    184 		if (a && n%a) {
    185 			(*IR->space)(a - n%a);
    186 			n = roundup(n, a);
    187 		}
    188 		if (len > 0 && n >= len || t != ',')
    189 			break;
    190 		t = gettok();
    191 	} while (t != '}');
    192 	return n;
    193 }
    194 
    195 /* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
    196 Type initializer(Type ty, int lev) {
    197 	int n = 0;
    198 	Tree e;
    199 	Type aty = NULL;
    200 	static char follow[] = { IF, CHAR, STATIC, 0 };
    201 
    202 	ty = unqual(ty);
    203 	if (isscalar(ty)) {
    204 		needconst++;
    205 		if (t == '{') {
    206 			t = gettok();
    207 			e = expr1(0);
    208 			initend(lev, follow);
    209 		} else
    210 			e = expr1(0);
    211 		e = pointer(e);
    212 		if ((aty = assign(ty, e)) != NULL)
    213 			e = cast(e, aty);
    214 		else
    215 			error("invalid initialization type; found `%t' expected `%t'\n",
    216 				e->type, ty);
    217 		n = genconst(e, 1);
    218 		deallocate(STMT);
    219 		needconst--;
    220 	}
    221 	if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
    222 		static char follow[] = { CHAR, STATIC, 0 };
    223 		error("cannot initialize undefined `%t'\n", ty);
    224 		skipto(';', follow);
    225 		return ty;
    226 	} else if (isunion(ty)) {
    227 		if (t == '{') {
    228 			t = gettok();
    229 			n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
    230 			initend(lev, follow);
    231 		} else {
    232 			if (lev == 0)
    233 				error("missing { in initialization of `%t'\n", ty);
    234 			n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
    235 		}
    236 	} else if (isstruct(ty)) {
    237 		if (t == '{') {
    238 			t = gettok();
    239 			n = initstruct(0, ty, lev + 1);
    240 			test('}', follow);
    241 		} else if (lev > 0)
    242 			n = initstruct(ty->size, ty, lev + 1);
    243 		else {
    244 			error("missing { in initialization of `%t'\n", ty);
    245 			n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
    246 		}
    247 	}
    248 	if (isarray(ty))
    249 		aty = unqual(ty->type);
    250 	if (isarray(ty) && ischar(aty)) {
    251 		if (t == SCON) {
    252 			if (ty->size > 0 && ty->size == tsym->type->size - 1)
    253 				tsym->type = array(chartype, ty->size, 0);
    254 			n = tsym->type->size;
    255 			(*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
    256 			t = gettok();
    257 		} else if (t == '{') {
    258 			t = gettok();
    259 			if (t == SCON) {
    260 				ty = initializer(ty, lev + 1);
    261 				initend(lev, follow);
    262 				return ty;
    263 			}
    264 			n = initchar(0, aty);
    265 			test('}', follow);
    266 		} else if (lev > 0 && ty->size > 0)
    267 			n = initchar(ty->size, aty);
    268 		else {	/* eg, char c[] = 0; */
    269 			error("missing { in initialization of `%t'\n", ty);
    270 			n = initchar(1, aty);
    271 		}
    272 	} else if (isarray(ty)) {
    273 		if (t == SCON && aty == widechar) {
    274 			int i;
    275 			unsigned int *s = tsym->u.c.v.p;
    276 			if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)
    277 				tsym->type = array(widechar, ty->size/widechar->size, 0);
    278 			n = tsym->type->size;
    279 			for (i = 0; i < n; i += widechar->size) {
    280 				Value v;
    281 				v.u = *s++;
    282 				(*IR->defconst)(widechar->op, widechar->size, v);
    283 			}
    284 			t = gettok();
    285 		} else if (t == '{') {
    286 			t = gettok();
    287 			if (t == SCON && aty == widechar) {
    288 				ty = initializer(ty, lev + 1);
    289 				initend(lev, follow);
    290 				return ty;
    291 			}
    292 			n = initarray(0, aty, lev + 1);
    293 			test('}', follow);
    294 		} else if (lev > 0 && ty->size > 0)
    295 			n = initarray(ty->size, aty, lev + 1);
    296 		else {
    297 			error("missing { in initialization of `%t'\n", ty);
    298 			n = initarray(aty->size, aty, lev + 1);
    299 		}
    300 	}	
    301 	if (ty->size) {
    302 		if (n > ty->size)
    303 			error("too many initializers\n");
    304 		else if (n < ty->size)
    305 			(*IR->space)(ty->size - n);
    306 	} else if (isarray(ty) && ty->type->size > 0)
    307 		ty = array(ty->type, n/ty->type->size, 0);
    308 	else
    309 		ty->size = n;
    310 	return ty;
    311 }
    312 
    313 /* swtoseg - switch to segment seg, if necessary */
    314 void swtoseg(int seg) {
    315 	if (curseg != seg)
    316 		(*IR->segment)(seg);
    317 	curseg = seg;
    318 }