cpp5.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. /******************************************************************************
  2. Copyright (c) 1999 Daniel Stenberg
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. SOFTWARE.
  18. ******************************************************************************/
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "cppdef.h"
  22. #include "cpp.h"
  23. INLINE FILE_LOCAL ReturnCode fpp_evallex(struct Global *, int, int *);
  24. INLINE FILE_LOCAL ReturnCode fpp_dosizeof(struct Global *, int *);
  25. INLINE FILE_LOCAL int fpp_bittest(int);
  26. INLINE FILE_LOCAL int fpp_evalnum(struct Global *, int);
  27. INLINE FILE_LOCAL int fpp_evalchar(struct Global *, int);
  28. INLINE FILE_LOCAL int *fpp_evaleval(struct Global *, int *, int, int);
  29. /*
  30. * Evaluate an #if expression.
  31. */
  32. static char *opname[] = { /* For debug and error messages */
  33. "end of expression", "val", "id",
  34. "+", "-", "*", "/", "%",
  35. "<<", ">>", "&", "|", "^",
  36. "==", "!=", "<", "<=", ">=", ">",
  37. "&&", "||", "?", ":", ",",
  38. "unary +", "unary -", "~", "!", "(", ")", "(none)",
  39. };
  40. /*
  41. * opdope[] has the operator precedence:
  42. * Bits
  43. * 7 Unused (so the value is always positive)
  44. * 6-2 Precedence (000x .. 017x)
  45. * 1-0 Binary op. flags:
  46. * 01 The binop flag should be set/cleared when this op is seen.
  47. * 10 The new value of the binop flag.
  48. * Note: Expected, New binop
  49. * constant 0 1 Binop, end, or ) should follow constants
  50. * End of line 1 0 End may not be preceeded by an operator
  51. * binary 1 0 Binary op follows a value, value follows.
  52. * unary 0 0 Unary op doesn't follow a value, value follows
  53. * ( 0 0 Doesn't follow value, value or unop follows
  54. * ) 1 1 Follows value. Op follows.
  55. */
  56. static char opdope[OP_MAX] = {
  57. 0001, /* End of expression */
  58. 0002, /* Digit */
  59. 0000, /* Letter (identifier) */
  60. 0141, 0141, 0151, 0151, 0151, /* ADD, SUB, MUL, DIV, MOD */
  61. 0131, 0131, 0101, 0071, 0071, /* ASL, ASR, AND, OR, XOR */
  62. 0111, 0111, 0121, 0121, 0121, 0121, /* EQ, NE, LT, LE, GE, GT */
  63. 0061, 0051, 0041, 0041, 0031, /* ANA, ORO, QUE, COL, CMA */
  64. /*
  65. * Unary op's follow
  66. */
  67. 0160, 0160, 0160, 0160, /* NEG, PLU, COM, NOT */
  68. 0170, 0013, 0023, /* LPA, RPA, END */
  69. };
  70. /*
  71. * OP_QUE and OP_RPA have alternate precedences:
  72. */
  73. #define OP_RPA_PREC 0013
  74. #define OP_QUE_PREC 0034
  75. /*
  76. * S_ANDOR and S_QUEST signal "short-circuit" boolean evaluation, so that
  77. * #if FOO != 0 && 10 / FOO ...
  78. * doesn't generate an error message. They are stored in optab.skip.
  79. */
  80. #define S_ANDOR 2
  81. #define S_QUEST 1
  82. typedef struct optab {
  83. char op; /* Operator */
  84. char prec; /* Its precedence */
  85. char skip; /* Short-circuit: FPP_TRUE to skip */
  86. } OPTAB;
  87. #ifdef nomacargs
  88. FILE_LOCAL int
  89. isbinary(op)
  90. int op;
  91. {
  92. return (op >= FIRST_BINOP && op <= LAST_BINOP);
  93. }
  94. FILE_LOCAL int
  95. isunary(op)
  96. int op;
  97. {
  98. return (op >= FIRST_UNOP && op <= LAST_UNOP);
  99. }
  100. #else
  101. #define isbinary(op) (op >= FIRST_BINOP && op <= LAST_BINOP)
  102. #define isunary(op) (op >= FIRST_UNOP && op <= LAST_UNOP)
  103. #endif
  104. /*
  105. * The following definitions are used to specify basic variable sizes.
  106. */
  107. #if OK_SIZEOF
  108. #ifndef S_CHAR
  109. #define S_CHAR (sizeof (char))
  110. #endif
  111. #ifndef S_SINT
  112. #ifdef manx /* Aztec/Manx C does not like "short int" */
  113. #define S_SINT (sizeof (short))
  114. #else
  115. #define S_SINT (sizeof (short int))
  116. #endif
  117. #endif
  118. #ifndef S_INT
  119. #define S_INT (sizeof (int))
  120. #endif
  121. #ifndef S_LINT
  122. #define S_LINT (sizeof (long int))
  123. #endif
  124. #ifndef S_FLOAT
  125. #define S_FLOAT (sizeof (float))
  126. #endif
  127. #ifndef S_DOUBLE
  128. #define S_DOUBLE (sizeof (double))
  129. #endif
  130. #ifndef S_PCHAR
  131. #define S_PCHAR (sizeof (char *))
  132. #endif
  133. #ifndef S_PSINT
  134. #ifdef manx /* Aztec/Manx C does not like "short int" */
  135. #define S_PSINT (sizeof (short *))
  136. #else
  137. #define S_PSINT (sizeof (short int *))
  138. #endif
  139. #endif
  140. #ifndef S_PINT
  141. #define S_PINT (sizeof (int *))
  142. #endif
  143. #ifndef S_PLINT
  144. #define S_PLINT (sizeof (long int *))
  145. #endif
  146. #ifndef S_PFLOAT
  147. #define S_PFLOAT (sizeof (float *))
  148. #endif
  149. #ifndef S_PDOUBLE
  150. #define S_PDOUBLE (sizeof (double *))
  151. #endif
  152. #ifndef S_PFPTR
  153. #define S_PFPTR (sizeof (int (*)()))
  154. #endif
  155. typedef struct types {
  156. short type; /* This is the bit if */
  157. char *name; /* this is the token word */
  158. } TYPES;
  159. static TYPES basic_types[] = {
  160. { T_CHAR, "char", },
  161. { T_INT, "int", },
  162. { T_FLOAT, "float", },
  163. { T_DOUBLE, "double", },
  164. { T_SHORT, "short", },
  165. { T_LONG, "long", },
  166. { T_SIGNED, "signed", },
  167. { T_UNSIGNED, "unsigned", },
  168. { 0, NULL, }, /* Signal end */
  169. };
  170. /*
  171. * Test_table[] is used to test for illegal combinations.
  172. */
  173. static short test_table[] = {
  174. T_FLOAT | T_DOUBLE | T_LONG | T_SHORT,
  175. T_FLOAT | T_DOUBLE | T_CHAR | T_INT,
  176. T_FLOAT | T_DOUBLE | T_SIGNED | T_UNSIGNED,
  177. T_LONG | T_SHORT | T_CHAR,
  178. 0 /* end marker */
  179. };
  180. /*
  181. * The order of this table is important -- it is also referenced by
  182. * the command line processor to allow run-time overriding of the
  183. * built-in size values. The order must not be changed:
  184. * char, short, int, long, float, double (func pointer)
  185. */
  186. SIZES size_table[] = {
  187. { T_CHAR, S_CHAR, S_PCHAR }, /* char */
  188. { T_SHORT, S_SINT, S_PSINT }, /* short int */
  189. { T_INT, S_INT, S_PINT }, /* int */
  190. { T_LONG, S_LINT, S_PLINT }, /* long */
  191. { T_FLOAT, S_FLOAT, S_PFLOAT }, /* float */
  192. { T_DOUBLE, S_DOUBLE, S_PDOUBLE }, /* double */
  193. { T_FPTR, 0, S_PFPTR }, /* int (*()) */
  194. { 0, 0, 0 }, /* End of table */
  195. };
  196. #endif /* OK_SIZEOF */
  197. ReturnCode fpp_eval(struct Global *global, int *eval)
  198. {
  199. /*
  200. * Evaluate an expression. Straight-forward operator precedence.
  201. * This is called from fpp_control() on encountering an #if statement.
  202. * It calls the following routines:
  203. * fpp_evallex Lexical analyser -- returns the type and value of
  204. * the next input token.
  205. * fpp_evaleval Evaluate the current operator, given the values on
  206. * the value stack. Returns a pointer to the (new)
  207. * value stack.
  208. * For compatiblity with older cpp's, this return returns 1 (FPP_TRUE)
  209. * if a syntax error is detected.
  210. */
  211. int op; /* Current operator */
  212. int *valp; /* -> value vector */
  213. OPTAB *opp; /* Operator stack */
  214. int prec; /* Op precedence */
  215. int binop; /* Set if binary op. needed */
  216. int op1; /* Operand from stack */
  217. int skip; /* For short-circuit testing */
  218. int value[NEXP]; /* Value stack */
  219. OPTAB opstack[NEXP]; /* Operand stack */
  220. ReturnCode ret;
  221. char again=FPP_TRUE;
  222. valp = value;
  223. opp = opstack;
  224. opp->op = OP_END; /* Mark bottom of stack */
  225. opp->prec = opdope[OP_END]; /* And its precedence */
  226. opp->skip = 0; /* Not skipping now */
  227. binop = 0;
  228. while(again) {
  229. ret=fpp_evallex(global, opp->skip, &op);
  230. if(ret)
  231. return(ret);
  232. if (op == OP_SUB && binop == 0)
  233. op = OP_NEG; /* Unary minus */
  234. else if (op == OP_ADD && binop == 0)
  235. op = OP_PLU; /* Unary plus */
  236. else if (op == OP_FAIL) {
  237. *eval=1; /* Error in evallex */
  238. return(FPP_OK);
  239. }
  240. if (op == DIG) { /* Value? */
  241. if (binop != 0) {
  242. fpp_cerror(global, ERROR_MISPLACED_CONSTANT);
  243. *eval=1;
  244. return(FPP_OK);
  245. } else if (valp >= &value[NEXP-1]) {
  246. fpp_cerror(global, ERROR_IF_OVERFLOW);
  247. *eval=1;
  248. return(FPP_OK);
  249. } else {
  250. *valp++ = global->evalue;
  251. binop = 1;
  252. }
  253. again=FPP_TRUE;
  254. continue;
  255. } else if (op > OP_END) {
  256. fpp_cerror(global, ERROR_ILLEGAL_IF_LINE);
  257. *eval=1;
  258. return(FPP_OK);
  259. }
  260. prec = opdope[op];
  261. if (binop != (prec & 1)) {
  262. fpp_cerror(global, ERROR_OPERATOR, opname[op]);
  263. *eval=1;
  264. return(FPP_OK);
  265. }
  266. binop = (prec & 2) >> 1;
  267. do {
  268. if (prec > opp->prec) {
  269. if (op == OP_LPA)
  270. prec = OP_RPA_PREC;
  271. else if (op == OP_QUE)
  272. prec = OP_QUE_PREC;
  273. op1 = opp->skip; /* Save skip for test */
  274. /*
  275. * Push operator onto op. stack.
  276. */
  277. opp++;
  278. if (opp >= &opstack[NEXP]) {
  279. fpp_cerror(global, ERROR_EXPR_OVERFLOW, opname[op]);
  280. *eval=1;
  281. return(FPP_OK);
  282. }
  283. opp->op = op;
  284. opp->prec = prec;
  285. skip = (valp[-1] != 0); /* Short-circuit tester */
  286. /*
  287. * Do the short-circuit stuff here. Short-circuiting
  288. * stops automagically when operators are evaluated.
  289. */
  290. if ((op == OP_ANA && !skip)
  291. || (op == OP_ORO && skip))
  292. opp->skip = S_ANDOR; /* And/or skip starts */
  293. else if (op == OP_QUE) /* Start of ?: operator */
  294. opp->skip = (op1 & S_ANDOR) | ((!skip) ? S_QUEST : 0);
  295. else if (op == OP_COL) { /* : inverts S_QUEST */
  296. opp->skip = (op1 & S_ANDOR)
  297. | (((op1 & S_QUEST) != 0) ? 0 : S_QUEST);
  298. }
  299. else { /* Other ops leave */
  300. opp->skip = op1; /* skipping unchanged. */
  301. }
  302. again=FPP_TRUE;
  303. continue;
  304. }
  305. /*
  306. * Pop operator from op. stack and evaluate it.
  307. * End of stack and '(' are specials.
  308. */
  309. skip = opp->skip; /* Remember skip value */
  310. switch ((op1 = opp->op)) { /* Look at stacked op */
  311. case OP_END: /* Stack end marker */
  312. if (op == OP_EOE) {
  313. *eval=valp[-1]; /* Finished ok. */
  314. return(FPP_OK);
  315. }
  316. /* Read another op. */
  317. again=FPP_TRUE;
  318. continue;
  319. case OP_LPA: /* ( on stack */
  320. if (op != OP_RPA) { /* Matches ) on input */
  321. fpp_cerror(global, ERROR_UNBALANCED_PARENS, opname[op]);
  322. *eval=1;
  323. return(FPP_OK);
  324. }
  325. opp--; /* Unstack it */
  326. /* -- Fall through */
  327. case OP_QUE:
  328. /* Evaluate true expr. */
  329. again=FPP_TRUE;
  330. continue;
  331. case OP_COL: /* : on stack. */
  332. opp--; /* Unstack : */
  333. if (opp->op != OP_QUE) { /* Matches ? on stack? */
  334. fpp_cerror(global, ERROR_MISPLACED, opname[(unsigned)opp->op]);
  335. *eval=1;
  336. return(FPP_OK);
  337. }
  338. /*
  339. * Evaluate op1.
  340. */
  341. default: /* Others: */
  342. opp--; /* Unstack the operator */
  343. valp = fpp_evaleval(global, valp, op1, skip);
  344. again=FPP_FALSE;
  345. } /* op1 switch end */
  346. } while (!again); /* Stack unwind loop */
  347. }
  348. return(FPP_OK);
  349. }
  350. INLINE FILE_LOCAL
  351. ReturnCode fpp_evallex(struct Global *global,
  352. int skip, /* FPP_TRUE if short-circuit evaluation */
  353. int *op)
  354. {
  355. /*
  356. * Set *op to next fpp_eval operator or value. Called from fpp_eval(). It
  357. * calls a special-purpose routines for 'char' strings and
  358. * numeric values:
  359. * fpp_evalchar called to evaluate 'x'
  360. * fpp_evalnum called to evaluate numbers.
  361. */
  362. int c, c1, t;
  363. ReturnCode ret;
  364. char loop;
  365. do { /* while(loop); */
  366. /* again: */
  367. loop=FPP_FALSE;
  368. do { /* Collect the token */
  369. c = fpp_skipws(global);
  370. if((ret=fpp_macroid(global, &c)))
  371. return(ret);
  372. if (c == EOF_CHAR || c == '\n') {
  373. fpp_unget(global);
  374. *op=OP_EOE; /* End of expression */
  375. return(FPP_OK);
  376. }
  377. } while ((t = type[c]) == LET && fpp_catenate(global, 0, &ret) && !ret);
  378. if(ret)
  379. /* If the loop was broken because of a fatal error! */
  380. return(ret);
  381. if (t == INV) { /* Total nonsense */
  382. if (!skip) {
  383. if (isascii(c) && isprint(c))
  384. fpp_cerror(global, ERROR_ILLEGAL_CHARACTER, c);
  385. else
  386. fpp_cerror(global, ERROR_ILLEGAL_CHARACTER2, c);
  387. }
  388. return(FPP_ILLEGAL_CHARACTER);
  389. } else if (t == QUO) { /* ' or " */
  390. if (c == '\'') { /* Character constant */
  391. global->evalue = fpp_evalchar(global, skip); /* Somewhat messy */
  392. *op=DIG; /* Return a value */
  393. return(FPP_OK);
  394. }
  395. fpp_cerror(global, ERROR_STRING_IN_IF);
  396. return(FPP_CANT_USE_STRING_IN_IF);
  397. } else if (t == LET) { /* ID must be a macro */
  398. if (streq(global->tokenbuf, "defined")) { /* Or defined name */
  399. c1 = c = fpp_skipws(global);
  400. if (c == '(') /* Allow defined(name) */
  401. c = fpp_skipws(global);
  402. if (type[c] == LET) {
  403. global->evalue = (fpp_lookid(global, c) != NULL);
  404. if (c1 != '(' /* Need to balance */
  405. || fpp_skipws(global) == ')') { /* Did we balance? */
  406. *op=DIG;
  407. return(FPP_OK); /* Parsed ok */
  408. }
  409. }
  410. fpp_cerror(global, ERROR_DEFINED_SYNTAX);
  411. return(FPP_BAD_IF_DEFINED_SYNTAX);
  412. }
  413. #if OK_SIZEOF
  414. else if (streq(global->tokenbuf, "sizeof")) { /* New sizeof hackery */
  415. ret=fpp_dosizeof(global, op); /* Gets own routine */
  416. return(ret);
  417. }
  418. #endif
  419. global->evalue = 0;
  420. *op=DIG;
  421. return(FPP_OK);
  422. }
  423. else if (t == DIG) { /* Numbers are harder */
  424. global->evalue = fpp_evalnum(global, c);
  425. }
  426. else if (strchr("!=<>&|\\", c) != NULL) {
  427. /*
  428. * Process a possible multi-byte lexeme.
  429. */
  430. c1 = fpp_cget(global); /* Peek at next char */
  431. switch (c) {
  432. case '!':
  433. if (c1 == '=') {
  434. *op=OP_NE;
  435. return(FPP_OK);
  436. }
  437. break;
  438. case '=':
  439. if (c1 != '=') { /* Can't say a=b in #if */
  440. fpp_unget(global);
  441. fpp_cerror(global, ERROR_ILLEGAL_ASSIGN);
  442. return (FPP_IF_ERROR);
  443. }
  444. *op=OP_EQ;
  445. return(FPP_OK);
  446. case '>':
  447. case '<':
  448. if (c1 == c) {
  449. *op= ((c == '<') ? OP_ASL : OP_ASR);
  450. return(FPP_OK);
  451. } else if (c1 == '=') {
  452. *op= ((c == '<') ? OP_LE : OP_GE);
  453. return(FPP_OK);
  454. }
  455. break;
  456. case '|':
  457. case '&':
  458. if (c1 == c) {
  459. *op= ((c == '|') ? OP_ORO : OP_ANA);
  460. return(FPP_OK);
  461. }
  462. break;
  463. case '\\':
  464. if (c1 == '\n') { /* Multi-line if */
  465. loop=FPP_TRUE;
  466. break;
  467. }
  468. fpp_cerror(global, ERROR_ILLEGAL_BACKSLASH);
  469. return(FPP_IF_ERROR);
  470. }
  471. if(!loop)
  472. fpp_unget(global);
  473. }
  474. } while(loop);
  475. *op=t;
  476. return(FPP_OK);
  477. }
  478. #if OK_SIZEOF
  479. INLINE FILE_LOCAL
  480. ReturnCode fpp_dosizeof(struct Global *global, int *result)
  481. {
  482. /*
  483. * Process the sizeof (basic type) operation in an #if string.
  484. * Sets evalue to the size and returns
  485. * DIG success
  486. * OP_FAIL bad parse or something.
  487. */
  488. int c;
  489. TYPES *tp;
  490. SIZES *sizp;
  491. short *testp;
  492. short typecode;
  493. ReturnCode ret;
  494. if ((c = fpp_skipws(global)) != '(') {
  495. fpp_unget(global);
  496. fpp_cerror(global, ERROR_SIZEOF_SYNTAX);
  497. return(FPP_SIZEOF_ERROR);
  498. }
  499. /*
  500. * Scan off the tokens.
  501. */
  502. typecode = 0;
  503. while ((c = fpp_skipws(global))) {
  504. if((ret=fpp_macroid(global, &c)))
  505. return(ret);
  506. /* (I) return on fail! */
  507. if (c == EOF_CHAR || c == '\n') {
  508. /* End of line is a bug */
  509. fpp_unget(global);
  510. fpp_cerror(global, ERROR_SIZEOF_SYNTAX);
  511. return(FPP_SIZEOF_ERROR);
  512. } else if (c == '(') { /* thing (*)() func ptr */
  513. if (fpp_skipws(global) == '*'
  514. && fpp_skipws(global) == ')') { /* We found (*) */
  515. if (fpp_skipws(global) != '(') /* Let () be optional */
  516. fpp_unget(global);
  517. else if (fpp_skipws(global) != ')') {
  518. fpp_unget(global);
  519. fpp_cerror(global, ERROR_SIZEOF_SYNTAX);
  520. return(FPP_SIZEOF_ERROR);
  521. }
  522. typecode |= T_FPTR; /* Function pointer */
  523. } else { /* Junk is a bug */
  524. fpp_unget(global);
  525. fpp_cerror(global, ERROR_SIZEOF_SYNTAX);
  526. return(FPP_SIZEOF_ERROR);
  527. }
  528. }
  529. else if (type[c] != LET) /* Exit if not a type */
  530. break;
  531. else if (!fpp_catenate(global, 0, &ret) && !ret) { /* Maybe combine tokens */
  532. /*
  533. * Look for this unexpandable token in basic_types.
  534. * The code accepts "int long" as well as "long int"
  535. * which is a minor bug as bugs go (and one shared with
  536. * a lot of C compilers).
  537. */
  538. for (tp = basic_types; tp->name != NULLST; tp++) {
  539. if (streq(global->tokenbuf, tp->name))
  540. break;
  541. }
  542. if (tp->name == NULLST) {
  543. fpp_cerror(global, ERROR_SIZEOF_UNKNOWN, global->tokenbuf);
  544. return(FPP_SIZEOF_ERROR);
  545. }
  546. typecode |= tp->type; /* Or in the type bit */
  547. } else if(ret)
  548. return(ret);
  549. }
  550. /*
  551. * We are at the end of the type scan. Chew off '*' if necessary.
  552. */
  553. if (c == '*') {
  554. typecode |= T_PTR;
  555. c = fpp_skipws(global);
  556. }
  557. if (c == ')') { /* Last syntax check */
  558. for (testp = test_table; *testp != 0; testp++) {
  559. if (!fpp_bittest(typecode & *testp)) {
  560. fpp_cerror(global, ERROR_SIZEOF_ILLEGAL_TYPE);
  561. return(FPP_SIZEOF_ERROR);
  562. }
  563. }
  564. /*
  565. * We assume that all function pointers are the same size:
  566. * sizeof (int (*)()) == sizeof (float (*)())
  567. * We assume that signed and unsigned don't change the size:
  568. * sizeof (signed int) == (sizeof unsigned int)
  569. */
  570. if ((typecode & T_FPTR) != 0) /* Function pointer */
  571. typecode = T_FPTR | T_PTR;
  572. else { /* Var or var * datum */
  573. typecode &= ~(T_SIGNED | T_UNSIGNED);
  574. if ((typecode & (T_SHORT | T_LONG)) != 0)
  575. typecode &= ~T_INT;
  576. }
  577. if ((typecode & ~T_PTR) == 0) {
  578. fpp_cerror(global, ERROR_SIZEOF_NO_TYPE);
  579. return(FPP_SIZEOF_ERROR);
  580. }
  581. /*
  582. * Exactly one bit (and possibly T_PTR) may be set.
  583. */
  584. for (sizp = size_table; sizp->bits != 0; sizp++) {
  585. if ((typecode & ~T_PTR) == sizp->bits) {
  586. global->evalue = ((typecode & T_PTR) != 0)
  587. ? sizp->psize : sizp->size;
  588. *result=DIG;
  589. return(FPP_OK);
  590. }
  591. } /* We shouldn't fail */
  592. fpp_cerror(global, ERROR_SIZEOF_BUG, typecode);
  593. return(FPP_SIZEOF_ERROR);
  594. }
  595. fpp_unget(global);
  596. fpp_cerror(global, ERROR_SIZEOF_SYNTAX);
  597. return(FPP_SIZEOF_ERROR);
  598. }
  599. INLINE FILE_LOCAL
  600. int fpp_bittest(int value)
  601. {
  602. /*
  603. * FPP_TRUE if value is zero or exactly one bit is set in value.
  604. */
  605. #if (4096 & ~(-4096)) == 0
  606. return ((value & ~(-value)) == 0);
  607. #else
  608. /*
  609. * Do it the hard way (for non 2's complement machines)
  610. */
  611. return (value == 0 || value ^ (value - 1) == (value * 2 - 1));
  612. #endif
  613. }
  614. #endif /* OK_SIZEOF */
  615. INLINE FILE_LOCAL
  616. int fpp_evalnum(struct Global *global, int c)
  617. {
  618. /*
  619. * Expand number for #if lexical analysis. Note: fpp_evalnum recognizes
  620. * the unsigned suffix, but only returns a signed int value.
  621. */
  622. int value;
  623. int base;
  624. int c1;
  625. if (c != '0')
  626. base = 10;
  627. else if ((c = fpp_cget(global)) == 'x' || c == 'X') {
  628. base = 16;
  629. c = fpp_cget(global);
  630. }
  631. else base = 8;
  632. value = 0;
  633. for (;;) {
  634. c1 = c;
  635. if (isascii(c) && isupper(c1))
  636. c1 = fpp_tolower(c1);
  637. if (c1 >= 'a')
  638. c1 -= ('a' - 10);
  639. else c1 -= '0';
  640. if (c1 < 0 || c1 >= base)
  641. break;
  642. value *= base;
  643. value += c1;
  644. c = fpp_cget(global);
  645. }
  646. if (c == 'u' || c == 'U') /* Unsigned nonsense */
  647. c = fpp_cget(global);
  648. fpp_unget(global);
  649. return (value);
  650. }
  651. INLINE FILE_LOCAL
  652. int fpp_evalchar(struct Global *global,
  653. int skip) /* FPP_TRUE if short-circuit evaluation */
  654. /*
  655. * Get a character constant
  656. */
  657. {
  658. int c;
  659. int value;
  660. int count;
  661. global->instring = FPP_TRUE;
  662. if ((c = fpp_cget(global)) == '\\') {
  663. switch ((c = fpp_cget(global))) {
  664. case 'a': /* New in Standard */
  665. #if ('a' == '\a' || '\a' == ALERT)
  666. value = ALERT; /* Use predefined value */
  667. #else
  668. value = '\a'; /* Use compiler's value */
  669. #endif
  670. break;
  671. case 'b':
  672. value = '\b';
  673. break;
  674. case 'f':
  675. value = '\f';
  676. break;
  677. case 'n':
  678. value = '\n';
  679. break;
  680. case 'r':
  681. value = '\r';
  682. break;
  683. case 't':
  684. value = '\t';
  685. break;
  686. case 'v': /* New in Standard */
  687. #if ('v' == '\v' || '\v' == VT)
  688. value = VT; /* Use predefined value */
  689. #else
  690. value = '\v'; /* Use compiler's value */
  691. #endif
  692. break;
  693. case 'x': /* '\xFF' */
  694. count = 3;
  695. value = 0;
  696. while ((((c = fpp_get(global)) >= '0' && c <= '9')
  697. || (c >= 'a' && c <= 'f')
  698. || (c >= 'A' && c <= 'F'))
  699. && (--count >= 0)) {
  700. value *= 16;
  701. value += (c <= '9') ? (c - '0') : ((c & 0xF) + 9);
  702. }
  703. fpp_unget(global);
  704. break;
  705. default:
  706. if (c >= '0' && c <= '7') {
  707. count = 3;
  708. value = 0;
  709. while (c >= '0' && c <= '7' && --count >= 0) {
  710. value *= 8;
  711. value += (c - '0');
  712. c = fpp_get(global);
  713. }
  714. fpp_unget(global);
  715. } else
  716. value = c;
  717. break;
  718. }
  719. } else if (c == '\'')
  720. value = 0;
  721. else value = c;
  722. /*
  723. * We warn on multi-byte constants and try to hack
  724. * (big|little)endian machines.
  725. */
  726. #if BIG_ENDIAN
  727. count = 0;
  728. #endif
  729. while ((c = fpp_get(global)) != '\'' && c != EOF_CHAR && c != '\n') {
  730. if (!skip)
  731. fpp_cwarn(global, WARN_MULTIBYTE_NOT_PORTABLE, c);
  732. #if BIG_ENDIAN
  733. count += BITS_CHAR;
  734. value += (c << count);
  735. #else
  736. value <<= BITS_CHAR;
  737. value += c;
  738. #endif
  739. }
  740. global->instring = FPP_FALSE;
  741. return (value);
  742. }
  743. INLINE FILE_LOCAL
  744. int *fpp_evaleval(struct Global *global,
  745. int *valp,
  746. int op,
  747. int skip) /* FPP_TRUE if short-circuit evaluation */
  748. {
  749. /*
  750. * Apply the argument operator to the data on the value stack.
  751. * One or two values are popped from the value stack and the result
  752. * is pushed onto the value stack.
  753. *
  754. * OP_COL is a special case.
  755. *
  756. * fpp_evaleval() returns the new pointer to the top of the value stack.
  757. */
  758. int v1, v2 = 0;
  759. if (isbinary(op))
  760. v2 = *--valp;
  761. v1 = *--valp;
  762. switch (op) {
  763. case OP_EOE:
  764. break;
  765. case OP_ADD:
  766. v1 += v2;
  767. break;
  768. case OP_SUB:
  769. v1 -= v2;
  770. break;
  771. case OP_MUL:
  772. v1 *= v2;
  773. break;
  774. case OP_DIV:
  775. case OP_MOD:
  776. if (v2 == 0) {
  777. if (!skip) {
  778. fpp_cwarn(global, WARN_DIVISION_BY_ZERO,
  779. (op == OP_DIV) ? "divide" : "mod");
  780. }
  781. v1 = 0;
  782. }
  783. else if (op == OP_DIV)
  784. v1 /= v2;
  785. else
  786. v1 %= v2;
  787. break;
  788. case OP_ASL:
  789. v1 <<= v2;
  790. break;
  791. case OP_ASR:
  792. v1 >>= v2;
  793. break;
  794. case OP_AND:
  795. v1 &= v2;
  796. break;
  797. case OP_OR:
  798. v1 |= v2;
  799. break;
  800. case OP_XOR:
  801. v1 ^= v2;
  802. break;
  803. case OP_EQ:
  804. v1 = (v1 == v2);
  805. break;
  806. case OP_NE:
  807. v1 = (v1 != v2);
  808. break;
  809. case OP_LT:
  810. v1 = (v1 < v2);
  811. break;
  812. case OP_LE:
  813. v1 = (v1 <= v2);
  814. break;
  815. case OP_GE:
  816. v1 = (v1 >= v2);
  817. break;
  818. case OP_GT:
  819. v1 = (v1 > v2);
  820. break;
  821. case OP_ANA:
  822. v1 = (v1 && v2);
  823. break;
  824. case OP_ORO:
  825. v1 = (v1 || v2);
  826. break;
  827. case OP_COL:
  828. /*
  829. * v1 has the "true" value, v2 the "false" value.
  830. * The top of the value stack has the test.
  831. */
  832. v1 = (*--valp) ? v1 : v2;
  833. break;
  834. case OP_NEG:
  835. v1 = (-v1);
  836. break;
  837. case OP_PLU:
  838. break;
  839. case OP_COM:
  840. v1 = ~v1;
  841. break;
  842. case OP_NOT:
  843. v1 = !v1;
  844. break;
  845. default:
  846. fpp_cerror(global, ERROR_IF_OPERAND, op);
  847. v1 = 0;
  848. }
  849. *valp++ = v1;
  850. return (valp);
  851. }