?? 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 2
static 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_ 100
static 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 + -