📄 preexpr.c
字号:
/* preexpr.c * * (C) Copyright Feb 2 1996, Edmond J. Breen. * ALL RIGHTS RESERVED. * This code may be copied for personal, non-profit use only. * */#ifndef _STANDALONE#include <stdio.h>#include <ctype.h>#include <string.h>#include <limits.h>#include "xalloc.h"#include "preproc.h"#endif/*ppint expr(int k);*//* typedef unsigned long ppint; the preprocessor integer */typedef struct { union { long s; /* signed value */ unsigned long u; /* unsigned value */ }v; int type;}ppint;/* methods */#define sval(x) ((x).v.s)#define uval(x) ((x).v.u)#define tval(x) ((x).type)#define USIGN 1#define SIGN 2static ppint do_binary(int tk, ppint left, ppint right);static int getTok(int k);static ppint EiC_expr_unary(void);static ppint get_number(void);static ppint EiC_ifexpr(int k);enum { LOR = 1, LAND, BOR, XOR, AND, EQ, NEQ, LT, LEQ, GT, GEQ, LSHFT, RSHFT,PLUS, MINUS, TIMES, DIV, MOD};static char *S;static int TK =0;#define _StrSz_ 100static void replaceDefines(char *S){ char str[50]; int cmode = 0; char *p; p = S; while(*S != '\0') { if(!cmode && (isalpha(*S) || *S == '_')) { if(S[0] == 'd' && S[1] == 'e' && S[2] == 'f' && S[3] == 'i' && S[4] == 'n' && S[5] == 'e' && S[6] == 'd' && !isalpha(S[7]) && S[7] != '_') { int br = 0; int i; S+=7; skipfws(S); if(*S=='(') { S++; br = 1; skipfws(S); } i = 0; while(i < 50 && (isalpha(*S) || *S == '_' || isdigit(*S))) str[i++] = *S++; str[i] = '\0'; if(br) { skipfws(S); if(*S != ')') EiC_pre_error("Missing ')'"); else S++; } if(str[0] != '\0') { if(EiC_ismacroid(str) > -1) *p = '1'; else *p = '0'; ++p; } else EiC_pre_error("Missing identifier"); continue; } do *p++ = *S++; while(isalpha(*S) || *S == '_' ); continue; } if(*S == '\'') cmode = !cmode; *p++ = *S++; } *p = '\0';}static void replaceIdentifiers(char *S){ int i; char str[50]; char *p; int cmode = 0; p = S; while(1) { while(isspace(*S)) *p++ = *S++; if(!*S) return; if(!isalpha(*S) && *S != '_') { if(isdigit(*S) || *S == '\'') { /* skip throu numbers or literals*/ while(*S && !isspace(*S)) *p++ = *S++; } else while(*S && !isspace(*S) && *S != '_' && ispunct(*S)) *p++ = *S++; continue; } if(!cmode) { i = 0; while(i < 50 && (isalpha(*S) || *S == '_' || isdigit(*S)) ) str[i++] = *S++; str[i] = '\0'; if(strcmp(str,"sizeof") == 0) EiC_pre_error("Illegal sizeof operator"); else *p++ = '0'; } else *p++ = *S++; }}int EiC_cpp_parse(char *s){ ppint res; S = s; replaceDefines(S);#ifdef DEBUG printf("return [%s]\n",S);#endif S = s = EiC_process2(S,0,0); replaceIdentifiers(S);#ifdef DEBUG printf("return [%s]\n",S);#endif res = EiC_ifexpr(0); if(s) xfree(s); if(tval(res) == SIGN) return sval(res); else return uval(res);}static ppint EiC_ifexpr(int k){ ppint res; int k1, tk; res = EiC_expr_unary(); for(k1 = 10; k1 >= k; k1--) while((tk = getTok(k1))) res = do_binary(tk, res,EiC_ifexpr(k1>8?k1:k1+1)); return res;}#define eval(a,l,r,op)\{\ if(tval(l) == SIGN)\ sval(a) = sval(l) op sval(r);\ else\ uval(a) = uval(l) op uval(r);\} static ppint do_binary(int tk, ppint left, ppint right){ ppint r; if(tval(left) == USIGN || tval(right) == USIGN) tval(r) = tval(left) = tval(right) = USIGN; else tval(r) = tval(left) = tval(right) = SIGN; switch(tk) { case BOR: eval(r,left,right, | ); break; case XOR: eval(r,left,right, ^ ); break; case AND: eval(r,left,right, & ); break; case LT: eval(r,left,right, < ); break; case LEQ: eval(r,left,right, <= ); break; case EQ: eval(r,left,right, == ); break; case NEQ: eval(r,left,right, != ); break; case GT: eval(r,left,right, > ); break; case GEQ: eval(r,left,right, >= ); break; case LOR: eval(r,left,right, || ); break; case LAND: eval(r,left,right, && ); break; case LSHFT: eval(r,left,right, << ); break; case RSHFT: eval(r,left,right, >> ); break; case PLUS: eval(r,left,right, + ); break; case MINUS: eval(r,left,right, - ); break; case TIMES: eval(r,left,right, * ); break; case DIV: eval(r,left,right, / ); break; case MOD: eval(r,left,right, % ); break; } return r;}static int getTok(int k){ TK = 0; while(isspace(*S)) S++; switch(k) { case 1: /* LOR */ if(*S == '|' && *(S+1) == '|') {S+=2; TK = LOR;} break; case 2: /* LAND */ if(*S == '&' && *(S+1) == '&') {S+=2; TK = LAND;} case 3: /* BOR */ if(*S == '|' && *(S+1) != '|') {S++; TK = BOR;} break; case 4: /* XOR */ if(*S == '^') {S++; TK = GEQ;} break; case 5: /* AND */ if(*S == '&' && *(S+1) != '&') {S++; TK = GEQ;} break; case 6: /* EQ, NEQ */ if(*S == '=' && *(S+1) == '=') {S+=2; TK = EQ;} else if(*S == '!' && *(S+1) == '=') {S+=2; TK = NEQ;} break; case 7: /* LT, LEQ, GT, GEQ */ if(*S == '<') { S++; if(*S == '='){S++;TK = LEQ;} else TK = LT; } else if(*S == '>') { S++; if(*S == '='){S++; TK = GEQ;} else TK = GT; } break; case 8: /* LSHFT, RSHFT */ if(*S == '<' && *(S+1) == '<') {S+=2; TK = LSHFT;} else if(*S == '>' && *(S+1) == '>') {S+=2; TK = RSHFT;} break; case 9: /* PLUS, MINUS */ if(*S == '-') {S++;TK = MINUS;} else if(*S == '+') {S++; TK = PLUS;} break; case 10: /* TIMES, DIV, MOD */ if(*S == '*') {S++;TK = TIMES;} else if(*S == '/') {S++; TK = DIV;} else if(*S == '%') {S++; TK = MOD;} break; } return TK;}static int get_oct(int x){ return x>='0'&&x<='7'? x-'0':-1;}static int get_hex(int x){ if (x >= '0' && x <= '9') x -= '0'; else if (x >= 'a' && x <= 'f') x = x - 'a' + 10; else if (x >= 'A' && x <= 'F') x = x - 'A' + 10; else x = -1; return x;}static int get_dec(int x){ return x >= '0' && x <= '9' ? x-'0':-1;}static ppint get_number() /* collect hex, octal and decimal integers */{ int (*f)(int x); int radix,val; ppint res = {{0},SIGN}; if(*S == '0') { S++; if(*S == 'x' || *S == 'X') { /* get hex number */ S++; radix = 16; f = get_hex; } else { /* get octal number */ radix = 8; f = get_oct; } } else { /* get decimal number */ radix = 10; f = get_dec; } while((val = (*f)(*S++)) >= 0) uval(res) = uval(res) * radix + val; S--; if(uval(res) > LONG_MAX) tval(res) = USIGN; /* check for prefix */ if(*S=='u' || *S=='U') { S++; tval(res) = USIGN; } if(*S=='l' || *S=='L') S++; return res;} static int get_charConst(){ int c; switch (*S) { case 'n': c = '\n'; break; /* newline */ case 't': c = '\t'; break; /* tabspace */ case 'v': c = '\v'; break; /* vertical tab */ case 'b': c = '\b'; break; /* backspace */ case 'r': c = '\r'; break; /* carriage return */ case 'f': c = '\f'; break; /* formfeed */ case 'a': c = '\a'; break; /* bell */ case '\\': c = '\\'; break; /* backslash */ case '\'': c = '\''; break; /* single quote */ case '"': c = '\"'; break; /* double quote */ case 'x': /* string of hex characters */ case 'X':{ int i, val = 0; S++; while ((i = get_hex(*S)) > -1) { S++; val = val * 16 + i; } if (val > 255) EiC_pre_error("Illegal character hex value"); c = val; } break; default: if (isdigit(*S)) { /* treat as octal characters */ int i, val = 0; while ((i = get_oct(*S)) > -1) { val = val * 8 + i; S++; } if (val > 255) EiC_pre_error("Illegal character octal value"); c = val; } else { EiC_pre_error("Illegal character escape sequence `\\%c'", *S); c = *S++; } break; } return c;}static ppint EiC_expr_unary(){ ppint res; while(isspace(*S)) S++; if(isdigit(*S)) { res = get_number(); } else if( *S == '(') { S++; res = EiC_ifexpr(0); if(*S != ')') EiC_pre_error("Unbalanced parenthesis"); S++; } else if(*S == '!') { S++; res = EiC_expr_unary(); uval(res) = !uval(res); } else if(*S == '-') { S++; if(*S == '-') EiC_pre_error("-- not allowed in operand of #if"); res = EiC_expr_unary(); tval(res) = SIGN; sval(res) = -uval(res); } else if(*S == '+') { S++; if(*S == '+') EiC_pre_error("++ not allowed in operand of #if"); res = EiC_expr_unary(); } else if(*S == '~') { S++; res = EiC_expr_unary(); uval(res) = ~uval(res); } else if(*S == '\'') { /* char constants */ S++; if(*S == '\\') { S++; uval(res) = get_charConst(); } else uval(res) = *S++; if(*S != '\'') EiC_pre_error("Missing closing single quote '"); else S++; tval(res) = SIGN; } else EiC_pre_error("Illegal constant expression"); return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -