LLlex.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* L E X I C A L A N A L Y Z E R */
  7. #include "debug.h"
  8. #include "lint.h"
  9. #include <alloc.h>
  10. #include "idfsize.h"
  11. #include "numsize.h"
  12. #include "strsize.h"
  13. #include "nopp.h"
  14. #include "input.h"
  15. #include "arith.h"
  16. #include "def.h"
  17. #include "macro.h"
  18. #include "idf.h"
  19. #include "LLlex.h"
  20. #include "Lpars.h"
  21. #include "class.h"
  22. #include "assert.h"
  23. #include "sizes.h"
  24. #include "specials.h" /* registration of special identifiers */
  25. /* Data about the token yielded */
  26. struct token dot, ahead, aside;
  27. int token_nmb = 0; /* number of the ahead token */
  28. int tk_nmb_at_last_syn_err = -5/*ERR_SHADOW*/;
  29. /* token number at last syntax error */
  30. int idfsize = IDFSIZE;
  31. char sp_occurred[SP_TOTAL+1];
  32. #ifndef NOPP
  33. int ReplaceMacros = 1; /* replacing macros */
  34. int AccDefined = 0; /* accept "defined(...)" */
  35. int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
  36. int Unstacked = 0; /* an unstack is done */
  37. extern int InputLevel;
  38. #endif
  39. int AccFileSpecifier = 0; /* return filespecifier <...> */
  40. int EoiForNewline = 0; /* return EOI upon encountering newline */
  41. int File_Inserted = 0; /* a file has just been inserted */
  42. int LexSave = 0; /* last character read by GetChar */
  43. #define MAX_LL_DEPTH 2
  44. #define FLG_ESEEN 0x01 /* possibly a floating point number */
  45. #define FLG_DOTSEEN 0x02 /* certainly a floating point number */
  46. extern arith full_mask[];
  47. #ifdef LINT
  48. extern int lint_skip_comment;
  49. #endif
  50. #ifndef NOPP
  51. static struct token LexStack[MAX_LL_DEPTH];
  52. static LexSP = 0;
  53. /* In PushLex() the actions are taken in order to initialise or
  54. re-initialise the lexical scanner.
  55. E.g. at the invocation of a sub-parser that uses LLlex(), the
  56. state of the current parser should be saved.
  57. */
  58. void PushLex()
  59. {
  60. ASSERT(LexSP < MAX_LL_DEPTH);
  61. ASSERT(ASIDE == 0); /* ASIDE = 0; */
  62. GetToken(&ahead);
  63. LexStack[LexSP++] = dot;
  64. }
  65. void PopLex()
  66. {
  67. ASSERT(LexSP > 0);
  68. dot = LexStack[--LexSP];
  69. }
  70. #endif /* NOPP */
  71. int LLlex()
  72. {
  73. /* LLlex() plays the role of Lexical Analyzer for the C parser.
  74. The look-ahead and putting aside of tokens are taken into
  75. account.
  76. */
  77. if (ASIDE) { /* a token is put aside */
  78. dot = aside;
  79. ASIDE = 0;
  80. }
  81. else { /* read ahead and return the old one */
  82. #ifdef LINT
  83. lint_comment_ahead();
  84. #endif /* LINT */
  85. dot = ahead;
  86. /* the following test is performed due to the dual
  87. task of LLlex(): it is also called for parsing the
  88. restricted constant expression following a #if or
  89. #elif. The newline character causes EOF to be
  90. returned in this case to stop the LLgen parsing task.
  91. */
  92. if (DOT != EOI)
  93. GetToken(&ahead);
  94. else
  95. DOT = EOF;
  96. }
  97. return DOT;
  98. }
  99. char *string_token(char *nm, int stop_char, int *plen);
  100. arith char_constant(char *nm);
  101. void skipcomment();
  102. void strint2tok(char intbuf[], struct token *ptok);
  103. void strflt2tok(char fltbuf[], struct token *ptok);
  104. int GetToken(struct token *ptok)
  105. {
  106. /* GetToken() is the actual token recognizer. It calls the
  107. control line interpreter if it encounters a "\n{w}*#"
  108. combination. Macro replacement is also performed if it is
  109. needed.
  110. */
  111. char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
  112. int ch, nch;
  113. token_nmb++;
  114. if (File_Inserted) {
  115. File_Inserted = 0;
  116. goto firstline;
  117. }
  118. again: /* rescan the input after an error or replacement */
  119. ch = GetChar();
  120. go_on: /* rescan, the following character has been read */
  121. if ((ch & 0200) && ch != EOI) /* stop on non-ascii character */
  122. {
  123. fatal("non-ascii '\\%03o' read", ch & 0377);
  124. }
  125. /* keep track of the place of the token in the file */
  126. ptok->tk_file = FileName;
  127. ptok->tk_line = LineNumber;
  128. switch (class(ch)) { /* detect character class */
  129. case STNL: /* newline, vertical space or formfeed */
  130. firstline:
  131. LineNumber++; /* also at vs and ff */
  132. ptok->tk_file = FileName;
  133. ptok->tk_line = LineNumber;
  134. if (EoiForNewline) /* called in control line */
  135. /* a newline in a control line indicates the
  136. end-of-information of the line.
  137. */
  138. return ptok->tk_symb = EOI;
  139. while ((ch = GetChar()),
  140. (ch == '#'
  141. #ifndef NOPP
  142. || ch == '/'
  143. #endif
  144. || class(ch) == STSKIP)) {
  145. /* blanks are allowed before hashes */
  146. if (ch == '#') {
  147. /* a control line follows */
  148. domacro();
  149. #ifndef NOPP
  150. if (File_Inserted) {
  151. File_Inserted = 0;
  152. goto firstline;
  153. }
  154. } else if (ch == '/') {
  155. if ((GetChar() == '*') && !InputLevel) {
  156. skipcomment();
  157. } else {
  158. UnGetChar();
  159. break;
  160. }
  161. #endif /* NOPP */
  162. }
  163. }
  164. /* We have to loop here, because in
  165. `domacro' the nl, vt or ff is read. The
  166. character following it may again be a `#'.
  167. */
  168. goto go_on;
  169. case STSKIP: /* just skip the skip characters */
  170. goto again;
  171. case STGARB: /* garbage character */
  172. #ifndef NOPP
  173. garbage:
  174. #endif
  175. if (040 < ch && ch < 0177) {
  176. return ptok->tk_symb = ch;
  177. } else {
  178. lexerror("garbage char \\%03o", ch);
  179. }
  180. goto again;
  181. case STSIMP: /* a simple character, no part of compound token*/
  182. return ptok->tk_symb = ch;
  183. case STCOMP: /* maybe the start of a compound token */
  184. nch = GetChar(); /* character lookahead */
  185. switch (ch) {
  186. case '!':
  187. if (nch == '=')
  188. return ptok->tk_symb = NOTEQUAL;
  189. break;
  190. case '&':
  191. if (nch == '&')
  192. return ptok->tk_symb = AND;
  193. if (nch == '=')
  194. return ptok->tk_symb = ANDAB;
  195. break;
  196. case '+':
  197. if (nch == '+')
  198. return ptok->tk_symb = PLUSPLUS;
  199. if (nch == '=')
  200. return ptok->tk_symb = PLUSAB;
  201. break;
  202. case '-':
  203. if (nch == '-')
  204. return ptok->tk_symb = MINMIN;
  205. if (nch == '>')
  206. return ptok->tk_symb = ARROW;
  207. if (nch == '=')
  208. return ptok->tk_symb = MINAB;
  209. break;
  210. case '<':
  211. if (AccFileSpecifier) {
  212. UnGetChar(); /* pushback nch */
  213. ptok->tk_bts = string_token("file specifier", '>', &(ptok->tk_len));
  214. return ptok->tk_symb = FILESPECIFIER;
  215. }
  216. if (nch == '<') {
  217. if ((nch = GetChar()) == '=')
  218. return ptok->tk_symb = LEFTAB;
  219. UnGetChar();
  220. return ptok->tk_symb = LEFT;
  221. }
  222. if (nch == '=')
  223. return ptok->tk_symb = LESSEQ;
  224. break;
  225. case '=':
  226. if (nch == '=')
  227. return ptok->tk_symb = EQUAL;
  228. break;
  229. case '>':
  230. if (nch == '=')
  231. return ptok->tk_symb = GREATEREQ;
  232. if (nch == '>') {
  233. if ((nch = GetChar()) == '=')
  234. return ptok->tk_symb = RIGHTAB;
  235. UnGetChar();
  236. return ptok->tk_symb = RIGHT;
  237. }
  238. break;
  239. case '|':
  240. if (nch == '|')
  241. return ptok->tk_symb = OR;
  242. if (nch == '=')
  243. return ptok->tk_symb = ORAB;
  244. break;
  245. case '%':
  246. if (nch == '=')
  247. return ptok->tk_symb = MODAB;
  248. break;
  249. case '*':
  250. if (nch == '=')
  251. return ptok->tk_symb = TIMESAB;
  252. break;
  253. case '^':
  254. if (nch == '=')
  255. return ptok->tk_symb = XORAB;
  256. break;
  257. case '/':
  258. #ifndef NOPP
  259. if (nch == '*' && !InputLevel) {
  260. skipcomment();
  261. goto again;
  262. }
  263. #endif
  264. if (nch == '=')
  265. return ptok->tk_symb = DIVAB;
  266. break;
  267. default:
  268. crash("bad class for char 0%o", ch);
  269. /* NOTREACHED */
  270. }
  271. UnGetChar();
  272. return ptok->tk_symb = ch;
  273. case STCHAR: /* character constant */
  274. ptok->tk_ival = char_constant("character");
  275. ptok->tk_fund = INT;
  276. return ptok->tk_symb = INTEGER;
  277. case STSTR: /* string */
  278. ptok->tk_bts = string_token("string", '"', &(ptok->tk_len));
  279. ptok->tk_fund = CHAR; /* string of characters */
  280. return ptok->tk_symb = STRING;
  281. case STELL: /* wide character constant/string prefix */
  282. nch = GetChar();
  283. if (nch == '"') {
  284. ptok->tk_bts = string_token("wide character string",
  285. '"', &(ptok->tk_len));
  286. ptok->tk_fund = WCHAR; /* string of wide characters */
  287. return ptok->tk_symb = STRING;
  288. } else if (nch == '\'') {
  289. ptok->tk_ival = char_constant("wide character");
  290. ptok->tk_fund = INT;
  291. return ptok->tk_symb = INTEGER;
  292. }
  293. UnGetChar();
  294. /* fallthrough */
  295. case STIDF:
  296. {
  297. char *tg = &buf[0];
  298. int pos = -1;
  299. struct idf *idef;
  300. int idfsize; /* ??? */
  301. #ifndef NOPP
  302. int NoExpandNext = 0;
  303. if (Unstacked) EnableMacros(); /* unstack macro's when allowed. */
  304. if (ch == NOEXPM) {
  305. NoExpandNext = 1;
  306. ch = GetChar();
  307. }
  308. #endif
  309. do { /* read the identifier */
  310. if (++pos < idfsize) {
  311. *tg++ = ch;
  312. }
  313. ch = GetChar();
  314. } while (in_idf(ch));
  315. if (ch != EOI)
  316. UnGetChar();
  317. *tg++ = '\0'; /* mark the end of the identifier */
  318. idef = ptok->tk_idf = str2idf(buf, 1);
  319. sp_occurred[idef->id_special] = 1;
  320. idef->id_file = ptok->tk_file;
  321. idef->id_line = ptok->tk_line;
  322. #ifndef NOPP
  323. if (idef->id_macro && ReplaceMacros && !NoExpandNext) {
  324. if (replace(idef))
  325. goto again;
  326. }
  327. if (UnknownIdIsZero && idef->id_reserved != SIZEOF) {
  328. ptok->tk_ival = (arith)0;
  329. ptok->tk_fund = INT;
  330. return ptok->tk_symb = INTEGER;
  331. }
  332. #endif /* NOPP */
  333. ptok->tk_symb = (
  334. idef->id_reserved
  335. ? idef->id_reserved
  336. : idef->id_def && idef->id_def->df_sc == TYPEDEF
  337. ? TYPE_IDENTIFIER
  338. : IDENTIFIER
  339. );
  340. return IDENTIFIER;
  341. }
  342. case STNUM: /* a numeric constant */
  343. {
  344. int siz_left = NUMSIZE - 1;
  345. char *np = &buf[0];
  346. int flags = 0;
  347. #define store(ch) if (--siz_left >= 0) \
  348. *np++ = ch;
  349. if (ch == '.') {
  350. /* An embarrasing ambiguity. We have either a
  351. pp-number, a field operator, an ELLIPSIS or
  352. an error (..).
  353. */
  354. ch = GetChar();
  355. if (!is_dig(ch)) { /* . or ... */
  356. if (ch == '.') {
  357. if ((ch = GetChar()) == '.')
  358. return ptok->tk_symb = ELLIPSIS;
  359. UnGetChar(); /* not '.' */
  360. ChPushBack('.'); /* sigh ... */
  361. } else
  362. UnGetChar(); /* not '.' */
  363. return ptok->tk_symb = '.';
  364. }
  365. UnGetChar();
  366. ch = '.';
  367. flags |= FLG_DOTSEEN;
  368. }
  369. store(ch);
  370. ch = GetChar();
  371. while(in_idf(ch) || ch == '.') {
  372. store(ch);
  373. if (ch == '.') flags |= FLG_DOTSEEN;
  374. if (ch == 'e' || ch == 'E') {
  375. flags |= FLG_ESEEN;
  376. ch = GetChar();
  377. if (ch == '+' || ch == '-') {
  378. flags |= FLG_DOTSEEN; /* trick */
  379. store(ch);
  380. ch = GetChar();
  381. }
  382. } else ch = GetChar();
  383. }
  384. store('\0');
  385. UnGetChar();
  386. np = &buf[0];
  387. ch = *np++;
  388. if (siz_left < 0) {
  389. lexerror("number too long");
  390. if ((flags & FLG_DOTSEEN)
  391. || (flags & FLG_ESEEN
  392. && !(ch == '0'
  393. && (*np == 'x' || *np == 'X')))) {
  394. ptok->tk_fval = Salloc("0.0", (unsigned) 4);
  395. ptok->tk_fund = DOUBLE;
  396. return ptok->tk_symb = FLOATING;
  397. }
  398. ptok->tk_ival = 1;
  399. ptok->tk_fund = ULONG;
  400. ptok->tk_symb = INTEGER;
  401. }
  402. /* Now, the pp-number must be converted into a token */
  403. if ((flags & FLG_DOTSEEN)
  404. || (flags & FLG_ESEEN
  405. && !(ch == '0' && (*np == 'x' || *np == 'X')))) {
  406. strflt2tok(&buf[0], ptok);
  407. return ptok->tk_symb = FLOATING;
  408. }
  409. strint2tok(&buf[0], ptok);
  410. return ptok->tk_symb = INTEGER;
  411. }
  412. case STEOI: /* end of text on source file */
  413. return ptok->tk_symb = EOI;
  414. #ifndef NOPP
  415. case STMSPEC:
  416. if (!InputLevel) goto garbage;
  417. if (ch == TOKSEP) goto again;
  418. /* fallthrough shouldn't happen */
  419. #endif
  420. default: /* this cannot happen */
  421. crash("bad class for char 0%o", ch);
  422. }
  423. /*NOTREACHED*/
  424. return 0;
  425. }
  426. #ifndef NOPP
  427. void skipcomment()
  428. {
  429. /* The last character read has been the '*' of '/_*'. The
  430. characters, except NL and EOI, between '/_*' and the first
  431. occurring '*_/' are not interpreted.
  432. NL only affects the LineNumber. EOI is not legal.
  433. Important note: it is not possible to stop skipping comment
  434. beyond the end-of-file of an included file.
  435. EOI is returned by LoadChar only on encountering EOF of the
  436. top-level file...
  437. */
  438. int c, oldc = '\0';
  439. NoUnstack++;
  440. c = GetChar();
  441. #ifdef LINT
  442. if (! lint_skip_comment) {
  443. lint_start_comment();
  444. lint_comment_char(c);
  445. }
  446. #endif /* LINT */
  447. do {
  448. while (c != '*') {
  449. if (class(c) == STNL) {
  450. ++LineNumber;
  451. } else if (c == EOI) {
  452. NoUnstack--;
  453. #ifdef LINT
  454. if (! lint_skip_comment) lint_end_comment();
  455. #endif /* LINT */
  456. return;
  457. }
  458. oldc = c;
  459. c = GetChar();
  460. #ifdef LINT
  461. if (! lint_skip_comment) lint_comment_char(c);
  462. #endif /* LINT */
  463. } /* last Character seen was '*' */
  464. c = GetChar();
  465. if ( c != '/' && oldc == '/')
  466. lexwarning("comment inside comment ?");
  467. oldc = '*';
  468. #ifdef LINT
  469. if (! lint_skip_comment) lint_comment_char(c);
  470. #endif /* LINT */
  471. } while (c != '/');
  472. #ifdef LINT
  473. if (! lint_skip_comment) lint_end_comment();
  474. #endif /* LINT */
  475. NoUnstack--;
  476. }
  477. #endif /* NOPP */
  478. arith char_constant(char *nm)
  479. {
  480. arith val = 0;
  481. int ch;
  482. int size = 0;
  483. ch = GetChar();
  484. if (ch == '\'')
  485. lexerror("%s constant too short", nm);
  486. else
  487. while (ch != '\'') {
  488. if (ch == '\n') {
  489. lexerror("newline in %s constant", nm);
  490. LineNumber++;
  491. break;
  492. }
  493. if (ch == '\\')
  494. ch = quoted(GetChar());
  495. if (ch >= 128) ch -= 256;
  496. if (size < (int)int_size)
  497. val |= ch << 8 * size;
  498. size++;
  499. ch = GetChar();
  500. }
  501. if (size > 1)
  502. lexstrict("%s constant includes more than one character", nm);
  503. if (size > (int)int_size)
  504. lexerror("%s constant too long", nm);
  505. return val;
  506. }
  507. char *string_token(char *nm, int stop_char, int *plen)
  508. {
  509. int ch;
  510. int str_size;
  511. char *str = Malloc((unsigned) (str_size = ISTRSIZE));
  512. int pos = 0;
  513. ch = GetChar();
  514. while (ch != stop_char) {
  515. if (ch == '\n') {
  516. lexerror("newline in %s", nm);
  517. LineNumber++;
  518. break;
  519. }
  520. if (ch == EOI) {
  521. lexerror("end-of-file inside %s", nm);
  522. break;
  523. }
  524. if (ch == '\\' && !AccFileSpecifier)
  525. ch = quoted(GetChar());
  526. str[pos++] = ch;
  527. if (pos == str_size)
  528. str = Realloc(str, (unsigned) (str_size += RSTRSIZE));
  529. ch = GetChar();
  530. }
  531. str[pos++] = '\0'; /* for filenames etc. */
  532. *plen = pos;
  533. return str;
  534. }
  535. int quoted(int ch)
  536. {
  537. /* quoted() replaces an escaped character sequence by the
  538. character meant.
  539. */
  540. /* first char after backslash already in ch */
  541. if (!is_oct(ch)) { /* a quoted char */
  542. switch (ch) {
  543. case 'n':
  544. ch = '\n';
  545. break;
  546. case 't':
  547. ch = '\t';
  548. break;
  549. case 'b':
  550. ch = '\b';
  551. break;
  552. case 'r':
  553. ch = '\r';
  554. break;
  555. case 'f':
  556. ch = '\f';
  557. break;
  558. case 'a': /* alert */
  559. ch = '\007';
  560. break;
  561. case 'v': /* vertical tab */
  562. ch = '\013';
  563. break;
  564. case 'x': /* quoted hex */
  565. {
  566. register int hex = 0;
  567. register int vch;
  568. for (;;) {
  569. ch = GetChar();
  570. if ((vch = hex_val(ch)) == -1)
  571. break;
  572. hex = hex * 16 + vch;
  573. }
  574. UnGetChar();
  575. ch = hex;
  576. }
  577. }
  578. }
  579. else { /* a quoted octal */
  580. register int oct = 0, cnt = 0;
  581. do {
  582. oct = oct*8 + (ch-'0');
  583. ch = GetChar();
  584. } while (is_oct(ch) && ++cnt < 3);
  585. UnGetChar();
  586. ch = oct;
  587. }
  588. return ch&0377;
  589. }
  590. int hex_val(int ch)
  591. {
  592. return is_dig(ch) ? ch - '0'
  593. : is_hex(ch) ? (ch - 'a' + 10) & 017
  594. : -1;
  595. }
  596. int GetChar()
  597. {
  598. /* The routines GetChar and trigraph parses the trigraph
  599. sequences and removes occurences of \\\n.
  600. */
  601. int ch;
  602. #ifndef NOPP
  603. again:
  604. #endif
  605. LoadChar(ch);
  606. #ifndef NOPP
  607. /* possible trigraph sequence */
  608. if (ch == '?')
  609. ch = trigraph();
  610. /* \<newline> is removed from the input stream */
  611. if (ch == '\\') {
  612. LoadChar(ch);
  613. if (ch == '\n') {
  614. ++LineNumber;
  615. goto again;
  616. }
  617. PushBack();
  618. ch = '\\';
  619. }
  620. #endif
  621. return(LexSave = ch);
  622. }
  623. #ifndef NOPP
  624. int trigraph()
  625. {
  626. int ch;
  627. LoadChar(ch);
  628. if (ch == '?') {
  629. LoadChar(ch);
  630. switch (ch) { /* its a trigraph */
  631. case '=':
  632. ch = '#';
  633. return(ch);
  634. case '(':
  635. ch = '[';
  636. return(ch);
  637. case '/':
  638. ch = '\\';
  639. return(ch);
  640. case ')':
  641. ch = ']';
  642. return(ch);
  643. case '\'':
  644. ch = '^';
  645. return(ch);
  646. case '<':
  647. ch = '{';
  648. return(ch);
  649. case '!':
  650. ch = '|';
  651. return(ch);
  652. case '>':
  653. ch = '}';
  654. return(ch);
  655. case '-':
  656. ch = '~';
  657. return(ch);
  658. }
  659. PushBack();
  660. }
  661. PushBack();
  662. return('?');
  663. }
  664. #endif
  665. /* strflt2tok only checks the syntax of the floating-point number and
  666. * selects the right type for the number.
  667. */
  668. void strflt2tok(char fltbuf[], struct token *ptok)
  669. {
  670. char *cp = fltbuf;
  671. int malformed = 0;
  672. while (is_dig(*cp)) cp++;
  673. if (*cp == '.') {
  674. cp++;
  675. while (is_dig(*cp)) cp++;
  676. }
  677. if (*cp == 'e' || *cp == 'E') {
  678. cp++;
  679. if (*cp == '+' || *cp == '-')
  680. cp++;
  681. if (!is_dig(*cp)) malformed++;
  682. while (is_dig(*cp)) cp++;
  683. }
  684. if (*cp == 'f' || *cp == 'F') {
  685. if (*(cp + 1)) malformed++;
  686. *cp = '\0';
  687. ptok->tk_fund = FLOAT;
  688. } else if (*cp == 'l' || *cp == 'L') {
  689. if (*(cp + 1)) malformed++;
  690. *cp = '\0';
  691. ptok->tk_fund = LNGDBL;
  692. } else {
  693. if (*cp) malformed++;
  694. ptok->tk_fund = DOUBLE;
  695. }
  696. if (malformed) {
  697. lexerror("malformed floating constant");
  698. ptok->tk_fval = Salloc("0.0", (unsigned) 4);
  699. } else {
  700. ptok->tk_fval = Salloc(fltbuf, (unsigned) (cp - fltbuf + 1));
  701. }
  702. }
  703. void strint2tok(char intbuf[], struct token *ptok)
  704. {
  705. char *cp = intbuf;
  706. int base = 10;
  707. arith val = 0, dig, ubound;
  708. int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
  709. int fund;
  710. ASSERT(*cp != '-');
  711. if (*cp == '0') {
  712. cp++;
  713. if (*cp == 'x' || *cp == 'X') {
  714. cp++;
  715. base = 16;
  716. } else base = 8;
  717. }
  718. /* The upperbound will be the same as when computed with
  719. * max_unsigned_arith / base (since base is even). The problem here
  720. * is that unsigned arith is not accepted by all compilers.
  721. */
  722. ubound = max_arith / (base / 2);
  723. while (is_hex(*cp)) {
  724. dig = hex_val(*cp);
  725. if (dig >= base) {
  726. malformed++; /* ignore */
  727. }
  728. else {
  729. if (val < 0 || val > ubound) ovfl++;
  730. val *= base;
  731. if (val < 0 && val + dig >= 0) ovfl++;
  732. val += dig;
  733. }
  734. cp++;
  735. }
  736. while (*cp) {
  737. if (*cp == 'l' || *cp == 'L') lng_flg++;
  738. else if (*cp == 'u' || *cp == 'U') uns_flg++;
  739. else break;
  740. cp++;
  741. }
  742. if (*cp) {
  743. malformed++;
  744. }
  745. if (malformed) {
  746. lexerror("malformed %s integer constant",
  747. (base == 10 ? "decimal"
  748. : (base == 8 ? "octal"
  749. : "hexadecimal")));
  750. } else {
  751. if (lng_flg > 1)
  752. lexerror("only one long suffix allowed");
  753. if (uns_flg > 1)
  754. lexerror("only one unsigned suffix allowed");
  755. }
  756. if (ovfl) {
  757. lexwarning("overflow in constant");
  758. fund = ULONG;
  759. } else if (!lng_flg && (val & full_mask[(int)int_size]) == val) {
  760. if (val >= 0 && val <= max_int) {
  761. fund = INT;
  762. } else if (int_size == long_size) {
  763. fund = UNSIGNED;
  764. } else if (base == 10 && !uns_flg)
  765. fund = LONG;
  766. else fund = UNSIGNED;
  767. } else if((val & full_mask[(int)long_size]) == val) {
  768. if (val >= 0) fund = LONG;
  769. else fund = ULONG;
  770. } else { /* sizeof(arith) is greater than long_size */
  771. ASSERT(arith_size > long_size);
  772. lexwarning("constant too large for target machine");
  773. /* cut the size to prevent further complaints */
  774. val &= full_mask[(int)long_size];
  775. fund = ULONG;
  776. }
  777. if (lng_flg) {
  778. /* fund can't be INT */
  779. if (fund == UNSIGNED) fund = ULONG;
  780. }
  781. if (uns_flg) {
  782. if (fund == INT) fund = UNSIGNED;
  783. else if (fund == LONG) fund = ULONG;
  784. }
  785. ptok->tk_fund = fund;
  786. ptok->tk_ival = val;
  787. }