LLlex.c 18 KB

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