LLlex.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  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. PushLex()
  59. {
  60. ASSERT(LexSP < MAX_LL_DEPTH);
  61. ASSERT(ASIDE == 0); /* ASIDE = 0; */
  62. GetToken(&ahead);
  63. LexStack[LexSP++] = dot;
  64. }
  65. PopLex()
  66. {
  67. ASSERT(LexSP > 0);
  68. dot = LexStack[--LexSP];
  69. }
  70. #endif /* NOPP */
  71. int
  72. LLlex()
  73. {
  74. /* LLlex() plays the role of Lexical Analyzer for the C parser.
  75. The look-ahead and putting aside of tokens are taken into
  76. account.
  77. */
  78. if (ASIDE) { /* a token is put aside */
  79. dot = aside;
  80. ASIDE = 0;
  81. }
  82. else { /* read ahead and return the old one */
  83. #ifdef LINT
  84. lint_comment_ahead();
  85. #endif /* LINT */
  86. dot = ahead;
  87. /* the following test is performed due to the dual
  88. task of LLlex(): it is also called for parsing the
  89. restricted constant expression following a #if or
  90. #elif. The newline character causes EOF to be
  91. returned in this case to stop the LLgen parsing task.
  92. */
  93. if (DOT != EOI)
  94. GetToken(&ahead);
  95. else
  96. DOT = EOF;
  97. }
  98. return DOT;
  99. }
  100. char *string_token();
  101. arith char_constant();
  102. int
  103. GetToken(ptok)
  104. register 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. register 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",
  214. '>', &(ptok->tk_len));
  215. return ptok->tk_symb = FILESPECIFIER;
  216. }
  217. if (nch == '<') {
  218. if ((nch = GetChar()) == '=')
  219. return ptok->tk_symb = LEFTAB;
  220. UnGetChar();
  221. return ptok->tk_symb = LEFT;
  222. }
  223. if (nch == '=')
  224. return ptok->tk_symb = LESSEQ;
  225. break;
  226. case '=':
  227. if (nch == '=')
  228. return ptok->tk_symb = EQUAL;
  229. break;
  230. case '>':
  231. if (nch == '=')
  232. return ptok->tk_symb = GREATEREQ;
  233. if (nch == '>') {
  234. if ((nch = GetChar()) == '=')
  235. return ptok->tk_symb = RIGHTAB;
  236. UnGetChar();
  237. return ptok->tk_symb = RIGHT;
  238. }
  239. break;
  240. case '|':
  241. if (nch == '|')
  242. return ptok->tk_symb = OR;
  243. if (nch == '=')
  244. return ptok->tk_symb = ORAB;
  245. break;
  246. case '%':
  247. if (nch == '=')
  248. return ptok->tk_symb = MODAB;
  249. break;
  250. case '*':
  251. if (nch == '=')
  252. return ptok->tk_symb = TIMESAB;
  253. break;
  254. case '^':
  255. if (nch == '=')
  256. return ptok->tk_symb = XORAB;
  257. break;
  258. case '/':
  259. #ifndef NOPP
  260. if (nch == '*' && !InputLevel) {
  261. skipcomment();
  262. goto again;
  263. }
  264. #endif
  265. if (nch == '=')
  266. return ptok->tk_symb = DIVAB;
  267. break;
  268. default:
  269. crash("bad class for char 0%o", ch);
  270. /* NOTREACHED */
  271. }
  272. UnGetChar();
  273. return ptok->tk_symb = ch;
  274. case STCHAR: /* character constant */
  275. ptok->tk_ival = char_constant("character");
  276. ptok->tk_fund = INT;
  277. return ptok->tk_symb = INTEGER;
  278. case STSTR: /* string */
  279. ptok->tk_bts = string_token("string", '"', &(ptok->tk_len));
  280. ptok->tk_fund = CHAR; /* string of characters */
  281. return ptok->tk_symb = STRING;
  282. case STELL: /* wide character constant/string prefix */
  283. nch = GetChar();
  284. if (nch == '"') {
  285. ptok->tk_bts = string_token("wide character string",
  286. '"', &(ptok->tk_len));
  287. ptok->tk_fund = WCHAR; /* string of wide characters */
  288. return ptok->tk_symb = STRING;
  289. } else if (nch == '\'') {
  290. ptok->tk_ival = char_constant("wide character");
  291. ptok->tk_fund = INT;
  292. return ptok->tk_symb = INTEGER;
  293. }
  294. UnGetChar();
  295. /* fallthrough */
  296. case STIDF:
  297. {
  298. register char *tg = &buf[0];
  299. register int pos = -1;
  300. register struct idf *idef;
  301. extern int idfsize; /* ??? */
  302. #ifndef NOPP
  303. int NoExpandNext = 0;
  304. if (Unstacked) EnableMacros(); /* unstack macro's when allowed. */
  305. if (ch == NOEXPM) {
  306. NoExpandNext = 1;
  307. ch = GetChar();
  308. }
  309. #endif
  310. do { /* read the identifier */
  311. if (++pos < idfsize) {
  312. *tg++ = ch;
  313. }
  314. ch = GetChar();
  315. } while (in_idf(ch));
  316. if (ch != EOI)
  317. UnGetChar();
  318. *tg++ = '\0'; /* mark the end of the identifier */
  319. idef = ptok->tk_idf = str2idf(buf, 1);
  320. sp_occurred[idef->id_special] = 1;
  321. idef->id_file = ptok->tk_file;
  322. idef->id_line = ptok->tk_line;
  323. #ifndef NOPP
  324. if (idef->id_macro && ReplaceMacros && !NoExpandNext) {
  325. if (replace(idef))
  326. goto again;
  327. }
  328. if (UnknownIdIsZero && idef->id_reserved != SIZEOF) {
  329. ptok->tk_ival = (arith)0;
  330. ptok->tk_fund = INT;
  331. return ptok->tk_symb = INTEGER;
  332. }
  333. #endif /* NOPP */
  334. ptok->tk_symb = (
  335. idef->id_reserved
  336. ? idef->id_reserved
  337. : idef->id_def && idef->id_def->df_sc == TYPEDEF
  338. ? TYPE_IDENTIFIER
  339. : IDENTIFIER
  340. );
  341. return IDENTIFIER;
  342. }
  343. case STNUM: /* a numeric constant */
  344. {
  345. register int siz_left = NUMSIZE - 1;
  346. register char *np = &buf[0];
  347. int flags = 0;
  348. #define store(ch) if (--siz_left >= 0) \
  349. *np++ = ch;
  350. if (ch == '.') {
  351. /* An embarrasing ambiguity. We have either a
  352. pp-number, a field operator, an ELLIPSIS or
  353. an error (..).
  354. */
  355. ch = GetChar();
  356. if (!is_dig(ch)) { /* . or ... */
  357. if (ch == '.') {
  358. if ((ch = GetChar()) == '.')
  359. return ptok->tk_symb = ELLIPSIS;
  360. UnGetChar(); /* not '.' */
  361. ChPushBack('.'); /* sigh ... */
  362. } else
  363. UnGetChar(); /* not '.' */
  364. return ptok->tk_symb = '.';
  365. }
  366. UnGetChar();
  367. ch = '.';
  368. flags |= FLG_DOTSEEN;
  369. }
  370. store(ch);
  371. ch = GetChar();
  372. while(in_idf(ch) || ch == '.') {
  373. store(ch);
  374. if (ch == '.') flags |= FLG_DOTSEEN;
  375. if (ch == 'e' || ch == 'E') {
  376. flags |= FLG_ESEEN;
  377. ch = GetChar();
  378. if (ch == '+' || ch == '-') {
  379. flags |= FLG_DOTSEEN; /* trick */
  380. store(ch);
  381. ch = GetChar();
  382. }
  383. } else ch = GetChar();
  384. }
  385. store('\0');
  386. UnGetChar();
  387. np = &buf[0];
  388. ch = *np++;
  389. if (siz_left < 0) {
  390. lexerror("number too long");
  391. if ((flags & FLG_DOTSEEN)
  392. || (flags & FLG_ESEEN
  393. && !(ch == '0'
  394. && (*np == 'x' || *np == 'X')))) {
  395. ptok->tk_fval = Salloc("0.0", (unsigned) 4);
  396. ptok->tk_fund = DOUBLE;
  397. return ptok->tk_symb = FLOATING;
  398. }
  399. ptok->tk_ival = 1;
  400. ptok->tk_fund = ULONG;
  401. ptok->tk_symb = INTEGER;
  402. }
  403. /* Now, the pp-number must be converted into a token */
  404. if ((flags & FLG_DOTSEEN)
  405. || (flags & FLG_ESEEN
  406. && !(ch == '0' && (*np == 'x' || *np == 'X')))) {
  407. strflt2tok(&buf[0], ptok);
  408. return ptok->tk_symb = FLOATING;
  409. }
  410. strint2tok(&buf[0], ptok);
  411. return ptok->tk_symb = INTEGER;
  412. }
  413. case STEOI: /* end of text on source file */
  414. return ptok->tk_symb = EOI;
  415. #ifndef NOPP
  416. case STMSPEC:
  417. if (!InputLevel) goto garbage;
  418. if (ch == TOKSEP) goto again;
  419. /* fallthrough shouldn't happen */
  420. #endif
  421. default: /* this cannot happen */
  422. crash("bad class for char 0%o", ch);
  423. }
  424. /*NOTREACHED*/
  425. }
  426. #ifndef NOPP
  427. 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. register 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
  479. char_constant(nm)
  480. char *nm;
  481. {
  482. register arith val = 0;
  483. register int ch;
  484. int size = 0;
  485. ch = GetChar();
  486. if (ch == '\'')
  487. lexerror("%s constant too short", nm);
  488. else
  489. while (ch != '\'') {
  490. if (ch == '\n') {
  491. lexerror("newline in %s constant", nm);
  492. LineNumber++;
  493. break;
  494. }
  495. if (ch == '\\')
  496. ch = quoted(GetChar());
  497. if (ch >= 128) ch -= 256;
  498. if (size < (int)int_size)
  499. val |= ch << 8 * size;
  500. size++;
  501. ch = GetChar();
  502. }
  503. if (size > 1)
  504. lexstrict("%s constant includes more than one character", nm);
  505. if (size > (int)int_size)
  506. lexerror("%s constant too long", nm);
  507. return val;
  508. }
  509. char *
  510. string_token(nm, stop_char, plen)
  511. char *nm;
  512. int *plen;
  513. {
  514. register int ch;
  515. register int str_size;
  516. register char *str = Malloc((unsigned) (str_size = ISTRSIZE));
  517. register int pos = 0;
  518. ch = GetChar();
  519. while (ch != stop_char) {
  520. if (ch == '\n') {
  521. lexerror("newline in %s", nm);
  522. LineNumber++;
  523. break;
  524. }
  525. if (ch == EOI) {
  526. lexerror("end-of-file inside %s", nm);
  527. break;
  528. }
  529. if (ch == '\\' && !AccFileSpecifier)
  530. ch = quoted(GetChar());
  531. str[pos++] = ch;
  532. if (pos == str_size)
  533. str = Realloc(str, (unsigned) (str_size += RSTRSIZE));
  534. ch = GetChar();
  535. }
  536. str[pos++] = '\0'; /* for filenames etc. */
  537. *plen = pos;
  538. return str;
  539. }
  540. int
  541. quoted(ch)
  542. register int ch;
  543. {
  544. /* quoted() replaces an escaped character sequence by the
  545. character meant.
  546. */
  547. /* first char after backslash already in ch */
  548. if (!is_oct(ch)) { /* a quoted char */
  549. switch (ch) {
  550. case 'n':
  551. ch = '\n';
  552. break;
  553. case 't':
  554. ch = '\t';
  555. break;
  556. case 'b':
  557. ch = '\b';
  558. break;
  559. case 'r':
  560. ch = '\r';
  561. break;
  562. case 'f':
  563. ch = '\f';
  564. break;
  565. case 'a': /* alert */
  566. ch = '\007';
  567. break;
  568. case 'v': /* vertical tab */
  569. ch = '\013';
  570. break;
  571. case 'x': /* quoted hex */
  572. {
  573. register int hex = 0;
  574. register int vch;
  575. for (;;) {
  576. ch = GetChar();
  577. if ((vch = hex_val(ch)) == -1)
  578. break;
  579. hex = hex * 16 + vch;
  580. }
  581. UnGetChar();
  582. ch = hex;
  583. }
  584. }
  585. }
  586. else { /* a quoted octal */
  587. register int oct = 0, cnt = 0;
  588. do {
  589. oct = oct*8 + (ch-'0');
  590. ch = GetChar();
  591. } while (is_oct(ch) && ++cnt < 3);
  592. UnGetChar();
  593. ch = oct;
  594. }
  595. return ch&0377;
  596. }
  597. int
  598. hex_val(ch)
  599. register int ch;
  600. {
  601. return is_dig(ch) ? ch - '0'
  602. : is_hex(ch) ? (ch - 'a' + 10) & 017
  603. : -1;
  604. }
  605. int
  606. GetChar()
  607. {
  608. /* The routines GetChar and trigraph parses the trigraph
  609. sequences and removes occurences of \\\n.
  610. */
  611. register int ch;
  612. #ifndef NOPP
  613. again:
  614. #endif
  615. LoadChar(ch);
  616. #ifndef NOPP
  617. /* possible trigraph sequence */
  618. if (ch == '?')
  619. ch = trigraph();
  620. /* \<newline> is removed from the input stream */
  621. if (ch == '\\') {
  622. LoadChar(ch);
  623. if (ch == '\n') {
  624. ++LineNumber;
  625. goto again;
  626. }
  627. PushBack();
  628. ch = '\\';
  629. }
  630. #endif
  631. return(LexSave = ch);
  632. }
  633. #ifndef NOPP
  634. int
  635. trigraph()
  636. {
  637. register int ch;
  638. LoadChar(ch);
  639. if (ch == '?') {
  640. LoadChar(ch);
  641. switch (ch) { /* its a trigraph */
  642. case '=':
  643. ch = '#';
  644. return(ch);
  645. case '(':
  646. ch = '[';
  647. return(ch);
  648. case '/':
  649. ch = '\\';
  650. return(ch);
  651. case ')':
  652. ch = ']';
  653. return(ch);
  654. case '\'':
  655. ch = '^';
  656. return(ch);
  657. case '<':
  658. ch = '{';
  659. return(ch);
  660. case '!':
  661. ch = '|';
  662. return(ch);
  663. case '>':
  664. ch = '}';
  665. return(ch);
  666. case '-':
  667. ch = '~';
  668. return(ch);
  669. }
  670. PushBack();
  671. }
  672. PushBack();
  673. return('?');
  674. }
  675. #endif
  676. /* strflt2tok only checks the syntax of the floating-point number and
  677. * selects the right type for the number.
  678. */
  679. strflt2tok(fltbuf, ptok)
  680. char fltbuf[];
  681. struct token *ptok;
  682. {
  683. register char *cp = fltbuf;
  684. int malformed = 0;
  685. while (is_dig(*cp)) cp++;
  686. if (*cp == '.') {
  687. cp++;
  688. while (is_dig(*cp)) cp++;
  689. }
  690. if (*cp == 'e' || *cp == 'E') {
  691. cp++;
  692. if (*cp == '+' || *cp == '-')
  693. cp++;
  694. if (!is_dig(*cp)) malformed++;
  695. while (is_dig(*cp)) cp++;
  696. }
  697. if (*cp == 'f' || *cp == 'F') {
  698. if (*(cp + 1)) malformed++;
  699. *cp = '\0';
  700. ptok->tk_fund = FLOAT;
  701. } else if (*cp == 'l' || *cp == 'L') {
  702. if (*(cp + 1)) malformed++;
  703. *cp = '\0';
  704. ptok->tk_fund = LNGDBL;
  705. } else {
  706. if (*cp) malformed++;
  707. ptok->tk_fund = DOUBLE;
  708. }
  709. if (malformed) {
  710. lexerror("malformed floating constant");
  711. ptok->tk_fval = Salloc("0.0", (unsigned) 4);
  712. } else {
  713. ptok->tk_fval = Salloc(fltbuf, (unsigned) (cp - fltbuf + 1));
  714. }
  715. }
  716. strint2tok(intbuf, ptok)
  717. char intbuf[];
  718. struct token *ptok;
  719. {
  720. register char *cp = intbuf;
  721. int base = 10;
  722. arith val = 0, dig, ubound;
  723. int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
  724. int fund;
  725. ASSERT(*cp != '-');
  726. if (*cp == '0') {
  727. cp++;
  728. if (*cp == 'x' || *cp == 'X') {
  729. cp++;
  730. base = 16;
  731. } else base = 8;
  732. }
  733. /* The upperbound will be the same as when computed with
  734. * max_unsigned_arith / base (since base is even). The problem here
  735. * is that unsigned arith is not accepted by all compilers.
  736. */
  737. ubound = max_arith / (base / 2);
  738. while (is_hex(*cp)) {
  739. dig = hex_val(*cp);
  740. if (dig >= base) {
  741. malformed++; /* ignore */
  742. }
  743. else {
  744. if (val < 0 || val > ubound) ovfl++;
  745. val *= base;
  746. if (val < 0 && val + dig >= 0) ovfl++;
  747. val += dig;
  748. }
  749. cp++;
  750. }
  751. while (*cp) {
  752. if (*cp == 'l' || *cp == 'L') lng_flg++;
  753. else if (*cp == 'u' || *cp == 'U') uns_flg++;
  754. else break;
  755. cp++;
  756. }
  757. if (*cp) {
  758. malformed++;
  759. }
  760. if (malformed) {
  761. lexerror("malformed %s integer constant",
  762. (base == 10 ? "decimal"
  763. : (base == 8 ? "octal"
  764. : "hexadecimal")));
  765. } else {
  766. if (lng_flg > 1)
  767. lexerror("only one long suffix allowed");
  768. if (uns_flg > 1)
  769. lexerror("only one unsigned suffix allowed");
  770. }
  771. if (ovfl) {
  772. lexwarning("overflow in constant");
  773. fund = ULONG;
  774. } else if (!lng_flg && (val & full_mask[(int)int_size]) == val) {
  775. if (val >= 0 && val <= max_int) {
  776. fund = INT;
  777. } else if (int_size == long_size) {
  778. fund = UNSIGNED;
  779. } else if (base == 10 && !uns_flg)
  780. fund = LONG;
  781. else fund = UNSIGNED;
  782. } else if((val & full_mask[(int)long_size]) == val) {
  783. if (val >= 0) fund = LONG;
  784. else fund = ULONG;
  785. } else { /* sizeof(arith) is greater than long_size */
  786. ASSERT(arith_size > long_size);
  787. lexwarning("constant too large for target machine");
  788. /* cut the size to prevent further complaints */
  789. val &= full_mask[(int)long_size];
  790. fund = ULONG;
  791. }
  792. if (lng_flg) {
  793. /* fund can't be INT */
  794. if (fund == UNSIGNED) fund = ULONG;
  795. }
  796. if (uns_flg) {
  797. if (fund == INT) fund = UNSIGNED;
  798. else if (fund == LONG) fund = ULONG;
  799. }
  800. ptok->tk_fund = fund;
  801. ptok->tk_ival = val;
  802. }