3 * (C) Copyright Feb 2 1996, Edmond J. Breen.
5 * This code may be copied for personal, non-profit use only.
21 /*ppint expr(int k);*/
23 /* typedef unsigned long ppint; the preprocessor integer */
27 long s; /* signed value */
28 unsigned long u; /* unsigned value */
33 #define sval(x) ((x).v.s)
34 #define uval(x) ((x).v.u)
35 #define tval(x) ((x).type)
40 static ppint do_binary(int tk, ppint left, ppint right);
41 static int getTok(int k);
42 static ppint EiC_expr_unary(void);
43 static ppint get_number(void);
44 static ppint EiC_ifexpr(int k);
47 enum { LOR = 1, LAND, BOR, XOR, AND, EQ, NEQ, LT, LEQ,
48 GT, GEQ, LSHFT, RSHFT,PLUS, MINUS, TIMES, DIV, MOD};
55 static void replaceDefines(char *S)
62 if(!cmode && (isalpha(*S) || *S == '_')) {
63 if(S[0] == 'd' && S[1] == 'e' &&
64 S[2] == 'f' && S[3] == 'i' &&
65 S[4] == 'n' && S[5] == 'e' &&
66 S[6] == 'd' && !isalpha(S[7]) &&
78 while(i < 50 && (isalpha(*S) || *S == '_' || isdigit(*S)))
84 EiC_pre_error("Missing ')'");
89 if(EiC_ismacroid(str) > -1)
95 EiC_pre_error("Missing identifier");
100 while(isalpha(*S) || *S == '_' );
109 static void replaceIdentifiers(char *S)
123 if(!isalpha(*S) && *S != '_') {
124 if(isdigit(*S) || *S == '\'') { /* skip throu numbers or literals*/
125 while(*S && !isspace(*S))
128 while(*S && !isspace(*S) && *S != '_' && ispunct(*S))
134 while(i < 50 && (isalpha(*S) || *S == '_' || isdigit(*S)) )
137 if(strcmp(str,"sizeof") == 0)
138 EiC_pre_error("Illegal sizeof operator");
147 int EiC_cpp_parse(char *s)
155 printf("return [%s]\n",S);
158 S = s = EiC_process2(S,0,0);
160 replaceIdentifiers(S);
163 printf("return [%s]\n",S);
171 if(tval(res) == SIGN)
177 static ppint EiC_ifexpr(int k)
181 res = EiC_expr_unary();
182 for(k1 = 10; k1 >= k; k1--)
183 while((tk = getTok(k1)))
184 res = do_binary(tk, res,EiC_ifexpr(k1>8?k1:k1+1));
188 #define eval(a,l,r,op)\
191 sval(a) = sval(l) op sval(r);\
193 uval(a) = uval(l) op uval(r);\
197 static ppint do_binary(int tk, ppint left, ppint right)
201 if(tval(left) == USIGN || tval(right) == USIGN)
202 tval(r) = tval(left) = tval(right) = USIGN;
204 tval(r) = tval(left) = tval(right) = SIGN;
209 case BOR: eval(r,left,right, | ); break;
210 case XOR: eval(r,left,right, ^ ); break;
211 case AND: eval(r,left,right, & ); break;
212 case LT: eval(r,left,right, < ); break;
213 case LEQ: eval(r,left,right, <= ); break;
214 case EQ: eval(r,left,right, == ); break;
215 case NEQ: eval(r,left,right, != ); break;
216 case GT: eval(r,left,right, > ); break;
217 case GEQ: eval(r,left,right, >= ); break;
218 case LOR: eval(r,left,right, || ); break;
219 case LAND: eval(r,left,right, && ); break;
220 case LSHFT: eval(r,left,right, << ); break;
221 case RSHFT: eval(r,left,right, >> ); break;
222 case PLUS: eval(r,left,right, + ); break;
223 case MINUS: eval(r,left,right, - ); break;
224 case TIMES: eval(r,left,right, * ); break;
225 case DIV: eval(r,left,right, / ); break;
226 case MOD: eval(r,left,right, % ); break;
231 static int getTok(int k)
240 if(*S == '|' && *(S+1) == '|') {S+=2; TK = LOR;}
243 if(*S == '&' && *(S+1) == '&') {S+=2; TK = LAND;}
245 if(*S == '|' && *(S+1) != '|') {S++; TK = BOR;}
248 if(*S == '^') {S++; TK = GEQ;}
251 if(*S == '&' && *(S+1) != '&') {S++; TK = GEQ;}
253 case 6: /* EQ, NEQ */
254 if(*S == '=' && *(S+1) == '=') {S+=2; TK = EQ;}
255 else if(*S == '!' && *(S+1) == '=') {S+=2; TK = NEQ;}
257 case 7: /* LT, LEQ, GT, GEQ */
260 if(*S == '='){S++;TK = LEQ;}
262 } else if(*S == '>') {
264 if(*S == '='){S++; TK = GEQ;}
268 case 8: /* LSHFT, RSHFT */
269 if(*S == '<' && *(S+1) == '<') {S+=2; TK = LSHFT;}
270 else if(*S == '>' && *(S+1) == '>') {S+=2; TK = RSHFT;}
272 case 9: /* PLUS, MINUS */
273 if(*S == '-') {S++;TK = MINUS;}
274 else if(*S == '+') {S++; TK = PLUS;}
276 case 10: /* TIMES, DIV, MOD */
277 if(*S == '*') {S++;TK = TIMES;}
278 else if(*S == '/') {S++; TK = DIV;}
279 else if(*S == '%') {S++; TK = MOD;}
285 static int get_oct(int x)
287 return x>='0'&&x<='7'? x-'0':-1;
290 static int get_hex(int x)
293 if (x >= '0' && x <= '9')
295 else if (x >= 'a' && x <= 'f')
297 else if (x >= 'A' && x <= 'F')
304 static int get_dec(int x)
306 return x >= '0' && x <= '9' ? x-'0':-1;
310 static ppint get_number() /* collect hex, octal and decimal integers */
314 ppint res = {{0},SIGN};
318 if(*S == 'x' || *S == 'X') { /* get hex number */
322 } else { /* get octal number */
326 } else { /* get decimal number */
330 while((val = (*f)(*S++)) >= 0)
331 uval(res) = uval(res) * radix + val;
334 if(uval(res) > LONG_MAX)
337 /* check for prefix */
338 if(*S=='u' || *S=='U') {
341 } if(*S=='l' || *S=='L')
347 static int get_charConst()
352 case 'n': c = '\n'; break; /* newline */
353 case 't': c = '\t'; break; /* tabspace */
354 case 'v': c = '\v'; break; /* vertical tab */
355 case 'b': c = '\b'; break; /* backspace */
356 case 'r': c = '\r'; break; /* carriage return */
357 case 'f': c = '\f'; break; /* formfeed */
358 case 'a': c = '\a'; break; /* bell */
359 case '\\': c = '\\'; break; /* backslash */
360 case '\'': c = '\''; break; /* single quote */
361 case '"': c = '\"'; break; /* double quote */
362 case 'x': /* string of hex characters */
366 while ((i = get_hex(*S)) > -1) {
371 EiC_pre_error("Illegal character hex value");
376 if (isdigit(*S)) { /* treat as octal characters */
378 while ((i = get_oct(*S)) > -1) {
383 EiC_pre_error("Illegal character octal value");
386 EiC_pre_error("Illegal character escape sequence `\\%c'", *S);
394 static ppint EiC_expr_unary()
402 } else if( *S == '(') {
406 EiC_pre_error("Unbalanced parenthesis");
408 } else if(*S == '!') {
410 res = EiC_expr_unary();
411 uval(res) = !uval(res);
412 } else if(*S == '-') {
415 EiC_pre_error("-- not allowed in operand of #if");
416 res = EiC_expr_unary();
418 sval(res) = -uval(res);
419 } else if(*S == '+') {
422 EiC_pre_error("++ not allowed in operand of #if");
423 res = EiC_expr_unary();
424 } else if(*S == '~') {
426 res = EiC_expr_unary();
427 uval(res) = ~uval(res);
428 } else if(*S == '\'') { /* char constants */
432 uval(res) = get_charConst();
436 EiC_pre_error("Missing closing single quote '");
441 EiC_pre_error("Illegal constant expression");