📄 cpp5.c
字号:
#if OK_SIZEOFelse if (streq(global->tokenbuf, "sizeof")) { /* New sizeof hackery */ ret=dosizeof(global, op); /* Gets own routine */ return(ret);}#endif global->evalue = 0; *op=DIG; return(FPP_OK); } else if (t == DIG) { /* Numbers are harder */ global->evalue = evalnum(global, c); } else if (strchr("!=<>&|\\", c) != NULL) { /* * Process a possible multi-byte lexeme. */ c1 = cget(global); /* Peek at next char */ switch (c) { case '!': if (c1 == '=') { *op=OP_NE; return(FPP_OK); } break; case '=': if (c1 != '=') { /* Can't say a=b in #if */ unget(global); cerror(global, ERROR_ILLEGAL_ASSIGN); return (FPP_IF_ERROR); } *op=OP_EQ; return(FPP_OK); case '>': case '<': if (c1 == c) { *op= ((c == '<') ? OP_ASL : OP_ASR); return(FPP_OK); } else if (c1 == '=') { *op= ((c == '<') ? OP_LE : OP_GE); return(FPP_OK); } break; case '|': case '&': if (c1 == c) { *op= ((c == '|') ? OP_ORO : OP_ANA); return(FPP_OK); } break; case '\\': if (c1 == '\n') { /* Multi-line if */ loop=TRUE; break; } cerror(global, ERROR_ILLEGAL_BACKSLASH); return(FPP_IF_ERROR); } if(!loop) unget(global); } } while(loop); *op=t; return(FPP_OK);}#if OK_SIZEOFINLINE FILE_LOCALReturnCode dosizeof(struct Global *global, int *result){ /* * Process the sizeof (basic type) operation in an #if string. * Sets evalue to the size and returns * DIG success * OP_FAIL bad parse or something. */ int c; TYPES *tp; SIZES *sizp; short *testp; short typecode; ReturnCode ret; if ((c = skipws(global)) != '(') { unget(global); cerror(global, ERROR_SIZEOF_SYNTAX); return(FPP_SIZEOF_ERROR); } /* * Scan off the tokens. */ typecode = 0; while ((c = skipws(global))) { if(ret=macroid(global, &c)) return(ret); /* (I) return on fail! */ if (c == EOF_CHAR || c == '\n') { /* End of line is a bug */ unget(global); cerror(global, ERROR_SIZEOF_SYNTAX); return(FPP_SIZEOF_ERROR); } else if (c == '(') { /* thing (*)() func ptr */ if (skipws(global) == '*' && skipws(global) == ')') { /* We found (*) */ if (skipws(global) != '(') /* Let () be optional */ unget(global); else if (skipws(global) != ')') { unget(global); cerror(global, ERROR_SIZEOF_SYNTAX); return(FPP_SIZEOF_ERROR); } typecode |= T_FPTR; /* Function pointer */ } else { /* Junk is a bug */ unget(global); cerror(global, ERROR_SIZEOF_SYNTAX); return(FPP_SIZEOF_ERROR); } } else if (type[c] != LET) /* Exit if not a type */ break; else if (!catenate(global, &ret) && !ret) { /* Maybe combine tokens */ /* * Look for this unexpandable token in basic_types. * The code accepts "int long" as well as "long int" * which is a minor bug as bugs go (and one shared with * a lot of C compilers). */ for (tp = basic_types; tp->name != NULLST; tp++) { if (streq(global->tokenbuf, tp->name)) break; } if (tp->name == NULLST) { cerror(global, ERROR_SIZEOF_UNKNOWN, global->tokenbuf); return(FPP_SIZEOF_ERROR); } typecode |= tp->type; /* Or in the type bit */ } else if(ret) return(ret); } /* * We are at the end of the type scan. Chew off '*' if necessary. */ if (c == '*') { typecode |= T_PTR; c = skipws(global); } if (c == ')') { /* Last syntax check */ for (testp = test_table; *testp != 0; testp++) { if (!bittest(typecode & *testp)) { cerror(global, ERROR_SIZEOF_ILLEGAL_TYPE); return(FPP_SIZEOF_ERROR); } } /* * We assume that all function pointers are the same size: * sizeof (int (*)()) == sizeof (float (*)()) * We assume that signed and unsigned don't change the size: * sizeof (signed int) == (sizeof unsigned int) */ if ((typecode & T_FPTR) != 0) /* Function pointer */ typecode = T_FPTR | T_PTR; else { /* Var or var * datum */ typecode &= ~(T_SIGNED | T_UNSIGNED); if ((typecode & (T_SHORT | T_LONG)) != 0) typecode &= ~T_INT; } if ((typecode & ~T_PTR) == 0) { cerror(global, ERROR_SIZEOF_NO_TYPE); return(FPP_SIZEOF_ERROR); } /* * Exactly one bit (and possibly T_PTR) may be set. */ for (sizp = size_table; sizp->bits != 0; sizp++) { if ((typecode & ~T_PTR) == sizp->bits) { global->evalue = ((typecode & T_PTR) != 0) ? sizp->psize : sizp->size; *result=DIG; return(FPP_OK); } } /* We shouldn't fail */ cerror(global, ERROR_SIZEOF_BUG, typecode); return(FPP_SIZEOF_ERROR); } unget(global); cerror(global, ERROR_SIZEOF_SYNTAX); return(FPP_SIZEOF_ERROR);}INLINE FILE_LOCALint bittest(int value){ /* * TRUE if value is zero or exactly one bit is set in value. */#if (4096 & ~(-4096)) == 0 return ((value & ~(-value)) == 0);#else /* * Do it the hard way (for non 2's complement machines) */ return (value == 0 || value ^ (value - 1) == (value * 2 - 1));#endif}#endif /* OK_SIZEOF */INLINE FILE_LOCALint evalnum(struct Global *global, int c){ /* * Expand number for #if lexical analysis. Note: evalnum recognizes * the unsigned suffix, but only returns a signed int value. */ int value; int base; int c1; if (c != '0') base = 10; else if ((c = cget(global)) == 'x' || c == 'X') { base = 16; c = cget(global); } else base = 8; value = 0; for (;;) { c1 = c; if (isascii(c) && isupper(c1)) c1 = tolower(c1); if (c1 >= 'a') c1 -= ('a' - 10); else c1 -= '0'; if (c1 < 0 || c1 >= base) break; value *= base; value += c1; c = cget(global); } if (c == 'u' || c == 'U') /* Unsigned nonsense */ c = cget(global); unget(global); return (value);}INLINE FILE_LOCALint evalchar(struct Global *global, int skip) /* TRUE if short-circuit evaluation */ /* * Get a character constant */{ int c; int value; int count; global->instring = TRUE; if ((c = cget(global)) == '\\') { switch ((c = cget(global))) { case 'a': /* New in Standard */#if ('a' == '\a' || '\a' == ALERT) value = ALERT; /* Use predefined value */#else value = '\a'; /* Use compiler's value */#endif break; case 'b': value = '\b'; break; case 'f': value = '\f'; break; case 'n': value = '\n'; break; case 'r': value = '\r'; break; case 't': value = '\t'; break; case 'v': /* New in Standard */#if ('v' == '\v' || '\v' == VT) value = VT; /* Use predefined value */#else value = '\v'; /* Use compiler's value */#endif break; case 'x': /* '\xFF' */ count = 3; value = 0; while ((((c = get(global)) >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) && (--count >= 0)) { value *= 16; value += (c <= '9') ? (c - '0') : ((c & 0xF) + 9); } unget(global); break; default: if (c >= '0' && c <= '7') { count = 3; value = 0; while (c >= '0' && c <= '7' && --count >= 0) { value *= 8; value += (c - '0'); c = get(global); } unget(global); } else value = c; break; } } else if (c == '\'') value = 0; else value = c; /* * We warn on multi-byte constants and try to hack * (big|little)endian machines. */#if BIG_ENDIAN count = 0;#endif while ((c = get(global)) != '\'' && c != EOF_CHAR && c != '\n') { if (!skip) cwarn(global, WARN_MULTIBYTE_NOT_PORTABLE, c);#if BIG_ENDIAN count += BITS_CHAR; value += (c << count);#else value <<= BITS_CHAR; value += c;#endif } global->instring = FALSE; return (value);}INLINE FILE_LOCALint *evaleval(struct Global *global, int *valp, int op, int skip) /* TRUE if short-circuit evaluation */{ /* * Apply the argument operator to the data on the value stack. * One or two values are popped from the value stack and the result * is pushed onto the value stack. * * OP_COL is a special case. * * evaleval() returns the new pointer to the top of the value stack. */ int v1, v2; if (isbinary(op)) v2 = *--valp; v1 = *--valp; switch (op) { case OP_EOE: break; case OP_ADD: v1 += v2; break; case OP_SUB: v1 -= v2; break; case OP_MUL: v1 *= v2; break; case OP_DIV: case OP_MOD: if (v2 == 0) { if (!skip) { cwarn(global, WARN_DIVISION_BY_ZERO, (op == OP_DIV) ? "divide" : "mod"); } v1 = 0; } else if (op == OP_DIV) v1 /= v2; else v1 %= v2; break; case OP_ASL: v1 <<= v2; break; case OP_ASR: v1 >>= v2; break; case OP_AND: v1 &= v2; break; case OP_OR: v1 |= v2; break; case OP_XOR: v1 ^= v2; break; case OP_EQ: v1 = (v1 == v2); break; case OP_NE: v1 = (v1 != v2); break; case OP_LT: v1 = (v1 < v2); break; case OP_LE: v1 = (v1 <= v2); break; case OP_GE: v1 = (v1 >= v2); break; case OP_GT: v1 = (v1 > v2); break; case OP_ANA: v1 = (v1 && v2); break; case OP_ORO: v1 = (v1 || v2); break; case OP_COL: /* * v1 has the "true" value, v2 the "false" value. * The top of the value stack has the test. */ v1 = (*--valp) ? v1 : v2; break; case OP_NEG: v1 = (-v1); break; case OP_PLU: break; case OP_COM: v1 = ~v1; break; case OP_NOT: v1 = !v1; break; default: cerror(global, ERROR_IF_OPERAND, op); v1 = 0; } *valp++ = v1; return (valp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -