PageRenderTime 78ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/SN-NG4.1/snavigator/parsers/fortran/forlex.c

https://gitlab.com/OpenSourceMirror/sourcenav
C | 1968 lines | 1514 code | 188 blank | 266 comment | 350 complexity | 7f0d7a98dc59265b01afc6d2b1255eca MD5 | raw file
  1. /*
  2. Copyright (c) 2000, Red Hat, Inc.
  3. This file is part of Source-Navigator.
  4. Source-Navigator is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. Source-Navigator is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with Source-Navigator; see the file COPYING. If not, write to
  14. the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
  15. MA 02111-1307, USA.
  16. */
  17. /* forlex.c:
  18. Tokenizing routines for Fortran program checker.
  19. This version implements blank-insensitivity.
  20. Copyright (C) 1993 by Robert K. Moniot.
  21. This program is free software. Permission is granted to
  22. modify it and/or redistribute it, retaining this notice.
  23. No guarantees accompany this software.
  24. Part I. yylex() -- gives tokens to the parser.
  25. Part II. advance() -- bottom-level scanning of input stream.
  26. */
  27. #define CASE_SENSITIVE
  28. /* Declarations shared by all modules */
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include <string.h>
  32. #if defined (__MSVC__) || defined(__STDC__) || defined(__osf__)
  33. #include <stdlib.h>
  34. #else
  35. char *getenv();
  36. #endif
  37. #include <tcl.h>
  38. #include "ftnchek.h"
  39. #define FORLEX
  40. #include "symtab.h"
  41. #include "fortran.h"
  42. #include "sn.h"
  43. int max_line_width = 0;
  44. extern FILE *hig_fp;
  45. extern int highlight;
  46. extern Tcl_Encoding encoding;
  47. /* lexdefs.h:
  48. Macros and shared info for lexical analysis routines
  49. */
  50. #define LEX_SHARED PRIVATE
  51. #define EOL '\n' /* Character for end of line, not of statement */
  52. extern YYSTYPE yylval; /* Lexical value for Yacc */
  53. /* Since EOS is special, need special macros for it */
  54. #define makeupper(C) (((C) != EOS && islower((int)(C)))? toupper((int)(C)):(C))
  55. #define iswhitespace(C) ( (C) != EOS && isspace((int)(C)) )
  56. #define isadigit(C) ( (C) != EOS && isdigit((int)(C)) )
  57. #define isaletter(C) ( (C) != EOS && isalpha((int)(C)) )
  58. #define ishex(C) ((C) != EOS && (isdigit((int)(C)) ||\
  59. (toupper((int)(C))>='A' && toupper((int)(C))<='F') ))
  60. /* define isidletter to allow underscore and/or dollar sign or not */
  61. /* both underscore and dollar sign */
  62. #define isidletter(C) ( (C) != EOS && (isalpha((int)(C)) || \
  63. (C) == '_' || (C) == '$' ) )
  64. #define BCD(C) ((C)-'0') /* Binary value of digit */
  65. #define HEX(C) (isdigit(C)?BCD(C):(makeupper(C)-'A'+10)) /* Hex value */
  66. /* Blank-insensitive advance */
  67. #define bi_advance() do {advance();} while(iswhitespace(curr_char))
  68. #define bi_advanceX() { do {advance(); i_white++; } while(iswhitespace(curr_char)); }
  69. LEX_SHARED int
  70. inside_string, /* TRUE when reading a string or hollerith */
  71. inside_hollerith, /* TRUE when reading a hollerith */
  72. WHILE_expected, /* DO seen and WHILE is coming up */
  73. contin_count, /* Number of continuation lines of stmt */
  74. prev_char, /* shared between forlex.c and advance.c */
  75. curr_char, /* Current input character */
  76. next_char; /* Lookahead character */
  77. #ifdef UNIX_CPP
  78. LEX_SHARED char
  79. *next_filename;
  80. LEX_SHARED int
  81. cpp_handled;
  82. #endif
  83. PRIVATE char acSymbol[1000];
  84. PRIVATE int Symbol_line_num;
  85. PRIVATE int Symbol_col_num;
  86. PRIVATE int Symbol_curr_index;
  87. PRIVATE char acCppInclude[1000];
  88. extern int complex_const_allowed, /* shared flags operated by fortran.y */
  89. inside_format,
  90. integer_context;
  91. extern int stmt_sequence_no; /* shared with fortran.y */
  92. /* Declare shared lexical routines */
  93. LEX_SHARED
  94. void advance();
  95. LEX_SHARED
  96. int is_keyword(), looking_at_cplx(), looking_at_keywd(), looking_at_relop();
  97. #ifdef DEBUG_INCLUDE
  98. LEX_SHARED
  99. int debug_include=FALSE;
  100. #endif
  101. /*
  102. Part I. yylex()
  103. Shared functions defined:
  104. yylex() Returns next token. Called from yyparse().
  105. implied_id_token(t,s) Creates token for blank common declaration.
  106. Note: compilation options LEX_STORE_STRINGS and LEX_STORE_HOLLERITHS:
  107. Define the macro name LEX_STORE_STRINGS to build a version of ftnchek that
  108. stores string constants, and LEX_STORE_HOLLERITHS to store hollerith
  109. constants. Now that INCLUDE statements are supported, strings must
  110. be stored. Holleriths are not used, so they need not be stored.
  111. */
  112. #define LEX_STORE_STRINGS
  113. #ifdef DEVELOPMENT /* For maintaining the program */
  114. abc
  115. #define LEX_STORE_HOLLERITHS
  116. #define DEBUG_FORLEX
  117. #endif
  118. #include <math.h>
  119. /* The following macro says whether a given character is legal,
  120. * i.e. one of the stream control chars or a valid ANSI Fortran
  121. * character. Lower case letters are considered legal too.
  122. * Nondigits in columns 1-6 (except EOF,EOS) are illegal.
  123. * Hopefully this works for EBCDIC too.
  124. */
  125. #define islegal(C) ( ((C) == EOF) || ((C) == EOS) || \
  126. ( (col_num >= 6 || isdigit(C)) && \
  127. ((C) >= ' ' && (C) <= 'z' && \
  128. legal_chars[toascii((int)(C))-toascii(' ')] == (C))) )
  129. /* Array has x where ASCII character is not valid */
  130. PRIVATE char legal_chars[]=
  131. " x\"x$xx'()*+,-./0123456789:x<=>xx\
  132. ABCDEFGHIJKLMNOPQRSTUVWXYZxxxx_xabcdefghijklmnopqrstuvwxyz";
  133. PRIVATE int
  134. #if 0
  135. curr_index, /* Index in line of curr_char */
  136. #endif
  137. next_index; /* Index in line of next_char */
  138. /* local functions defined */
  139. PRIVATE void
  140. #ifdef UNIX_CPP
  141. get_cpp_directive(),
  142. #endif
  143. get_dot(), get_dotted_keyword(), get_edit_descriptor(), get_hollerith(),
  144. get_identifier(), get_illegal_token(), get_label(),
  145. get_letter(), get_number(), get_punctuation(),
  146. get_simple_punctuation(), get_string(),
  147. #ifdef TYPELESS_CONSTANTS
  148. get_binary_const(),
  149. #endif
  150. get_complex_const();
  151. static void save_comment(char *filename, char *func, char *classn, int line_num, int col_num, char *acComment);
  152. PRIVATE void
  153. closeup();
  154. /* Gets next token for Yacc. Return value is token.class,
  155. * and a copy of the token is stored in yylval.
  156. */
  157. int
  158. yylex()
  159. {
  160. Token token;
  161. token.next_token = 0;
  162. token.dot_token = 0;
  163. if( acCppInclude[0] )
  164. {
  165. char acFilename[1000];
  166. strcpy( acFilename, acCppInclude );
  167. acCppInclude[0] = 0;
  168. open_include_file( SN_StrDup( acFilename ));
  169. }
  170. if( acSymbol[0] )
  171. {
  172. int h;
  173. Lsymtab *symt;
  174. /* printf( "acSymbol: <%s> %d %d\n", acSymbol, Symbol_line_num, Symbol_col_num ); */
  175. token.subclass = 0;
  176. token.line_num = Symbol_line_num;
  177. token.col_num = Symbol_col_num;
  178. token.curr_index = Symbol_curr_index;
  179. token.class = tok_identifier;
  180. token.value.integer = h = hash_lookup(acSymbol);
  181. if((symt=hashtab[h].loc_symtab) != NULL && symt->array_var) {
  182. token.class = tok_array_identifier;
  183. }
  184. acSymbol[0] = 0;
  185. yylval = token;
  186. return token.class;
  187. }
  188. /* Initialize token fields to scratch. */
  189. token.subclass = 0;
  190. token.value.integer = 0;
  191. if(curr_char == EOF) {
  192. token.class = EOF;
  193. token.line_num = line_num;
  194. token.col_num = col_num;
  195. token.curr_index = curr_index;
  196. }
  197. else /* not EOF */ {
  198. /* Skip leading spaces, and give error message if non-ANSI
  199. * characters are found.
  200. */
  201. while(iswhitespace(curr_char) || (! islegal(curr_char)) ) {
  202. if(!iswhitespace(curr_char)) {
  203. #ifdef UNIX_CPP
  204. if(curr_char == '#' && col_num == 1) {
  205. get_cpp_directive(); /* turn # line into EOS */
  206. break;
  207. }
  208. else
  209. #endif
  210. yyerror("Illegal character");
  211. }
  212. advance();
  213. }
  214. token.line_num = line_num;
  215. token.col_num = col_num;
  216. token.curr_index = curr_index;
  217. if(inside_format) { /* Handle format stuff here to avoid trouble */
  218. get_edit_descriptor(&token);
  219. }
  220. else if(isadigit(curr_char)) {
  221. if(col_num < 6)
  222. get_label(&token); /* Stmt label */
  223. else
  224. get_number(&token); /* Numeric or hollerith const */
  225. }
  226. else if(isidletter(curr_char)) {
  227. if(implicit_letter_flag)
  228. get_letter(&token); /* letter in IMPLICIT list */
  229. else
  230. get_identifier(&token); /* Identifier or keyword */
  231. }
  232. else if(curr_char == '\'' || curr_char == '"') {
  233. get_string(&token); /* Quoted string */
  234. }
  235. else if(curr_char == '.') {
  236. get_dot(&token); /* '.' lead-in */
  237. }
  238. else {
  239. get_punctuation(&token); /* Punctuation character or EOS */
  240. }
  241. }/*end not EOF*/
  242. if(token.class == EOS) {
  243. implicit_flag=FALSE; /* in case of errors, reset flags */
  244. implicit_letter_flag = FALSE;
  245. }
  246. prev_token_class = token.class;
  247. yylval = token;
  248. /* printf( "Token: %d\n", token.class ); */
  249. return token.class;
  250. } /* yylex */
  251. /* Fills argument with token for an identifer, as if an identifer
  252. * with name given by string s had been lexed. This will
  253. * be called by parser when blank common declaration is seen,
  254. * and when a main prog without program statement is found,
  255. * and when an unnamed block data statement is found,
  256. * so processing of named and unnamed cases can be handled uniformly.
  257. */
  258. void
  259. implied_id_token(t,s)
  260. Token *t;
  261. char *s;
  262. {
  263. int h;
  264. unsigned long hnum;
  265. hnum = hash(s);
  266. while( h=hnum%HASHSZ, hashtab[h].name != NULL &&
  267. strcmp(hashtab[h].name,s) != 0)
  268. hnum = rehash(hnum);
  269. if(hashtab[h].name == NULL) { /* not seen before */
  270. hashtab[h].name = s;
  271. hashtab[h].loc_symtab = NULL;
  272. hashtab[h].glob_symtab = NULL;
  273. hashtab[h].com_loc_symtab = NULL;
  274. hashtab[h].com_glob_symtab = NULL;
  275. }
  276. t->class = tok_identifier;
  277. t->value.integer = h;
  278. } /* implied_id_token */
  279. #ifdef UNIX_CPP
  280. /* This does not create a token but just performs the
  281. actions needed when a cpp directive is seen. It
  282. advances curr_char to the EOS. The setting of
  283. filename is delayed to this point because it is not
  284. stored in tokens but is external, so changing it
  285. must wait till the previous statement is fully
  286. parsed and any error messages printed and arg or
  287. com list headers completed.
  288. */
  289. #ifdef rigo
  290. PRIVATE void
  291. get_cpp_directive()
  292. {
  293. if(next_filename != (char *)NULL) {
  294. current_filename = next_filename;
  295. if(incdepth == 0)
  296. top_filename = next_filename;
  297. }
  298. do { /* Skip to end of directive. It will become an EOS */
  299. advance();
  300. } while( curr_char != EOS);
  301. if(f77_standard || !cpp_handled) {
  302. nonstandard(line_num,col_num);
  303. msg_tail(": preprocessor directive");
  304. if(!cpp_handled)
  305. msg_tail("(not processed)");
  306. }
  307. }/*get_cpp_directive*/
  308. #endif
  309. static void get_cpp_directive()
  310. {
  311. char ac[1000];
  312. char *pc;
  313. char *pcFilename;
  314. char *pcDefinename;
  315. int my_line_num;
  316. if( next_filename != (char *)NULL )
  317. {
  318. current_filename = next_filename;
  319. if( incdepth == 0 )
  320. {
  321. top_filename = next_filename;
  322. }
  323. }
  324. pc = ac;
  325. my_line_num = line_num;
  326. do
  327. { /* Skip to end of directive. It will become an EOS */
  328. advance();
  329. *pc++ = curr_char;
  330. } while( curr_char != EOS);
  331. pc[-1] = 0;
  332. for( pc = ac; *pc; pc++ )
  333. {
  334. if( ! isspace( *pc )) break;
  335. }
  336. if( strncmp( pc, "include", 7 ) == 0 )
  337. {
  338. if( hig_fp )
  339. {
  340. if( strcmp( current_filename, top_filename ) == 0 )
  341. {
  342. fprintf( hig_fp, "%d key %d.%d %d.%d\n"
  343. , PAF_HIGH
  344. , my_line_num
  345. , 0
  346. , my_line_num
  347. , pc - ac + 8
  348. );
  349. }
  350. }
  351. pcFilename = 0;
  352. for( ; *pc; pc++ )
  353. {
  354. if( *pc == '"' || *pc == '<' )
  355. {
  356. pcFilename = pc+1;
  357. break;
  358. }
  359. }
  360. if( pcFilename )
  361. {
  362. for( pc = pcFilename; *pc; pc++ )
  363. {
  364. if( *pc == '"' || *pc == '>' )
  365. {
  366. *pc = 0;
  367. break;
  368. }
  369. }
  370. strcpy( acCppInclude, pcFilename );
  371. }
  372. }
  373. else if( strncmp( pc, "define", 6 ) == 0 )
  374. {
  375. int my_index;
  376. if( hig_fp )
  377. {
  378. if( strcmp( current_filename, top_filename ) == 0 )
  379. {
  380. fprintf( hig_fp, "%d key %d.%d %d.%d\n"
  381. , PAF_HIGH
  382. , my_line_num
  383. , 0
  384. , my_line_num
  385. , pc - ac + 7
  386. );
  387. }
  388. }
  389. pcDefinename = 0;
  390. pc += 6;
  391. for( ; *pc; pc++)
  392. {
  393. if( ! iswhitespace( *pc ))
  394. {
  395. pcDefinename = pc;
  396. break;
  397. }
  398. }
  399. my_index = pc - ac + 1;
  400. if( pcDefinename )
  401. {
  402. for( pc = pcDefinename; *pc; pc++ )
  403. {
  404. #ifndef CASE_SENSITIVE
  405. *pc = makeupper( *pc );
  406. #endif
  407. if( iswhitespace( *pc ) || *pc == '(' )
  408. {
  409. *pc = 0;
  410. break;
  411. }
  412. }
  413. /* Identifier: find its hashtable entry or
  414. create a new entry. */
  415. {
  416. int h;
  417. h = hash_lookup(pcDefinename);
  418. hashtab[h].define = 1;
  419. if( highlight != -1 )
  420. {
  421. put_symbol(PAF_CONS_DEF,NULL,pcDefinename,
  422. current_filename,
  423. my_line_num,
  424. my_index,
  425. 0,0,
  426. (long)0,NULL,NULL,NULL,
  427. get_comment(current_filename,my_line_num),
  428. 0,0,0,0);
  429. }
  430. }
  431. }
  432. }
  433. }
  434. #endif
  435. PRIVATE void
  436. get_dot(token)
  437. Token *token;
  438. {
  439. closeup(); /* Advance till nonspace char in next_char */
  440. if(isadigit(next_char))
  441. get_number(token); /* Numeric const */
  442. else if(isaletter(next_char))
  443. get_dotted_keyword(token); /* .EQ. etc. */
  444. else
  445. get_simple_punctuation(token); /* "." out of place */
  446. }
  447. #define MAX_DOTTED_KEYWD (sizeof(".FALSE.")/sizeof(char))
  448. struct {
  449. char *name;
  450. int class,subclass;
  451. } dotted_keywords[]={
  452. {"EQ",tok_relop,relop_EQ},
  453. {"NE",tok_relop,relop_NE},
  454. {"LE",tok_relop,relop_LE},
  455. {"LT",tok_relop,relop_LT},
  456. {"GE",tok_relop,relop_GE},
  457. {"GT",tok_relop,relop_GT},
  458. {"AND",tok_AND,0},
  459. {"OR",tok_OR,0},
  460. {"NOT",tok_NOT,0},
  461. {"FALSE",tok_logical_const,FALSE},
  462. {"TRUE",tok_logical_const,TRUE},
  463. {"EQV",tok_EQV,0},
  464. {"NEQV",tok_NEQV,0},
  465. {NULL,0,0}
  466. };
  467. PRIVATE void
  468. get_dotted_keyword(token)
  469. Token *token;
  470. {
  471. char s[8];
  472. int i=0,
  473. has_embedded_space, /* Spaces inside keyword */
  474. space_seen_lately; /* Flag for catching embedded space */
  475. int j=0;
  476. initial_flag = FALSE;
  477. /* Watch for embedded space, but not
  478. between dots and letters of keyword.
  479. I.e. ". eq ." is OK, but not ".e q." */
  480. has_embedded_space = FALSE;
  481. space_seen_lately = FALSE;
  482. bi_advance(); /* gobble the initial '.' */
  483. Symbol_line_num = line_num;
  484. Symbol_col_num = col_num;
  485. Symbol_curr_index = curr_index;
  486. /* while(isaletter(curr_char)) { */
  487. while(isidletter(curr_char) || isadigit(curr_char)) {
  488. if( i<7 )
  489. s[i++] = makeupper(curr_char);
  490. #ifdef CASE_SENSITIVE
  491. acSymbol[j++] = curr_char;
  492. #else
  493. acSymbol[j++] = makeupper(curr_char);
  494. #endif
  495. if(space_seen_lately)
  496. has_embedded_space = TRUE;
  497. bi_advance();
  498. space_seen_lately = iswhitespace(prev_char);
  499. }
  500. s[i] = '\0';
  501. acSymbol[j] = '\0';
  502. /* printf( "***** <%s>\n", acSymbol ); */
  503. for(i=0; dotted_keywords[i].name != NULL; i++) {
  504. if(strcmp(s,dotted_keywords[i].name) == 0) {
  505. token->class = dotted_keywords[i].class;
  506. token->subclass = dotted_keywords[i].subclass;
  507. token->value.string = dotted_keywords[i].name;
  508. if(curr_char != '.') {
  509. yyerror("Badly formed logical/relational operator or constant");
  510. }
  511. else {
  512. advance(); /* gobble the final '.' */
  513. acSymbol[0] = 0;
  514. }
  515. return;
  516. }
  517. }
  518. /* keyword not found */
  519. token->class = '.';
  520. } /* get_dotted_keyword */
  521. static void get_edit_descriptor(token)
  522. Token *token;
  523. {
  524. while( curr_char != EOS && curr_char != EOF )
  525. {
  526. advance();
  527. };
  528. token->class = EOS;
  529. }
  530. #ifdef rigo
  531. PRIVATE void
  532. get_edit_descriptor(token)
  533. Token *token;
  534. {
  535. int i=0,c;
  536. long repeat_spec;
  537. char s[MAXIDSIZE+1]; /* string holding the descriptor: NOT STORED */
  538. if(isadigit(curr_char)) { /* Digit: repeat spec or holl or kP or nX */
  539. repeat_spec = 0;
  540. do {
  541. repeat_spec = repeat_spec*10L + (long)BCD(curr_char);
  542. if( makeupper(next_char) == 'H' )
  543. inside_hollerith = TRUE;/* get ready for hollerith*/
  544. bi_advance();
  545. } while(isadigit(curr_char));
  546. if( makeupper(curr_char) == 'H' ) {
  547. /* nH... pass off to hollerith routine */
  548. get_hollerith(token, (int)repeat_spec);
  549. return;
  550. }
  551. else {
  552. /* Otherwise it is a repeat spec or the
  553. numeric part of kP or nX which we treat
  554. as repeat specs too */
  555. token->class = tok_integer_const;
  556. token->value.integer = repeat_spec;
  557. #ifdef DEBUG_FORLEX
  558. if(debug_lexer)
  559. fprintf(list_fd,"\nInteger const:\t\t%d",repeat_spec);
  560. #endif
  561. }
  562. }/* end if digit */
  563. else if(isaletter(curr_char)) {
  564. c = makeupper(curr_char);
  565. s[i++] = c;
  566. bi_advance();
  567. switch(c) {
  568. case 'P': /* P of kP k seen previously */
  569. if(prev_token_class != tok_integer_const) {
  570. if(f77_standard){
  571. nonstandard(token->line_num,token->col_num);
  572. msg_tail(": P must follow a number");
  573. }
  574. }
  575. break;
  576. case 'X': /* X or nX */
  577. break;
  578. case 'S': /* S or SP or SS */
  579. c = makeupper(curr_char);
  580. if(c == 'S' || c == 'P') {
  581. s[i++] = c;
  582. bi_advance();
  583. }
  584. break;
  585. case 'B': /* BN or BZ */
  586. c = makeupper(curr_char);
  587. if(c == 'N' || c == 'Z') {
  588. s[i++] = c;
  589. bi_advance();
  590. }
  591. else {
  592. if(f77_standard){
  593. nonstandard(token->line_num,token->col_num);
  594. msg_tail(": N or Z expected after B");
  595. }
  596. }
  597. break;
  598. case 'T': /* Tc or TLc or TRc */
  599. c = makeupper(curr_char);
  600. if(c == 'L' || c == 'R') {
  601. s[i++] = c;
  602. bi_advance();
  603. }
  604. goto get_w_d;
  605. /* Iw, Ew.c and similar forms */
  606. case 'A': case 'D': case 'E':
  607. case 'F': case 'G': case 'L':
  608. case 'I':
  609. get_w_d: /* Get the w field if any */
  610. while( isadigit(curr_char) ){
  611. if(i < MAXIDSIZE) /* Store it temporarily (up to a point) */
  612. s[i++] = curr_char;
  613. bi_advance();
  614. }
  615. /* Include any dot followed by number (e.g. F10.5)
  616. */
  617. if( curr_char == '.' ) {
  618. do {
  619. if(i < MAXIDSIZE)
  620. s[i++] = curr_char;
  621. bi_advance();
  622. } while( isadigit(curr_char) );
  623. }
  624. break;
  625. default:
  626. if(f77_standard) {
  627. nonstandard(token->line_num,token->col_num);
  628. msg_tail(": edit descriptor");
  629. s[i] = '\0';
  630. msg_tail(s);
  631. }
  632. goto get_w_d;
  633. }/*end switch*/
  634. token->class = tok_edit_descriptor;
  635. token->value.string = NULL;
  636. s[i++] = '\0';
  637. #ifdef DEBUG_FORLEX
  638. if(debug_lexer)
  639. fprintf(list_fd,"\nEdit descriptor:\t%s",s);
  640. #endif
  641. }/*end else if isaletter*/
  642. /* Apostrophe means a string */
  643. else if( curr_char == '\'' || curr_char == '"' ) {
  644. get_string(token);
  645. }
  646. /* Otherwise it is mere punctuation. Handle
  647. it here ourself to avoid complications. */
  648. else {
  649. get_simple_punctuation(token);
  650. }
  651. }
  652. #endif
  653. PRIVATE void
  654. get_hollerith(token,n) /* Gets string of form nHaaaa */
  655. Token *token;
  656. int n;
  657. {
  658. int i,last_col_num;
  659. /* Holl. consts are not stored unless the macro name LEX_STORE_HOLLERITHS
  660. is defined. */
  661. #ifdef LEX_STORE_HOLLERITHS
  662. int strsize=n;
  663. char *s;
  664. #else
  665. char *s = "Not stored";
  666. #endif
  667. initial_flag = FALSE;
  668. #ifdef LEX_STORE_HOLLERITHS
  669. if( (s=(char *)ckalloc((unsigned)(strsize+1))) == (char *)NULL ) {
  670. oops_message(OOPS_NONFATAL,line_num,col_num,
  671. "Out of string space for hollerith constant");
  672. strsize=0;
  673. }
  674. memset (s, 0, (strsize+1));
  675. #endif
  676. if(n==1)
  677. inside_hollerith=FALSE;/* turn off flag ahead of next_char */
  678. advance();/* Gobble the 'H' */
  679. last_col_num = col_num;
  680. for(i=0; i<n; i++) {
  681. while(curr_char == EOL) {
  682. /* Treat short line as if extended with blanks */
  683. int col;
  684. for(col=last_col_num; i<n && col<max_stmt_col; i++,col++) {
  685. #ifdef LEX_STORE_HOLLERITHS
  686. if(i < strsize)
  687. s[i] = ' ';
  688. #endif
  689. }
  690. last_col_num = col_num;
  691. advance();
  692. }
  693. if(i==n) break;
  694. if(curr_char == EOS || curr_char == EOF) {
  695. int col;
  696. for(col=last_col_num; i<n && col<max_stmt_col; i++,col++) {
  697. #ifdef LEX_STORE_HOLLERITHS
  698. if(i < strsize)
  699. s[i] = ' ';
  700. #endif
  701. }
  702. #ifdef LEX_STORE_HOLLERITHS
  703. strsize=i; /* in case it did not fill up */
  704. #endif
  705. break;
  706. }
  707. else {
  708. #ifdef LEX_STORE_HOLLERITHS
  709. s[i] = curr_char;
  710. #endif
  711. last_col_num = col_num;
  712. if(i==n-2)/* turn flag off ahead of next_char*/
  713. inside_hollerith = FALSE;
  714. advance();
  715. }
  716. }
  717. #ifdef LEX_STORE_HOLLERITHS
  718. if(strsize > 0)
  719. s[strsize] = '\0';
  720. #endif
  721. inside_hollerith = FALSE;
  722. token->class = tok_hollerith;
  723. token->value.string = s;
  724. token->size = n;
  725. #ifdef DEBUG_FORLEX
  726. if(debug_lexer)
  727. fprintf(list_fd,"\nHollerith:\t\t%s",s);
  728. #endif
  729. } /* get_hollerith */
  730. #include "keywords.h"
  731. /* get_identifier reads a string of characters satisfying
  732. isidletter. As they are read and as long as they are
  733. alphabetic, it looks for a match to a keyword, and
  734. whenever one is found, checks with is_keyword to see
  735. if the context is right. If so, it returns the keyword.
  736. Otherwise it keeps going and eventually returns the id.
  737. */
  738. PRIVATE void
  739. get_identifier(token)
  740. Token *token;
  741. {
  742. char s_upper[MAXIDSIZE+1]; /* string holding the identifier */
  743. char s_lower[MAXIDSIZE+1]; /* string holding the identifier */
  744. int c, /* Uppercase version of current letter */
  745. preceding_c,/* Char preceding latest id */
  746. has_embedded_space, /* Spaces inside keyword or id */
  747. space_seen_lately, /* Flag for catching embedded space */
  748. i, /* Index in s of current letter */
  749. lo,hi, /* Indices in keyword table where match may be */
  750. klen, /* Length of id read so far (after keyword test) */
  751. keywd_class;/* Class number returned by is_keyword */
  752. int possible_keyword;
  753. int i_white;
  754. token->class = tok_identifier;
  755. keywd_class = FALSE;
  756. i = klen = 0;
  757. lo = 0;
  758. hi = NUM_KEYWORDS-1;
  759. i_white = 0;
  760. /* Define shorthand for the keyword letter under study */
  761. #define KN(i) keywords[i].name
  762. #define KL(i) keywords[i].name[klen]
  763. possible_keyword = TRUE;
  764. preceding_c = prev_char;
  765. has_embedded_space = FALSE;
  766. space_seen_lately = FALSE;
  767. /* This loop gets letter [letter|digit]* forms */
  768. while(isidletter(curr_char) || isadigit(curr_char)) {
  769. c = makeupper(curr_char); /* Get the next char of id */
  770. if(i < MAXIDSIZE) /* Store it (up to a point) */
  771. {
  772. s_upper[i] = c;
  773. s_lower[i] = curr_char;
  774. i++;
  775. }
  776. if(space_seen_lately)
  777. {
  778. has_embedded_space = TRUE;
  779. }
  780. bi_advanceX(); /* Pull in the next character */
  781. space_seen_lately = iswhitespace(prev_char);
  782. /* As long as it may yet be a keyword,
  783. keep track of whether to invoke is_keyword.
  784. */
  785. if(possible_keyword) {
  786. if(!isaletter(c) /* If not alphabetic, cannot be keyword */
  787. || klen >= sizeof(keywords[0].name)-1) /* or overlength */
  788. {
  789. #ifdef DEBUG_IS_KEYWORD
  790. if(debug_lexer && getenv("BISECTION")) {
  791. s[i] = '\0';
  792. fprintf(list_fd,"\n%s not a keyword because",s);
  793. if(!isaletter(c))
  794. fprintf(list_fd," non-letter at %c",c);
  795. if(klen >= sizeof(keywords[0].name)-1)
  796. fprintf(list_fd,"length %d >= max %d",klen,sizeof(keywords[0].name)-1);
  797. }
  798. #endif
  799. possible_keyword = FALSE;
  800. }
  801. else {
  802. int mid;
  803. #ifdef DEBUG_IS_KEYWORD
  804. if(debug_lexer && getenv("BISECTION")) {
  805. fprintf(list_fd,"\nklen=%d c=%c",klen,c);
  806. fprintf(list_fd,"\nBisecting [lo,hi]=[%d,%d] \"%s\"..\"%s\"",
  807. lo,hi,KN(lo),KN(hi));
  808. }
  809. #endif
  810. /* Bisect lo .. hi looking for match
  811. on characters found so far. */
  812. while(lo <= hi) {
  813. mid = (lo + hi)/2;
  814. if( KL(mid) < c ) { /* No match in lower half */
  815. lo = mid+1;
  816. }
  817. else if( KL(mid) > c ) {/* No match in upper half */
  818. hi = mid-1;
  819. }
  820. else { /* Match at midpoint: Bisect each
  821. half to find the new subinterval. */
  822. int midlo=mid, midhi=mid;
  823. /* Bisect lo .. mid */
  824. while( lo < midlo-1 && KL(lo) != c) {
  825. mid = (lo + midlo)/2;
  826. if( KL(mid) < c ) {
  827. lo = mid+1;
  828. }
  829. else { /* equal */
  830. midlo = mid;
  831. }
  832. }
  833. if( KL(lo) != c )
  834. lo = midlo;
  835. /* Bisect mid .. hi */
  836. while( midhi < hi-1 && KL(hi) != c ) {
  837. mid = (midhi + hi)/2;
  838. if( KL(mid) > c ) {
  839. hi = mid-1;
  840. }
  841. else { /* equal */
  842. midhi = mid;
  843. }
  844. }
  845. if( KL(hi) != c )
  846. hi = midhi;
  847. break; /* After bisecting each half, we are done */
  848. } /* end else KL(mid) == c */
  849. } /* end while(lo <= hi) */
  850. klen++; /* Now increment the length */
  851. #ifdef DEBUG_IS_KEYWORD
  852. if(debug_lexer && getenv("BISECTION")) {
  853. fprintf(list_fd,"\nNew [lo,hi]=[%d,%d] \"%s\"..\"%s\"",
  854. lo,hi,KN(lo),KN(hi));
  855. }
  856. #endif
  857. /* If range is null, a match has been ruled out. */
  858. if(lo > hi) {
  859. #ifdef DEBUG_IS_KEYWORD
  860. if(debug_lexer && getenv("BISECTION")) {
  861. s[i]='\0';
  862. fprintf(list_fd,"\nKeyword ruled out for %s at length %d since lo %d > hi %d",
  863. s,klen,lo,hi);
  864. }
  865. #endif
  866. possible_keyword = FALSE;
  867. }
  868. /* If length of first keyword in range is equal
  869. to the new length, then we have a match at
  870. this point. Check it out with is_keyword.
  871. */
  872. else if(KN(lo)[klen] == '\0') {
  873. if( (keywd_class = is_keyword(lo)) != FALSE) {
  874. token->class = keywd_class; /* It's a keyword */
  875. token->value.string = NULL;
  876. s_upper[i] = 0;
  877. s_lower[i] = 0;
  878. i++;
  879. if( hig_fp )
  880. {
  881. if( strcmp( current_filename, top_filename ) == 0 )
  882. {
  883. fprintf( hig_fp, "%d key %d.%d %d.%d\n"
  884. , PAF_HIGH
  885. , token->line_num
  886. , token->curr_index
  887. , token->line_num
  888. , token->curr_index + i_white
  889. );
  890. }
  891. }
  892. break; /* Quit the input loop */
  893. }
  894. else if(lo == hi) { /* Match is unique and ruled out */
  895. possible_keyword = FALSE;
  896. }
  897. }
  898. }/* end else isaletter(c) */
  899. }/* end if(possible_keyword) */
  900. }/* end while(isidletter || isadigit) */
  901. if(keywd_class == FALSE) { /* it is an identifier */
  902. /* Identifier: find its hashtable entry or
  903. create a new entry. */
  904. int h;
  905. Lsymtab *symt;
  906. #ifdef TYPELESS_CONSTANTS
  907. /* Watch out for const like X'nnn' */
  908. if(i == 1 && curr_char == '\'') {
  909. get_binary_const(token,s_upper[0],NULL);
  910. return;
  911. }
  912. #endif
  913. s_upper[i] = '\0';
  914. s_lower[i] = '\0';
  915. i++;
  916. #ifdef CASE_SENSITIVE
  917. token->value.integer = h = hash_lookup(s_lower);
  918. #else
  919. token->value.integer = h = hash_lookup(s_upper);
  920. #endif
  921. /* If it is an array give it a special token
  922. class, so that arrays can be distinguished
  923. from functions in the grammar. */
  924. if((symt=hashtab[h].loc_symtab) != NULL
  925. && symt->array_var) {
  926. token->class = tok_array_identifier;
  927. }
  928. }
  929. /* Check identifiers for being juxtaposed
  930. to keywords or having internal space.
  931. Keywords are immune to warning since
  932. want to allow both GOTO and GO TO, etc.
  933. */
  934. if(pretty_flag &&
  935. (token->class==tok_identifier || token->class==tok_array_identifier)
  936. && ( isidletter(preceding_c) || isadigit(preceding_c)
  937. || has_embedded_space ) ) {
  938. ugly_code(token->line_num,token->col_num,"identifier");
  939. msg_tail(hashtab[token->value.integer].name);
  940. #if 0 /* Keywords immune for now */
  941. ugly_code(token->line_num,token->col_num,"keyword");
  942. msg_tail(keywords[keytab_index[keywd_class-keytab_offset]].name);
  943. #endif
  944. if(has_embedded_space)
  945. msg_tail("has embedded space");
  946. else
  947. msg_tail("not clearly separated from context");
  948. }
  949. #ifdef DEBUG_FORLEX
  950. if(debug_lexer){
  951. switch(token->class) {
  952. case tok_identifier:
  953. fprintf(list_fd,"\nIdentifier:\t\t%s",s);
  954. break;
  955. case tok_array_identifier:
  956. fprintf(list_fd,"\nArray_identifier:\t%s",s);
  957. break;
  958. default:
  959. fprintf(list_fd,"\nKeyword:\t\ttok_%s",s);
  960. break;
  961. }
  962. }
  963. #endif
  964. } /* get_identifier */
  965. /* iskeyword:
  966. Determines (to the best of its current ability) whether a given
  967. identifier is a keyword or not. Hopefully now no keywords are
  968. reserved.
  969. Method uses context from start of statement up to and including
  970. the character following the putative keyword to eliminate as
  971. many cases as possible. Any non-IK keywords (those that need not
  972. be in the initial series of keywords of statement) have special
  973. code to handle them. Any IK's that are always the second word of a
  974. pair are accepted if the predecessor was just seen. The rest are
  975. handed off to looking_at_keywd which tries to see if
  976. it is an assignment statement.
  977. Note that some rules that could be used if F77 Standard were
  978. adhered to strictly are not used here. The idea is to allow
  979. extensions, and leave catching syntax errors in the parser.
  980. For example, specification-statement keywords are not excluded
  981. after the first executable statement has been seen. The status
  982. of a variable as declared array or character type is not consulted
  983. in ruling out an assignment statement if following parentheses
  984. are present. Etc.
  985. */
  986. /* Macro to test if all the specified bits are set */
  987. #define MATCH(CONTEXT) ((keywords[i].context & (CONTEXT)) == (CONTEXT))
  988. LEX_SHARED int
  989. is_keyword(i)
  990. int i; /* Index in keywords table */
  991. {
  992. int ans = FALSE;
  993. int putative_keyword_class; /* Class of the supposed keyword */
  994. while(iswhitespace(curr_char)) /* Move to lookahead char */
  995. advance();
  996. #ifdef DEBUG_IS_KEYWORD
  997. if(debug_lexer){
  998. fprintf(list_fd,
  999. "\nkeyword %s: initialflag=%d implicitflag=%d ",
  1000. keywords[i].name,initial_flag,implicit_flag);
  1001. fprintf(list_fd,
  1002. "context=%o, next char=%c %o",keywords[i].context,
  1003. curr_char,curr_char);
  1004. }
  1005. #endif
  1006. putative_keyword_class = keywords[i].class;
  1007. if( !initial_flag && MATCH(IK) ) {
  1008. /* Dispose of keywords which can only occur in initial
  1009. part of statement, if found elsewhere. */
  1010. ans = FALSE;
  1011. }
  1012. #if 0 /* This does not work: curr_stmt_class not cleared beforehand */
  1013. else if(curr_stmt_class == tok_IF && MATCH(NI)) {
  1014. /* Dispose of keywords which cannot occur in stmt
  1015. field of logical IF if that is where we are.
  1016. */
  1017. ans = FALSE;
  1018. }
  1019. #endif
  1020. else if(MATCH(NA) && isalpha(curr_char)) {
  1021. /* Dispose of keywords which cannot be followed
  1022. by alphabetic character if that is so.
  1023. */
  1024. ans = FALSE;
  1025. }
  1026. else if(putative_keyword_class == tok_TO) {/* A non-IK case */
  1027. /* TO always follows the word GO or
  1028. is followed by a variable
  1029. name (in ASSIGN statement).
  1030. */
  1031. #ifdef SPLIT_KEYWORDS
  1032. #define in_assign_stmt (curr_stmt_class == tok_ASSIGN)
  1033. ans = (prev_token_class == (in_assign_stmt?
  1034. tok_integer_const:
  1035. tok_GO));
  1036. #else
  1037. ans = ( curr_stmt_class == tok_ASSIGN
  1038. && prev_token_class == tok_integer_const);
  1039. #endif
  1040. }
  1041. else if(putative_keyword_class == tok_FUNCTION /* A non-IK case */
  1042. && (stmt_sequence_no != 0 /* not the first statement of module */
  1043. || !(initial_flag /* if not initial can only be preceded by type */
  1044. || is_a_type_token(curr_stmt_class)) )) {
  1045. ans = FALSE; /* otherwise it will be handled correctly by looking_at */
  1046. }
  1047. else if(putative_keyword_class == tok_WHILE) { /* A non-IK case */
  1048. ans = WHILE_expected; /* Only occurs in DO label [,] WHILE */
  1049. WHILE_expected = FALSE;
  1050. }
  1051. /* Remaining cases are IK in initial part */
  1052. /* Eliminate those which can are never followed
  1053. by '(' or '=' if that is what we have.
  1054. */
  1055. else if(MATCH(NP) &&
  1056. (curr_char == '(' || curr_char == '=') ) {
  1057. ans = FALSE;
  1058. }
  1059. /* Likewise with those that must be followed by
  1060. '(' but aren't */
  1061. else if(MATCH(MP) && curr_char != '(') {
  1062. ans = FALSE;
  1063. }
  1064. /* PRECISION always follows the word DOUBLE */
  1065. else if( putative_keyword_class == tok_PRECISION ){
  1066. ans = (prev_token_class == tok_DOUBLE);
  1067. }
  1068. /* END DO: handle its DO here */
  1069. else if( putative_keyword_class == tok_DO && curr_char == EOS ) {
  1070. /* Also must have prev_token_class == tok_END, but
  1071. no need to check since end-of-statement suffices. */
  1072. ans = TRUE;
  1073. }
  1074. /* Other type names always follow the word
  1075. IMPLICIT */
  1076. else if( implicit_flag ) {
  1077. ans = MATCH(TY);
  1078. }
  1079. else {
  1080. /* Remaining cases are keywords that must be in
  1081. initial position. If followed by '=' must be an
  1082. identifier. If followed by '(' then may be an array
  1083. or character lvalue, so use looking_at to scan ahead
  1084. to see if this is an assignment statement. */
  1085. ans = looking_at_keywd(putative_keyword_class);
  1086. }
  1087. /* Save initial token class for use by parser.
  1088. Either set it to keyword token or to id for
  1089. assignment stmt. */
  1090. if(initial_flag) {
  1091. curr_stmt_class = (ans? keywords[i].class: tok_identifier);
  1092. }
  1093. /* Turn off the initial-keyword flag if this is a
  1094. keyword that cannot be followed by another keyword
  1095. or if it is not a keyword.
  1096. */
  1097. if(ans) {
  1098. if(keywords[i].context & EK)
  1099. initial_flag = FALSE;
  1100. return keywords[i].class;
  1101. }
  1102. else { /* If no more letters follow, then keyword here
  1103. is ruled out. Turn off initial_flag. */
  1104. if( ! isalpha(curr_char) )
  1105. initial_flag = FALSE;
  1106. return 0; /* Not found in list */
  1107. }
  1108. }/* End of is_keyword */
  1109. /* init_keyhashtab:
  1110. */
  1111. /* Hashing is no longer used. This guy now only
  1112. initializes the table of indices that allow
  1113. keywords to be looked up by their token class*/
  1114. void
  1115. init_keyhashtab()
  1116. {
  1117. int i,k,kmin,kmax;
  1118. kmin = kmax = keywords[0].class; /* Find min and max token classes */
  1119. for(i=1; i<NUM_KEYWORDS; i++) {
  1120. k = keywords[i].class;
  1121. if(k < kmin) kmin = k;
  1122. if(k > kmax) kmax = k;
  1123. }
  1124. keytab_offset = kmin; /* Index table from [kmin..kmax] -> [0..size-1] */
  1125. keytab_size = (unsigned) (kmax-kmin+1);
  1126. if( (keytab_index=(short *)ckalloc(keytab_size*sizeof(keytab_index[0])))
  1127. == (short *)NULL) {
  1128. oops_message(OOPS_FATAL,NO_LINE_NUM,NO_COL_NUM,
  1129. "cannot allocate space for keytab_index");
  1130. }
  1131. memset (keytab_index, 0, keytab_size*sizeof(keytab_index[0]));
  1132. /* Now fill in the lookup table, indexed
  1133. by class - offset */
  1134. for(i=0; i<NUM_KEYWORDS; i++) {
  1135. k = keywords[i].class;
  1136. keytab_index[k - keytab_offset] = i;
  1137. }
  1138. }
  1139. PRIVATE void
  1140. get_illegal_token(token) /* Handle an illegal input situation */
  1141. Token *token;
  1142. {
  1143. token->class = tok_illegal;
  1144. #ifdef DEBUG_FORLEX
  1145. if(debug_lexer)
  1146. fprintf(list_fd,"\nILLEGAL TOKEN");
  1147. #endif
  1148. } /* get_illegal_token */
  1149. /* Read a label from label field. */
  1150. PRIVATE void
  1151. get_label(token)
  1152. Token *token;
  1153. {
  1154. int value=0;
  1155. int space_seen=FALSE, has_embedded_space=FALSE;
  1156. while( isadigit(curr_char) && col_num < 6 ) {
  1157. if(space_seen)
  1158. has_embedded_space = TRUE;
  1159. value = value*10 + BCD(curr_char);
  1160. advance();
  1161. while(curr_char==' ' && col_num < 6) {
  1162. space_seen = TRUE;
  1163. advance();
  1164. }
  1165. }
  1166. if(pretty_flag && has_embedded_space) {
  1167. ugly_code(token->line_num,token->col_num,
  1168. "label has embedded space");
  1169. }
  1170. token->class = tok_label;
  1171. token->value.integer = value;
  1172. #ifdef DEBUG_FORLEX
  1173. if(debug_lexer)
  1174. fprintf(list_fd,"\nLabel:\t\t\t%d",value);
  1175. #endif
  1176. } /* get_label */
  1177. PRIVATE void
  1178. get_letter(token) /* Gets letter in IMPLICIT list */
  1179. Token *token;
  1180. {
  1181. token->class = tok_letter;
  1182. token->subclass = makeupper(curr_char);
  1183. #ifdef DEBUG_FORLEX
  1184. if(debug_lexer)
  1185. fprintf(list_fd,"\nLetter:\t\t\t%c",token->subclass);
  1186. #endif
  1187. advance();
  1188. } /* get_letter */
  1189. /* get_number reads a number and determines data type: integer,
  1190. * real, or double precision.
  1191. */
  1192. /* This belongs in ftnchek.h, perhaps. Defines number of significant
  1193. figures that are reasonable for a single-precision real constant.
  1194. Works out to 9 for wordsize=4, 21 for wordsize=8. These allow
  1195. for a couple of extra digits for rounding. Used in -trunc warning. */
  1196. #define REAL_SIGFIGS (local_wordsize==0? 8: (local_wordsize-1)*3)
  1197. PRIVATE void
  1198. get_number(token)
  1199. Token *token;
  1200. {
  1201. double dvalue,leftside,rightside,pwr_of_ten;
  1202. int exponent,expsign,datatype,c;
  1203. int sigfigs;
  1204. initial_flag = FALSE;
  1205. leftside = 0.0;
  1206. sigfigs = 0;
  1207. datatype = tok_integer_const;
  1208. while(isadigit(curr_char)) {
  1209. leftside = leftside*10.0 + (double)BCD(curr_char);
  1210. ++sigfigs;
  1211. if( !integer_context && makeupper(next_char) == 'H' )
  1212. inside_hollerith = TRUE;/* get ready for hollerith*/
  1213. bi_advance();
  1214. }
  1215. /* If context specifies integer expected, skip to end.
  1216. Otherwise scan on ahead for more. */
  1217. if( integer_context) {
  1218. if(sigfigs == 0) {
  1219. yyerror("integer expected");
  1220. advance(); /* gobble something to avoid infinite loop */
  1221. }
  1222. }
  1223. else {/* not integer_context */
  1224. if( makeupper(curr_char) == 'H' ){ /* nnH means hollerith */
  1225. if(leftside == 0.0) {
  1226. yyerror("Zero-length hollerith constant");
  1227. inside_hollerith = FALSE;
  1228. advance();
  1229. get_illegal_token(token);
  1230. }
  1231. else {
  1232. get_hollerith(token, (int)leftside);
  1233. }
  1234. return;
  1235. }
  1236. rightside = 0.0;
  1237. pwr_of_ten = 1.0;
  1238. closeup(); /* Pull in the lookahead character */
  1239. if( curr_char == '.' &&
  1240. /* don't be fooled by 1.eq.N or
  1241. I.eq.1.and. etc */
  1242. !looking_at_relop() ) {
  1243. datatype = tok_real_const;
  1244. bi_advance();
  1245. while(isadigit(curr_char)) {
  1246. rightside = rightside*10.0 + (double)BCD(curr_char);
  1247. ++sigfigs;
  1248. pwr_of_ten *= 0.10;
  1249. bi_advance();
  1250. }
  1251. }
  1252. #ifdef DEBUG_FORLEX
  1253. if(debug_lexer)
  1254. dvalue = leftside + rightside*pwr_of_ten;
  1255. #endif
  1256. exponent = 0;
  1257. expsign = 1;
  1258. /* Integer followed by E or D gives a real/d.p constant */
  1259. if( ( (c = makeupper(curr_char)) == 'E' || c == 'D' ) )
  1260. {
  1261. datatype = ((c == 'E')? tok_real_const: tok_dp_const);
  1262. bi_advance();
  1263. if(curr_char == '+') {
  1264. expsign = 1;
  1265. bi_advance();
  1266. }
  1267. else if(curr_char == '-') {
  1268. expsign = -1;
  1269. bi_advance();
  1270. }
  1271. if(!isadigit(curr_char)) {
  1272. yyerror("Badly formed real constant");
  1273. }
  1274. else while(isadigit(curr_char)) {
  1275. exponent = exponent*10 + (curr_char-'0');
  1276. bi_advance();
  1277. }
  1278. /* Compute real value only if debugging. If it exceeds max magnitude,
  1279. computing it may cause crash. At this time, value of real const
  1280. is not used for anything. */
  1281. #ifdef DEBUG_FORLEX
  1282. if(debug_lexer)
  1283. dvalue *= pow(10.0, (double)(exponent*expsign));
  1284. else
  1285. #endif
  1286. dvalue = 0.0;
  1287. }
  1288. }/* end if(!integer_context) */
  1289. token->class = datatype;
  1290. switch(datatype) {
  1291. case tok_integer_const:
  1292. token->value.integer = (long)leftside;
  1293. #ifdef DEBUG_FORLEX
  1294. if(debug_lexer)
  1295. fprintf(list_fd,"\nInteger const:\t\t%ld",token->value.integer);
  1296. #endif
  1297. break;
  1298. case tok_real_const:
  1299. /* store single as double lest it overflow */
  1300. token->value.dbl = dvalue;
  1301. if(trunc_check && sigfigs >= REAL_SIGFIGS) {
  1302. warning(token->line_num,token->col_num,
  1303. "Single-precision real constant has more digits than are stored");
  1304. }
  1305. #ifdef DEBUG_FORLEX
  1306. if(debug_lexer)
  1307. fprintf(list_fd,"\nReal const:\t\t%g",token->value.dbl);
  1308. #endif
  1309. break;
  1310. case tok_dp_const:
  1311. token->value.dbl = dvalue;
  1312. #ifdef DEBUG_FORLEX
  1313. if(debug_lexer)
  1314. fprintf(list_fd,"\nDouble const:\t\t%lg",token->value.dbl);
  1315. #endif
  1316. break;
  1317. }
  1318. } /* get_number */
  1319. /* get_complex_constant reads an entity of the form (num,num)
  1320. where num is any [signed] numeric constant. It will only be
  1321. called when looking_at() has guaranteed that there is one there.
  1322. The token receives the real part as a number. The imaginary part
  1323. is not stored. Whitespace is allowed between ( and num, around
  1324. the comma, and between num and ) but not within num. */
  1325. PRIVATE void
  1326. get_complex_const(token)
  1327. Token *token;
  1328. {
  1329. Token imag_part; /* temporary to hold imag part */
  1330. double sign=1.0;
  1331. int dble_size=FALSE; /* flag to set if parts are D floats */
  1332. int imag_dble_size=FALSE;/* if imaginary part D float */
  1333. unsigned comma_line_num,comma_col_num;
  1334. initial_flag = FALSE;
  1335. bi_advance(); /* skip over the initial paren */
  1336. if(curr_char == '+' || curr_char == '-') {
  1337. if(curr_char == '-') sign = -1.0;
  1338. bi_advance();
  1339. }
  1340. #ifdef DEBUG_FORLEX
  1341. if(debug_lexer){
  1342. fprintf(list_fd,"\nComplex const:(");
  1343. if(sign < 0.0) fprintf(list_fd," -");
  1344. }
  1345. #endif
  1346. get_number(token);
  1347. switch(token->class) {
  1348. case tok_integer_const:
  1349. token->value.dbl = sign*(double)token->value.integer;
  1350. break;
  1351. case tok_dp_const:
  1352. dble_size=TRUE;
  1353. /*fallthru*/
  1354. case tok_real_const:
  1355. token->value.dbl = sign*token->value.dbl;
  1356. break;
  1357. }
  1358. while(iswhitespace(curr_char))
  1359. advance();
  1360. comma_line_num = line_num;
  1361. comma_col_num = col_num;
  1362. bi_advance(); /* skip over the comma */
  1363. if(curr_char == '+' || curr_char == '-') {
  1364. if(curr_char == '-') sign = -1.0;
  1365. bi_advance();
  1366. }
  1367. #ifdef DEBUG_FORLEX
  1368. if(debug_lexer){
  1369. fprintf(list_fd,"\n,");
  1370. if(sign < 0.0) fprintf(list_fd," -");
  1371. }
  1372. #endif
  1373. get_number(&imag_part);
  1374. imag_dble_size = (imag_part.class == tok_dp_const);
  1375. if(dble_size != imag_dble_size) {
  1376. warning(comma_line_num,comma_col_num,
  1377. "different precision in real and imaginary parts");
  1378. }
  1379. else if(f77_standard) {
  1380. if(dble_size)
  1381. warning(token->line_num,token->col_num,
  1382. "nonstandard double precision complex constant");
  1383. }
  1384. dble_size = (dble_size || imag_dble_size);
  1385. while(iswhitespace(curr_char))
  1386. advance();
  1387. advance(); /* skip over final paren */
  1388. if(dble_size)
  1389. token->class = tok_dcomplex_const;
  1390. else
  1391. token->class = tok_complex_const;
  1392. #ifdef DEBUG_FORLEX
  1393. if(debug_lexer)
  1394. fprintf(list_fd,"\n)");
  1395. #endif
  1396. }
  1397. #ifdef TYPELESS_CONSTANTS
  1398. /* Routine to get constants of the forms:
  1399. B'nnnn' 'nnnn'B -- binary
  1400. O'nnnn' 'nnnn'O -- octal
  1401. X'nnnn' Z'nnnn' 'nnnn'X 'nnnn'Z -- hex
  1402. No check of whether digits are less than base.
  1403. Nonstandard warning is issued here since the constant
  1404. looks like a normal integer by the time the parser sees it.
  1405. */
  1406. PRIVATE void
  1407. get_binary_const(token,c,s)
  1408. Token *token;
  1409. int c; /* base character: madeupper'ed by caller */
  1410. char *s; /* string of digits, or NULL */
  1411. {
  1412. long value=0;
  1413. int base;
  1414. if(c == 'O') base = 8;
  1415. else if(c == 'X' || c == 'Z') base = 16;
  1416. else if(c == 'B') base = 2;
  1417. else {
  1418. syntax_error(token->line_num,token->col_num,
  1419. "Unknown base for typeless constant -- octal assumed");
  1420. base = 8;
  1421. }
  1422. /* Two forms: X'nnnn' and 'nnnn'X. For the first, string has not
  1423. been scanned yet, and s is null. For second, s=digit string. */
  1424. if(s == NULL) {
  1425. bi_advance(); /* gobble the leading quote */
  1426. while(ishex(curr_char)){
  1427. value = value*base + HEX(curr_char);
  1428. bi_advance();
  1429. }
  1430. if(curr_char != '\'') {
  1431. syntax_error(line_num,col_num, "Closing quote missing");
  1432. }
  1433. else
  1434. advance(); /* gobble the trailing quote */
  1435. }
  1436. else { /* Use the given string */
  1437. while(*s != '\0') {
  1438. if(!isspace(*s)) /* skip blanks */
  1439. value = value*base + HEX(*s);
  1440. s++;
  1441. }
  1442. }
  1443. token->class = tok_integer_const;
  1444. token->value.integer = value;
  1445. if(f77_standard) {
  1446. nonstandard(token->line_num,token->col_num);
  1447. }
  1448. #ifdef DEBUG_FORLEX
  1449. if(debug_lexer)
  1450. fprintf(list_fd,"\nInteger const:\t\t%d",token->value.integer);
  1451. #endif
  1452. }/*get_binary_const*/
  1453. #endif/*TYPELESS_CONSTANTS*/
  1454. PRIVATE void
  1455. get_punctuation(token)
  1456. Token *token;
  1457. {
  1458. initial_flag = FALSE;
  1459. closeup();
  1460. if(curr_char == '*' && next_char == '*') {
  1461. token->class = tok_power;
  1462. advance();
  1463. }
  1464. else if(curr_char == '/' && next_char == '/' ) {
  1465. token->class = tok_concat;
  1466. advance();
  1467. }
  1468. /* paren can be the start of complex constant if everything
  1469. is just right. Maybe more tests needed here. */
  1470. else if(complex_const_allowed && curr_char == '(' &&
  1471. ( (prev_token_class<256 && ispunct(prev_token_class))
  1472. || prev_token_class == tok_relop
  1473. || prev_token_class == tok_power )
  1474. && looking_at_cplx()) {
  1475. get_complex_const(token);
  1476. return;
  1477. }
  1478. else
  1479. token->class = curr_char;
  1480. advance();
  1481. #ifdef DEBUG_FORLEX
  1482. if(debug_lexer) {
  1483. if(token->class == EOS)
  1484. fprintf(list_fd,"\n\t\t\tEOS");
  1485. else if(token->class == tok_power)
  1486. fprintf(list_fd,"\nPunctuation:\t\t**");
  1487. else if(token->class == tok_concat)
  1488. fprintf(list_fd,"\nPunctuation:\t\t//");
  1489. else
  1490. fprintf(list_fd,"\nPunctuation:\t\t%c",token->class);
  1491. }
  1492. #endif
  1493. } /* get_punctuation */
  1494. PRIVATE void
  1495. get_simple_punctuation(token)
  1496. Token *token;
  1497. {
  1498. /* Like get_punctuation but lacks special cases. Just
  1499. gets the punctuation character. */
  1500. token->class = curr_char;
  1501. advance();
  1502. #ifdef DEBUG_FORLEX
  1503. if(debug_lexer) {
  1504. if(token->class == EOS)
  1505. fprintf(list_fd,"\n\t\t\tEOS");
  1506. else
  1507. fprintf(list_fd,"\nPunctuation:\t\t%c",token->class);
  1508. }
  1509. #endif
  1510. } /* get_simple_punctuation */
  1511. PRIVATE void
  1512. get_string(token) /* Gets string of form 'aaaa' */
  1513. Token *token;
  1514. {
  1515. int i,len,last_col_num;
  1516. int first_char = curr_char;
  1517. /* String consts are not stored unless the macro name LEX_STORE_STRINGS
  1518. is defined. */
  1519. #ifdef LEX_STORE_STRINGS
  1520. char *s;
  1521. char tmpstr[MAXSTR+1];
  1522. #else
  1523. char *s = "Not stored";
  1524. #endif
  1525. initial_flag = FALSE;
  1526. inside_string = TRUE;
  1527. last_col_num=col_num;
  1528. advance(); /* Gobble leading quote */
  1529. i = len = 0;
  1530. for(;;) {
  1531. while(curr_char == EOL) {
  1532. /* Treat short line as if extended with blanks */
  1533. int col;
  1534. for(col=last_col_num; col<max_stmt_col; col++) {
  1535. #ifdef LEX_STORE_STRINGS
  1536. if(i < MAXSTR)
  1537. tmpstr[i++] = ' ';
  1538. #endif
  1539. ++len;
  1540. }
  1541. last_col_num=col_num;
  1542. advance();
  1543. }
  1544. if(curr_char == EOS || curr_char == EOF) {
  1545. yyerror("Closing quote missing from string");
  1546. break;
  1547. }
  1548. if(curr_char == first_char) {
  1549. inside_string = FALSE;/* assume so for now */
  1550. /* Handle possible continuation */
  1551. if(next_char == EOL && col_num == max_stmt_col)
  1552. advance();
  1553. last_col_num=col_num;
  1554. advance();
  1555. if(curr_char == first_char) { /* '' becomes ' in string */
  1556. inside_string = TRUE; /* not a closing quote */
  1557. #ifdef LEX_STORE_STRINGS
  1558. if(i < MAXSTR)
  1559. tmpstr[i++] = curr_char;
  1560. #endif
  1561. ++len;
  1562. last_col_num=col_num;
  1563. advance();
  1564. }
  1565. else {
  1566. break; /* It was a closing quote after all */
  1567. }
  1568. }
  1569. else {
  1570. #ifdef LEX_STORE_STRINGS
  1571. if(i < MAXSTR)
  1572. tmpstr[i++] = curr_char;
  1573. #endif
  1574. ++len;
  1575. last_col_num=col_num;
  1576. advance();
  1577. }
  1578. }
  1579. #ifdef LEX_STORE_STRINGS
  1580. tmpstr[i++] = '\0';
  1581. #ifdef TYPELESS_CONSTANTS
  1582. /* Watch for const like 'nnn'X */
  1583. if(!inside_format) {
  1584. while(iswhitespace(curr_char))
  1585. advance();
  1586. if(isaletter(curr_char)) {
  1587. int c=makeupper(curr_char);
  1588. advance(); /* Gobble the base character */
  1589. get_binary_const(token,c,tmpstr);
  1590. return;
  1591. }
  1592. }
  1593. #endif
  1594. if( (s=(char *)ckalloc(i)) == (char *)NULL ) {
  1595. oops_message(OOPS_NONFATAL,line_num,col_num,
  1596. "Out of string space for character constant");
  1597. }
  1598. else {
  1599. memset (s, 0, i);
  1600. (void) strcpy(s,tmpstr);
  1601. }
  1602. #endif
  1603. if(len == 0) {
  1604. warning(line_num,col_num,
  1605. "Zero-length string not allowed\n");
  1606. len = 1;
  1607. }
  1608. inside_string = FALSE;
  1609. token->class = tok_string;
  1610. token->value.string = s;
  1611. token->size = len;
  1612. /* Under -port warn if char size > 255 */
  1613. if(port_check) {
  1614. if(len > 255)
  1615. nonportable(line_num,col_num,
  1616. "character constant length exceeds 255");
  1617. }
  1618. #ifdef DEBUG_FORLEX
  1619. if(debug_lexer)
  1620. fprintf(list_fd,"\nString:\t\t\t%s",s);
  1621. #endif
  1622. } /* get_string */
  1623. /* End of Forlex module */
  1624. /*
  1625. II. Advance
  1626. */
  1627. /* advance.c:
  1628. Low-level input routines for Fortran program checker.
  1629. Shared functions defined:
  1630. init_scan() Initializes an input stream.
  1631. finish_scan() Finishes processing an input stream.
  1632. advance() Reads next char, removing comments and
  1633. handling continuation lines.
  1634. looking_at_x Handles lookahead up to end of line:
  1635. looking_at_cplx() Identifies complex constant.
  1636. looking_at_keywd() Identifies assgnmt stmts vs keywords.
  1637. looking_at_relop() Distinguishes .EQ. from .Eexp .
  1638. flush_line_out(n) Prints lines up to line n if not already
  1639. printed, so error messages come out looking OK.
  1640. */
  1641. /* Define tab stops: nxttab[col_num] is column of next tab stop */
  1642. #define do8(X) X,X,X,X,X,X,X,X
  1643. PRIVATE int nxttab[]={ 0, do8(9), do8(17), do8(25), do8(33),
  1644. do8(41), do8(49), do8(57), do8(65), do8(73), do8(81)};
  1645. PRIVATE int
  1646. prev_comment_line, /* True if previous line was comment */
  1647. curr_comment_line, /* True if current line is comment */
  1648. noncomment_line_count, /* Number of noncomment lines read so far */
  1649. line_is_printed, /* True if line has been flushed (printed) */
  1650. prev_line_is_printed, /* True if line has been flushed (printed) */
  1651. sticky_EOF; /* Signal to delay EOF a bit for sake
  1652. of error messages in include files. */
  1653. PRIVATE unsigned
  1654. prev_line_num; /* line number of previous input line */
  1655. unsigned prev_stmt_line_num; /* line number of previous noncomment */
  1656. PRIVATE char
  1657. lineA[MAXLINE+1],lineB[MAXLINE+1], /* Buffers holding input lines */
  1658. *prev_line,*line; /* Pointers to input buffers */
  1659. PRIVATE char
  1660. *getstrn();
  1661. #ifdef UNIX_CPP
  1662. PRIVATE int
  1663. take_cpp_line(); /* Reads #line directives and ignores others */
  1664. #endif
  1665. /* Lookahead routines that scan the input
  1666. line for various things. The is_whatever routines take a
  1667. string as argument and return TRUE if it satisfies the
  1668. criterion. The skip_whatever routines take an index and
  1669. string as argument and return the index of the next
  1670. nonspace character in the string after the expected thing,
  1671. which must be there in a syntactically correct program.
  1672. The given index points at the character after a known
  1673. lead-in (except for see_a_number, which can be given the
  1674. index of 1st char of number). The see_whatever routines
  1675. are similar but return -1 if the expected thing is not
  1676. seen, which it need not be. */
  1677. PRIVATE int
  1678. is_comment(), is_continuation();
  1679. #if 0
  1680. PRIVATE int, is_overlength();
  1681. #endif
  1682. PRIVATE int
  1683. see_a_number(), see_dowhile(), see_expression(), see_keyword();
  1684. PRIVATE int
  1685. skip_balanced_parens(), skip_idletters(), skip_quoted_string(),
  1686. skip_hollerith();
  1687. #ifdef ALLOW_INCLUDE
  1688. /* Definition of structure for saving the input stream parameters while
  1689. processing an include file.
  1690. */
  1691. typedef struct {
  1692. FILE *yyin;
  1693. char *fname;
  1694. char line[MAXLINE]; /* MAXLINE is defined in ftnchek.h */
  1695. int curr_char;
  1696. int curr_index;
  1697. int next_char;
  1698. int