1 /* Implementation of Fortran lexer
2 Copyright (C) 1995-1998 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
29 #if FFECOM_targetCURRENT == FFECOM_targetGCC
34 #include "output.j" /* Must follow tree.j so TREE_CODE is defined! */
37 #ifdef DWARF_DEBUGGING_INFO
38 void dwarfout_resume_previous_source_file (register unsigned);
39 void dwarfout_start_new_source_file (register char *);
40 void dwarfout_define (register unsigned, register char *);
41 void dwarfout_undef (register unsigned, register char *);
42 #endif DWARF_DEBUGGING_INFO
44 static void ffelex_append_to_token_ (char c
);
45 static int ffelex_backslash_ (int c
, ffewhereColumnNumber col
);
46 static void ffelex_bad_1_ (ffebad errnum
, ffewhereLineNumber ln0
,
47 ffewhereColumnNumber cn0
);
48 static void ffelex_bad_2_ (ffebad errnum
, ffewhereLineNumber ln0
,
49 ffewhereColumnNumber cn0
, ffewhereLineNumber ln1
,
50 ffewhereColumnNumber cn1
);
51 static void ffelex_bad_here_ (int num
, ffewhereLineNumber ln0
,
52 ffewhereColumnNumber cn0
);
53 static void ffelex_finish_statement_ (void);
54 #if FFECOM_targetCURRENT == FFECOM_targetGCC
55 static int ffelex_get_directive_line_ (char **text
, FILE *finput
);
56 static int ffelex_hash_ (FILE *f
);
58 static ffewhereColumnNumber
ffelex_image_char_ (int c
,
59 ffewhereColumnNumber col
);
60 static void ffelex_include_ (void);
61 static bool ffelex_is_free_char_ctx_contin_ (ffewhereColumnNumber col
);
62 static bool ffelex_is_free_nonc_ctx_contin_ (ffewhereColumnNumber col
);
63 static void ffelex_next_line_ (void);
64 static void ffelex_prepare_eos_ (void);
65 static void ffelex_send_token_ (void);
66 static ffelexHandler
ffelex_swallow_tokens_ (ffelexToken t
);
67 static ffelexToken
ffelex_token_new_ (void);
69 /* Pertaining to the geometry of the input file. */
71 /* Initial size for card image to be allocated. */
72 #define FFELEX_columnINITIAL_SIZE_ 255
74 /* The card image itself, which grows as source lines get longer. It
75 has room for ffelex_card_size_ + 8 characters, and the length of the
76 current image is ffelex_card_length_. (The + 8 characters are made
77 available for easy handling of tabs and such.) */
78 static char *ffelex_card_image_
;
79 static ffewhereColumnNumber ffelex_card_size_
;
80 static ffewhereColumnNumber ffelex_card_length_
;
82 /* Max width for free-form lines (ISO F90). */
83 #define FFELEX_FREE_MAX_COLUMNS_ 132
85 /* True if we saw a tab on the current line, as this (currently) means
86 the line is therefore treated as though final_nontab_column_ were
88 static bool ffelex_saw_tab_
;
90 /* TRUE if current line is known to be erroneous, so don't bother
91 expanding room for it just to display it. */
92 static bool ffelex_bad_line_
= FALSE
;
94 /* Last column for vanilla, i.e. non-tabbed, line. Usually 72 or 132. */
95 static ffewhereColumnNumber ffelex_final_nontab_column_
;
97 /* Array for quickly deciding what kind of line the current card has,
98 based on its first character. */
99 static ffelexType ffelex_first_char_
[256];
101 /* Pertaining to file management. */
103 /* The wf argument of the most recent active ffelex_file_(fixed,free)
105 static ffewhereFile ffelex_current_wf_
;
107 /* TRUE if an INCLUDE statement can be processed (ffelex_set_include
109 static bool ffelex_permit_include_
;
111 /* TRUE if an INCLUDE statement is pending (ffelex_set_include has been
113 static bool ffelex_set_include_
;
115 /* Information on the pending INCLUDE file. */
116 static FILE *ffelex_include_file_
;
117 static bool ffelex_include_free_form_
;
118 static ffewhereFile ffelex_include_wherefile_
;
120 /* Current master line count. */
121 static ffewhereLineNumber ffelex_linecount_current_
;
122 /* Next master line count. */
123 static ffewhereLineNumber ffelex_linecount_next_
;
125 /* ffewhere info on the latest (currently active) line read from the
126 active source file. */
127 static ffewhereLine ffelex_current_wl_
;
128 static ffewhereColumn ffelex_current_wc_
;
130 /* Pertaining to tokens in general. */
132 /* Initial capacity for text in a CHARACTER/HOLLERITH/NAME/NAMES/NUMBER
134 #define FFELEX_columnTOKEN_SIZE_ 63
135 #if FFELEX_columnTOKEN_SIZE_ < FFEWHERE_indexMAX
136 #error "token size too small!"
139 /* Current token being lexed. */
140 static ffelexToken ffelex_token_
;
142 /* Handler for current token. */
143 static ffelexHandler ffelex_handler_
;
145 /* TRUE if fixed-form lexer is to generate NAMES instead of NAME tokens. */
146 static bool ffelex_names_
;
148 /* TRUE if both lexers are to generate NAMES instead of NAME tokens. */
149 static bool ffelex_names_pure_
;
151 /* TRUE if 0-9 starts a NAME token instead of NUMBER, for parsing hex
153 static bool ffelex_hexnum_
;
155 /* For ffelex_swallow_tokens(). */
156 static ffelexHandler ffelex_eos_handler_
;
158 /* Number of tokens sent since last EOS or beginning of input file
159 (include INCLUDEd files). */
160 static unsigned long int ffelex_number_of_tokens_
;
162 /* Number of labels sent (as NUMBER tokens) since last reset of
163 ffelex_number_of_tokens_ to 0, should be 0 or 1 in most cases.
164 (Fixed-form source only.) */
165 static unsigned long int ffelex_label_tokens_
;
167 /* Metering for token management, to catch token-memory leaks. */
168 static long int ffelex_total_tokens_
= 0;
169 static long int ffelex_old_total_tokens_
= 1;
170 static long int ffelex_token_nextid_
= 0;
172 /* Pertaining to lexing CHARACTER and HOLLERITH tokens. */
174 /* >0 if a Hollerith constant of that length might be in mid-lex, used
175 when the next character seen is 'H' or 'h' to enter HOLLERITH lexing
176 mode (see ffelex_raw_mode_). */
177 static long int ffelex_expecting_hollerith_
;
179 /* -3: Backslash (escape) sequence being lexed in CHARACTER.
180 -2: Possible closing apostrophe/quote seen in CHARACTER.
181 -1: Lexing CHARACTER.
182 0: Not lexing CHARACTER or HOLLERITH.
183 >0: Lexing HOLLERITH, value is # chars remaining to expect. */
184 static long int ffelex_raw_mode_
;
186 /* When lexing CHARACTER, open quote/apostrophe (either ' or "). */
187 static char ffelex_raw_char_
;
189 /* TRUE when backslash processing had to use most recent character
190 to finish its state engine, but that character is not part of
191 the backslash sequence, so must be reconsidered as a "normal"
192 character in CHARACTER/HOLLERITH lexing. */
193 static bool ffelex_backslash_reconsider_
= FALSE
;
195 /* Characters preread before lexing happened (might include EOF). */
196 static int *ffelex_kludge_chars_
= NULL
;
198 /* Doing the kludge processing, so not initialized yet. */
199 static bool ffelex_kludge_flag_
= FALSE
;
201 /* The beginning of a (possible) CHARACTER/HOLLERITH token. */
202 static ffewhereLine ffelex_raw_where_line_
;
203 static ffewhereColumn ffelex_raw_where_col_
;
206 /* Call this to append another character to the current token. If it isn't
207 currently big enough for it, it will be enlarged. The current token
208 must be a CHARACTER, HOLLERITH, NAME, NAMES, or NUMBER. */
211 ffelex_append_to_token_ (char c
)
213 if (ffelex_token_
->text
== NULL
)
216 = malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
217 FFELEX_columnTOKEN_SIZE_
+ 1);
218 ffelex_token_
->size
= FFELEX_columnTOKEN_SIZE_
;
219 ffelex_token_
->length
= 0;
221 else if (ffelex_token_
->length
>= ffelex_token_
->size
)
224 = malloc_resize_ksr (malloc_pool_image (),
226 (ffelex_token_
->size
<< 1) + 1,
227 ffelex_token_
->size
+ 1);
228 ffelex_token_
->size
<<= 1;
229 assert (ffelex_token_
->length
< ffelex_token_
->size
);
232 Sorry
, MAP_CHARACTER is
not going to work as expected in GNU Fortran
,
233 please contact fortran@gnu
.org
if you wish to fund work to
234 port g77 to non
-ASCII machines
.
236 ffelex_token_
->text
[ffelex_token_
->length
++] = c
;
239 /* Do backslash (escape) processing for a CHARACTER/HOLLERITH token
243 ffelex_backslash_ (int c
, ffewhereColumnNumber col
)
245 static int state
= 0;
246 static unsigned int count
;
248 static unsigned int firstdig
= 0;
250 static ffewhereLineNumber line
;
251 static ffewhereColumnNumber column
;
253 /* See gcc/c-lex.c readescape() for a straightforward version
254 of this state engine for handling backslashes in character/
255 hollerith constants. */
258 #define warn_traditional 0
259 #define flag_traditional 0
265 && (ffelex_raw_mode_
!= 0)
266 && ffe_is_backslash ())
270 line
= ffelex_linecount_current_
;
276 state
= 0; /* Assume simple case. */
280 if (warn_traditional
)
282 ffebad_start_msg_lex ("The meaning of `\\x' (at %0) varies with -traditional",
283 FFEBAD_severityWARNING
);
284 ffelex_bad_here_ (0, line
, column
);
288 if (flag_traditional
)
297 case '0': case '1': case '2': case '3': case '4':
298 case '5': case '6': case '7':
304 case '\\': case '\'': case '"':
307 #if 0 /* Inappropriate for Fortran. */
309 ffelex_next_line_ ();
315 return TARGET_NEWLINE
;
330 if (warn_traditional
)
332 ffebad_start_msg_lex ("The meaning of `\\a' (at %0) varies with -traditional",
333 FFEBAD_severityWARNING
);
334 ffelex_bad_here_ (0, line
, column
);
338 if (flag_traditional
)
343 #if 0 /* Vertical tab is present in common usage compilers. */
344 if (flag_traditional
)
361 ffebad_start_msg_lex ("Non-ANSI-C-standard escape sequence `\\%A' at %0",
362 FFEBAD_severityPEDANTIC
);
363 ffelex_bad_here_ (0, line
, column
);
367 return (c
== 'E' || c
== 'e') ? 033 : c
;
373 if (c
>= 040 && c
< 0177)
379 ffebad_start_msg_lex ("Unknown escape sequence `\\%A' at %0",
380 FFEBAD_severityPEDANTIC
);
381 ffelex_bad_here_ (0, line
, column
);
387 ffebad_start_msg_lex ("Unterminated escape sequence `\\' at %0",
388 FFEBAD_severityPEDANTIC
);
389 ffelex_bad_here_ (0, line
, column
);
396 sprintf (&m
[0], "%x", c
);
397 ffebad_start_msg_lex ("Unknown escape sequence `\\' followed by char code 0x%A at %0",
398 FFEBAD_severityPEDANTIC
);
399 ffelex_bad_here_ (0, line
, column
);
407 if ((c
>= 'a' && c
<= 'f')
408 || (c
>= 'A' && c
<= 'F')
409 || (c
>= '0' && c
<= '9'))
412 if (c
>= 'a' && c
<= 'f')
413 code
+= c
- 'a' + 10;
414 if (c
>= 'A' && c
<= 'F')
415 code
+= c
- 'A' + 10;
416 if (c
>= '0' && c
<= '9')
418 if (code
!= 0 || count
!= 0)
432 ffebad_start_msg_lex ("\\x used at %0 with no following hex digits",
433 FFEBAD_severityFATAL
);
434 ffelex_bad_here_ (0, line
, column
);
438 /* Digits are all 0's. Ok. */
440 else if ((count
- 1) * 4 >= TYPE_PRECISION (integer_type_node
)
442 && ((1 << (TYPE_PRECISION (integer_type_node
) - (count
- 1) * 4))
445 ffebad_start_msg_lex ("Hex escape at %0 out of range",
446 FFEBAD_severityPEDANTIC
);
447 ffelex_bad_here_ (0, line
, column
);
453 if ((c
<= '7') && (c
>= '0') && (count
++ < 3))
455 code
= (code
* 8) + (c
- '0');
462 assert ("bad backslash state" == NULL
);
466 /* Come here when code has a built character, and c is the next
467 character that might (or might not) be the next one in the constant. */
469 /* Don't bother doing this check for each character going into
470 CHARACTER or HOLLERITH constants, just the escaped-value ones.
471 gcc apparently checks every single character, which seems
472 like it'd be kinda slow and not worth doing anyway. */
475 && TYPE_PRECISION (char_type_node
) < HOST_BITS_PER_INT
476 && code
>= (1 << TYPE_PRECISION (char_type_node
)))
478 ffebad_start_msg_lex ("Escape sequence at %0 out of range for character",
479 FFEBAD_severityFATAL
);
480 ffelex_bad_here_ (0, line
, column
);
486 /* Known end of constant, just append this character. */
487 ffelex_append_to_token_ (code
);
488 if (ffelex_raw_mode_
> 0)
493 /* Have two characters to handle. Do the first, then leave it to the
494 caller to detect anything special about the second. */
496 ffelex_append_to_token_ (code
);
497 if (ffelex_raw_mode_
> 0)
499 ffelex_backslash_reconsider_
= TRUE
;
503 /* ffelex_bad_1_ -- Issue diagnostic with one source point
505 ffelex_bad_1_(FFEBAD_SOME_ERROR,ffelex_linecount_current_,column + 1);
507 Creates ffewhere line and column objects for the source point, sends them
508 along with the error code to ffebad, then kills the line and column
509 objects before returning. */
512 ffelex_bad_1_ (ffebad errnum
, ffewhereLineNumber ln0
, ffewhereColumnNumber cn0
)
517 wl0
= ffewhere_line_new (ln0
);
518 wc0
= ffewhere_column_new (cn0
);
519 ffebad_start_lex (errnum
);
520 ffebad_here (0, wl0
, wc0
);
522 ffewhere_line_kill (wl0
);
523 ffewhere_column_kill (wc0
);
526 /* ffelex_bad_2_ -- Issue diagnostic with two source points
528 ffelex_bad_2_(FFEBAD_SOME_ERROR,ffelex_linecount_current_,column + 1,
529 otherline,othercolumn);
531 Creates ffewhere line and column objects for the source points, sends them
532 along with the error code to ffebad, then kills the line and column
533 objects before returning. */
536 ffelex_bad_2_ (ffebad errnum
, ffewhereLineNumber ln0
, ffewhereColumnNumber cn0
,
537 ffewhereLineNumber ln1
, ffewhereColumnNumber cn1
)
539 ffewhereLine wl0
, wl1
;
540 ffewhereColumn wc0
, wc1
;
542 wl0
= ffewhere_line_new (ln0
);
543 wc0
= ffewhere_column_new (cn0
);
544 wl1
= ffewhere_line_new (ln1
);
545 wc1
= ffewhere_column_new (cn1
);
546 ffebad_start_lex (errnum
);
547 ffebad_here (0, wl0
, wc0
);
548 ffebad_here (1, wl1
, wc1
);
550 ffewhere_line_kill (wl0
);
551 ffewhere_column_kill (wc0
);
552 ffewhere_line_kill (wl1
);
553 ffewhere_column_kill (wc1
);
557 ffelex_bad_here_ (int n
, ffewhereLineNumber ln0
,
558 ffewhereColumnNumber cn0
)
563 wl0
= ffewhere_line_new (ln0
);
564 wc0
= ffewhere_column_new (cn0
);
565 ffebad_here (n
, wl0
, wc0
);
566 ffewhere_line_kill (wl0
);
567 ffewhere_column_kill (wc0
);
570 #if FFECOM_targetCURRENT == FFECOM_targetGCC
572 ffelex_getc_ (FILE *finput
)
576 if (ffelex_kludge_chars_
== NULL
)
577 return getc (finput
);
579 c
= *ffelex_kludge_chars_
++;
583 ffelex_kludge_chars_
= NULL
;
584 return getc (finput
);
588 #if FFECOM_targetCURRENT == FFECOM_targetGCC
590 ffelex_cfebackslash_ (int *use_d
, int *d
, FILE *finput
)
592 register int c
= getc (finput
);
594 register unsigned count
;
595 unsigned firstdig
= 0;
603 if (warn_traditional
)
604 warning ("the meaning of `\\x' varies with -traditional");
606 if (flag_traditional
)
615 if (!(c
>= 'a' && c
<= 'f')
616 && !(c
>= 'A' && c
<= 'F')
617 && !(c
>= '0' && c
<= '9'))
624 if (c
>= 'a' && c
<= 'f')
625 code
+= c
- 'a' + 10;
626 if (c
>= 'A' && c
<= 'F')
627 code
+= c
- 'A' + 10;
628 if (c
>= '0' && c
<= '9')
630 if (code
!= 0 || count
!= 0)
639 error ("\\x used with no following hex digits");
641 /* Digits are all 0's. Ok. */
643 else if ((count
- 1) * 4 >= TYPE_PRECISION (integer_type_node
)
646 << (TYPE_PRECISION (integer_type_node
) - (count
- 1)
649 pedwarn ("hex escape out of range");
652 case '0': case '1': case '2': case '3': case '4':
653 case '5': case '6': case '7':
656 while ((c
<= '7') && (c
>= '0') && (count
++ < 3))
658 code
= (code
* 8) + (c
- '0');
665 case '\\': case '\'': case '"':
669 ffelex_next_line_ ();
679 return TARGET_NEWLINE
;
694 if (warn_traditional
)
695 warning ("the meaning of `\\a' varies with -traditional");
697 if (flag_traditional
)
702 #if 0 /* Vertical tab is present in common usage compilers. */
703 if (flag_traditional
)
711 pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c
);
717 /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
721 /* `\%' is used to prevent SCCS from getting confused. */
724 pedwarn ("non-ANSI escape sequence `\\%c'", c
);
727 if (c
>= 040 && c
< 0177)
728 pedwarn ("unknown escape sequence `\\%c'", c
);
730 pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c
);
735 /* A miniature version of the C front-end lexer. */
737 #if FFECOM_targetCURRENT == FFECOM_targetGCC
739 ffelex_cfelex_ (ffelexToken
*xtoken
, FILE *finput
, int c
)
746 register unsigned buffer_length
;
748 if ((*xtoken
!= NULL
) && !ffelex_kludge_flag_
)
749 ffelex_token_kill (*xtoken
);
753 case '0': case '1': case '2': case '3': case '4':
754 case '5': case '6': case '7': case '8': case '9':
755 buffer_length
= ARRAY_SIZE (buff
);
758 r
= &buff
[buffer_length
];
764 register unsigned bytes_used
= (p
- q
);
767 q
= (char *)xrealloc (q
, buffer_length
);
769 r
= &q
[buffer_length
];
771 c
= ffelex_getc_ (finput
);
776 token
= ffelex_token_new_number (q
, ffewhere_line_unknown (),
777 ffewhere_column_unknown ());
785 buffer_length
= ARRAY_SIZE (buff
);
788 r
= &buff
[buffer_length
];
789 c
= ffelex_getc_ (finput
);
803 case '\\': /* ~~~~~ */
804 c
= ffelex_cfebackslash_ (&use_d
, &d
, finput
);
809 fatal ("Badly formed directive -- no closing quote");
819 if (use_d
!= 2) /* 0=>c, 1=>cd, 2=>nil. */
824 register unsigned bytes_used
= (p
- q
);
826 buffer_length
= bytes_used
* 2;
827 q
= (char *)xrealloc (q
, buffer_length
);
829 r
= &q
[buffer_length
];
838 token
= ffelex_token_new_character (q
, ffewhere_line_unknown (),
839 ffewhere_column_unknown ());
856 #if FFECOM_targetCURRENT == FFECOM_targetGCC
858 ffelex_file_pop_ (char *input_filename
)
860 if (input_file_stack
->next
)
862 struct file_stack
*p
= input_file_stack
;
863 input_file_stack
= p
->next
;
865 input_file_stack_tick
++;
866 #ifdef DWARF_DEBUGGING_INFO
867 if (debug_info_level
== DINFO_LEVEL_VERBOSE
868 && write_symbols
== DWARF_DEBUG
)
869 dwarfout_resume_previous_source_file (input_file_stack
->line
);
870 #endif /* DWARF_DEBUGGING_INFO */
873 error ("#-lines for entering and leaving files don't match");
875 /* Now that we've pushed or popped the input stack,
876 update the name in the top element. */
877 if (input_file_stack
)
878 input_file_stack
->name
= input_filename
;
882 #if FFECOM_targetCURRENT == FFECOM_targetGCC
884 ffelex_file_push_ (int old_lineno
, char *input_filename
)
887 = (struct file_stack
*) xmalloc (sizeof (struct file_stack
));
889 input_file_stack
->line
= old_lineno
;
890 p
->next
= input_file_stack
;
891 p
->name
= input_filename
;
892 input_file_stack
= p
;
893 input_file_stack_tick
++;
894 #ifdef DWARF_DEBUGGING_INFO
895 if (debug_info_level
== DINFO_LEVEL_VERBOSE
896 && write_symbols
== DWARF_DEBUG
)
897 dwarfout_start_new_source_file (input_filename
);
898 #endif /* DWARF_DEBUGGING_INFO */
900 /* Now that we've pushed or popped the input stack,
901 update the name in the top element. */
902 if (input_file_stack
)
903 input_file_stack
->name
= input_filename
;
907 /* Prepare to finish a statement-in-progress by sending the current
908 token, if any, then setting up EOS as the current token with the
909 appropriate current pointer. The caller can then move the current
910 pointer before actually sending EOS, if desired, as it is in
911 typical fixed-form cases. */
914 ffelex_prepare_eos_ ()
916 if (ffelex_token_
->type
!= FFELEX_typeNONE
)
918 ffelex_backslash_ (EOF
, 0);
920 switch (ffelex_raw_mode_
)
926 ffebad_start_lex ((ffelex_raw_char_
== '\'') ? FFEBAD_NO_CLOSING_APOSTROPHE
927 : FFEBAD_NO_CLOSING_QUOTE
);
928 ffebad_here (0, ffelex_token_
->where_line
, ffelex_token_
->where_col
);
929 ffebad_here (1, ffelex_current_wl_
, ffelex_current_wc_
);
940 ffebad_start_lex (FFEBAD_NOT_ENOUGH_HOLLERITH_CHARS
);
941 ffebad_here (0, ffelex_token_
->where_line
, ffelex_token_
->where_col
);
942 ffebad_here (1, ffelex_current_wl_
, ffelex_current_wc_
);
943 sprintf (num
, "%lu", (unsigned long) ffelex_raw_mode_
);
946 /* Make sure the token has some text, might as well fill up with spaces. */
949 ffelex_append_to_token_ (' ');
950 } while (--ffelex_raw_mode_
> 0);
954 ffelex_raw_mode_
= 0;
955 ffelex_send_token_ ();
957 ffelex_token_
->type
= FFELEX_typeEOS
;
958 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
959 ffelex_token_
->where_col
= ffewhere_column_use (ffelex_current_wc_
);
963 ffelex_finish_statement_ ()
965 if ((ffelex_number_of_tokens_
== 0)
966 && (ffelex_token_
->type
== FFELEX_typeNONE
))
967 return; /* Don't have a statement pending. */
969 if (ffelex_token_
->type
!= FFELEX_typeEOS
)
970 ffelex_prepare_eos_ ();
972 ffelex_permit_include_
= TRUE
;
973 ffelex_send_token_ ();
974 ffelex_permit_include_
= FALSE
;
975 ffelex_number_of_tokens_
= 0;
976 ffelex_label_tokens_
= 0;
977 ffelex_names_
= TRUE
;
978 ffelex_names_pure_
= FALSE
; /* Probably not necessary. */
979 ffelex_hexnum_
= FALSE
;
981 if (!ffe_is_ffedebug ())
984 /* For debugging purposes only. */
986 if (ffelex_total_tokens_
!= ffelex_old_total_tokens_
)
988 fprintf (dmpout
, "; token_track had %ld tokens, now have %ld.\n",
989 ffelex_old_total_tokens_
, ffelex_total_tokens_
);
990 ffelex_old_total_tokens_
= ffelex_total_tokens_
;
994 /* Copied from gcc/c-common.c get_directive_line. */
996 #if FFECOM_targetCURRENT == FFECOM_targetGCC
998 ffelex_get_directive_line_ (char **text
, FILE *finput
)
1000 static char *directive_buffer
= NULL
;
1001 static unsigned buffer_length
= 0;
1003 register char *buffer_limit
;
1004 register int looking_for
= 0;
1005 register int char_escaped
= 0;
1007 if (buffer_length
== 0)
1009 directive_buffer
= (char *)xmalloc (128);
1010 buffer_length
= 128;
1013 buffer_limit
= &directive_buffer
[buffer_length
];
1015 for (p
= directive_buffer
; ; )
1019 /* Make buffer bigger if it is full. */
1020 if (p
>= buffer_limit
)
1022 register unsigned bytes_used
= (p
- directive_buffer
);
1026 = (char *)xrealloc (directive_buffer
, buffer_length
);
1027 p
= &directive_buffer
[bytes_used
];
1028 buffer_limit
= &directive_buffer
[buffer_length
];
1033 /* Discard initial whitespace. */
1034 if ((c
== ' ' || c
== '\t') && p
== directive_buffer
)
1037 /* Detect the end of the directive. */
1038 if ((c
== '\n' && looking_for
== 0)
1041 if (looking_for
!= 0)
1042 fatal ("Bad directive -- missing close-quote");
1045 *text
= directive_buffer
;
1051 ffelex_next_line_ ();
1053 /* Handle string and character constant syntax. */
1056 if (looking_for
== c
&& !char_escaped
)
1057 looking_for
= 0; /* Found terminator... stop looking. */
1060 if (c
== '\'' || c
== '"')
1061 looking_for
= c
; /* Don't stop buffering until we see another
1062 one of these (or an EOF). */
1064 /* Handle backslash. */
1065 char_escaped
= (c
== '\\' && ! char_escaped
);
1070 /* Handle # directives that make it through (or are generated by) the
1071 preprocessor. As much as reasonably possible, emulate the behavior
1072 of the gcc compiler phase cc1, though interactions between #include
1073 and INCLUDE might possibly produce bizarre results in terms of
1074 error reporting and the generation of debugging info vis-a-vis the
1075 locations of some things.
1077 Returns the next character unhandled, which is always newline or EOF. */
1079 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1081 #if defined HANDLE_PRAGMA
1082 /* Local versions of these macros, that can be passed as function pointers. */
1086 return getc (finput
);
1093 ungetc (arg
, finput
);
1095 #endif /* HANDLE_PRAGMA */
1098 ffelex_hash_ (FILE *finput
)
1101 ffelexToken token
= NULL
;
1103 /* Read first nonwhite char after the `#'. */
1105 c
= ffelex_getc_ (finput
);
1106 while (c
== ' ' || c
== '\t')
1107 c
= ffelex_getc_ (finput
);
1109 /* If a letter follows, then if the word here is `line', skip
1110 it and ignore it; otherwise, ignore the line, with an error
1111 if the word isn't `pragma', `ident', `define', or `undef'. */
1113 if ((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z'))
1117 if (getc (finput
) == 'r'
1118 && getc (finput
) == 'a'
1119 && getc (finput
) == 'g'
1120 && getc (finput
) == 'm'
1121 && getc (finput
) == 'a'
1122 && ((c
= getc (finput
)) == ' ' || c
== '\t' || c
== '\n'
1125 #if 0 /* g77 doesn't handle pragmas, so ignores them FOR NOW. */
1126 static char buffer
[128];
1127 char * buff
= buffer
;
1129 /* Read the pragma name into a buffer.
1130 ISSPACE() may evaluate its argument more than once! */
1131 while (((c
= getc (finput
)), ISSPACE(c
)))
1139 while (c
!= EOF
&& ! ISSPACE (c
) && c
!= '\n'
1140 && buff
< buffer
+ 128);
1145 #ifdef HANDLE_PRAGMA
1146 if (HANDLE_PRAGMA (pragma_getc
, pragma_ungetc
, buffer
))
1148 #endif /* HANDLE_PRAGMA */
1149 #ifdef HANDLE_GENERIC_PRAGMAS
1150 if (handle_generic_pragma (buffer
))
1152 #endif /* !HANDLE_GENERIC_PRAGMAS */
1154 /* Issue a warning message if we have been asked to do so.
1155 Ignoring unknown pragmas in system header file unless
1156 an explcit -Wunknown-pragmas has been given. */
1157 if (warn_unknown_pragmas
> 1
1158 || (warn_unknown_pragmas
&& ! in_system_header
))
1159 warning ("ignoring pragma: %s", token_buffer
);
1167 if (getc (finput
) == 'e'
1168 && getc (finput
) == 'f'
1169 && getc (finput
) == 'i'
1170 && getc (finput
) == 'n'
1171 && getc (finput
) == 'e'
1172 && ((c
= getc (finput
)) == ' ' || c
== '\t' || c
== '\n'
1177 c
= ffelex_get_directive_line_ (&text
, finput
);
1179 #ifdef DWARF_DEBUGGING_INFO
1180 if ((debug_info_level
== DINFO_LEVEL_VERBOSE
)
1181 && (write_symbols
== DWARF_DEBUG
))
1182 dwarfout_define (lineno
, text
);
1183 #endif /* DWARF_DEBUGGING_INFO */
1190 if (getc (finput
) == 'n'
1191 && getc (finput
) == 'd'
1192 && getc (finput
) == 'e'
1193 && getc (finput
) == 'f'
1194 && ((c
= getc (finput
)) == ' ' || c
== '\t' || c
== '\n'
1199 c
= ffelex_get_directive_line_ (&text
, finput
);
1201 #ifdef DWARF_DEBUGGING_INFO
1202 if ((debug_info_level
== DINFO_LEVEL_VERBOSE
)
1203 && (write_symbols
== DWARF_DEBUG
))
1204 dwarfout_undef (lineno
, text
);
1205 #endif /* DWARF_DEBUGGING_INFO */
1212 if (getc (finput
) == 'i'
1213 && getc (finput
) == 'n'
1214 && getc (finput
) == 'e'
1215 && ((c
= getc (finput
)) == ' ' || c
== '\t'))
1220 if (getc (finput
) == 'd'
1221 && getc (finput
) == 'e'
1222 && getc (finput
) == 'n'
1223 && getc (finput
) == 't'
1224 && ((c
= getc (finput
)) == ' ' || c
== '\t'))
1226 /* #ident. The pedantic warning is now in cccp.c. */
1228 /* Here we have just seen `#ident '.
1229 A string constant should follow. */
1231 while (c
== ' ' || c
== '\t')
1234 /* If no argument, ignore the line. */
1235 if (c
== '\n' || c
== EOF
)
1238 c
= ffelex_cfelex_ (&token
, finput
, c
);
1241 || (ffelex_token_type (token
) != FFELEX_typeCHARACTER
))
1243 error ("invalid #ident");
1247 if (! flag_no_ident
)
1249 #ifdef ASM_OUTPUT_IDENT
1250 ASM_OUTPUT_IDENT (asm_out_file
,
1251 ffelex_token_text (token
));
1255 /* Skip the rest of this line. */
1260 error ("undefined or invalid # directive");
1265 /* Here we have either `#line' or `# <nonletter>'.
1266 In either case, it should be a line number; a digit should follow. */
1268 while (c
== ' ' || c
== '\t')
1269 c
= ffelex_getc_ (finput
);
1271 /* If the # is the only nonwhite char on the line,
1272 just ignore it. Check the new newline. */
1273 if (c
== '\n' || c
== EOF
)
1276 /* Something follows the #; read a token. */
1278 c
= ffelex_cfelex_ (&token
, finput
, c
);
1281 && (ffelex_token_type (token
) == FFELEX_typeNUMBER
))
1283 int old_lineno
= lineno
;
1284 char *old_input_filename
= input_filename
;
1287 /* subtract one, because it is the following line that
1288 gets the specified number */
1289 int l
= atoi (ffelex_token_text (token
)) - 1;
1291 /* Is this the last nonwhite stuff on the line? */
1292 while (c
== ' ' || c
== '\t')
1293 c
= ffelex_getc_ (finput
);
1294 if (c
== '\n' || c
== EOF
)
1296 /* No more: store the line number and check following line. */
1298 if (!ffelex_kludge_flag_
)
1300 ffewhere_file_set (NULL
, TRUE
, (ffewhereLineNumber
) l
);
1303 ffelex_token_kill (token
);
1308 /* More follows: it must be a string constant (filename). */
1310 /* Read the string constant. */
1311 c
= ffelex_cfelex_ (&token
, finput
, c
);
1314 || (ffelex_token_type (token
) != FFELEX_typeCHARACTER
))
1316 error ("invalid #line");
1322 if (ffelex_kludge_flag_
)
1323 input_filename
= ffelex_token_text (token
);
1326 wf
= ffewhere_file_new (ffelex_token_text (token
),
1327 ffelex_token_length (token
));
1328 input_filename
= ffewhere_file_name (wf
);
1329 ffewhere_file_set (wf
, TRUE
, (ffewhereLineNumber
) l
);
1332 #if 0 /* Not sure what g77 should do with this yet. */
1333 /* Each change of file name
1334 reinitializes whether we are now in a system header. */
1335 in_system_header
= 0;
1338 if (main_input_filename
== 0)
1339 main_input_filename
= input_filename
;
1341 /* Is this the last nonwhite stuff on the line? */
1342 while (c
== ' ' || c
== '\t')
1344 if (c
== '\n' || c
== EOF
)
1346 if (!ffelex_kludge_flag_
)
1348 /* Update the name in the top element of input_file_stack. */
1349 if (input_file_stack
)
1350 input_file_stack
->name
= input_filename
;
1353 ffelex_token_kill (token
);
1358 c
= ffelex_cfelex_ (&token
, finput
, c
);
1360 /* `1' after file name means entering new file.
1361 `2' after file name means just left a file. */
1364 && (ffelex_token_type (token
) == FFELEX_typeNUMBER
))
1366 int num
= atoi (ffelex_token_text (token
));
1368 if (ffelex_kludge_flag_
)
1371 input_filename
= old_input_filename
;
1372 fatal ("Use `#line ...' instead of `# ...' in first line");
1377 /* Pushing to a new file. */
1378 ffelex_file_push_ (old_lineno
, input_filename
);
1382 /* Popping out of a file. */
1383 ffelex_file_pop_ (input_filename
);
1386 /* Is this the last nonwhite stuff on the line? */
1387 while (c
== ' ' || c
== '\t')
1389 if (c
== '\n' || c
== EOF
)
1392 ffelex_token_kill (token
);
1396 c
= ffelex_cfelex_ (&token
, finput
, c
);
1399 /* `3' after file name means this is a system header file. */
1401 #if 0 /* Not sure what g77 should do with this yet. */
1403 && (ffelex_token_type (token
) == FFELEX_typeNUMBER
)
1404 && (atoi (ffelex_token_text (token
)) == 3))
1405 in_system_header
= 1;
1408 while (c
== ' ' || c
== '\t')
1410 if (((token
!= NULL
)
1411 || (c
!= '\n' && c
!= EOF
))
1412 && ffelex_kludge_flag_
)
1415 input_filename
= old_input_filename
;
1416 fatal ("Use `#line ...' instead of `# ...' in first line");
1420 error ("invalid #-line");
1422 /* skip the rest of this line. */
1424 if ((token
!= NULL
) && !ffelex_kludge_flag_
)
1425 ffelex_token_kill (token
);
1426 while ((c
= getc (finput
)) != EOF
&& c
!= '\n')
1430 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
1432 /* "Image" a character onto the card image, return incremented column number.
1434 Normally invoking this function as in
1435 column = ffelex_image_char_ (c, column);
1436 is the same as doing:
1437 ffelex_card_image_[column++] = c;
1439 However, tabs and carriage returns are handled specially, to preserve
1440 the visual "image" of the input line (in most editors) in the card
1443 Carriage returns are ignored, as they are assumed to be followed
1446 A tab is handled by first doing:
1447 ffelex_card_image_[column++] = ' ';
1448 That is, it translates to at least one space. Then, as many spaces
1449 are imaged as necessary to bring the column number to the next tab
1450 position, where tab positions start in the ninth column and each
1451 eighth column afterwards. ALSO, a static var named ffelex_saw_tab_
1452 is set to TRUE to notify the lexer that a tab was seen.
1454 Columns are numbered and tab stops set as illustrated below:
1456 012345670123456701234567...
1460 xxxxxxx yyyyyyy zzzzzzz
1461 xxxxxxxx yyyyyyyy... */
1463 static ffewhereColumnNumber
1464 ffelex_image_char_ (int c
, ffewhereColumnNumber column
)
1466 ffewhereColumnNumber old_column
= column
;
1468 if (column
>= ffelex_card_size_
)
1470 ffewhereColumnNumber newmax
= ffelex_card_size_
<< 1;
1472 if (ffelex_bad_line_
)
1475 if ((newmax
>> 1) != ffelex_card_size_
)
1476 { /* Overflowed column number. */
1477 overflow
: /* :::::::::::::::::::: */
1479 ffelex_bad_line_
= TRUE
;
1480 strcpy (&ffelex_card_image_
[column
- 3], "...");
1481 ffelex_card_length_
= column
;
1482 ffelex_bad_1_ (FFEBAD_LINE_TOO_LONG
,
1483 ffelex_linecount_current_
, column
+ 1);
1488 = malloc_resize_ksr (malloc_pool_image (),
1491 ffelex_card_size_
+ 9);
1492 ffelex_card_size_
= newmax
;
1501 ffelex_saw_tab_
= TRUE
;
1502 ffelex_card_image_
[column
++] = ' ';
1503 while ((column
& 7) != 0)
1504 ffelex_card_image_
[column
++] = ' ';
1508 if (!ffelex_bad_line_
)
1510 ffelex_bad_line_
= TRUE
;
1511 strcpy (&ffelex_card_image_
[column
], "[\\0]");
1512 ffelex_card_length_
= column
+ 4;
1513 ffebad_start_msg_lex ("Null character at %0 -- line ignored",
1514 FFEBAD_severityFATAL
);
1515 ffelex_bad_here_ (0, ffelex_linecount_current_
, column
+ 1);
1522 ffelex_card_image_
[column
++] = c
;
1526 if (column
< old_column
)
1528 column
= old_column
;
1529 goto overflow
; /* :::::::::::::::::::: */
1538 ffewhereFile include_wherefile
= ffelex_include_wherefile_
;
1539 FILE *include_file
= ffelex_include_file_
;
1540 /* The rest of this is to push, and after the INCLUDE file is processed,
1541 pop, the static lexer state info that pertains to each particular
1544 ffewhereColumnNumber card_size
= ffelex_card_size_
;
1545 ffewhereColumnNumber card_length
= ffelex_card_length_
;
1546 ffewhereLine current_wl
= ffelex_current_wl_
;
1547 ffewhereColumn current_wc
= ffelex_current_wc_
;
1548 bool saw_tab
= ffelex_saw_tab_
;
1549 ffewhereColumnNumber final_nontab_column
= ffelex_final_nontab_column_
;
1550 ffewhereFile current_wf
= ffelex_current_wf_
;
1551 ffewhereLineNumber linecount_current
= ffelex_linecount_current_
;
1552 ffewhereLineNumber linecount_offset
1553 = ffewhere_line_filelinenum (current_wl
);
1554 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1555 int old_lineno
= lineno
;
1556 char *old_input_filename
= input_filename
;
1559 if (card_length
!= 0)
1561 card_image
= malloc_new_ks (malloc_pool_image (),
1562 "FFELEX saved card image",
1564 memcpy (card_image
, ffelex_card_image_
, card_length
);
1569 ffelex_set_include_
= FALSE
;
1571 ffelex_next_line_ ();
1573 ffewhere_file_set (include_wherefile
, TRUE
, 0);
1575 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1576 ffelex_file_push_ (old_lineno
, ffewhere_file_name (include_wherefile
));
1577 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
1579 if (ffelex_include_free_form_
)
1580 ffelex_file_free (include_wherefile
, include_file
);
1582 ffelex_file_fixed (include_wherefile
, include_file
);
1584 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1585 ffelex_file_pop_ (ffewhere_file_name (current_wf
));
1586 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
1588 ffewhere_file_set (current_wf
, TRUE
, linecount_offset
);
1590 ffecom_close_include (include_file
);
1592 if (card_length
!= 0)
1594 #ifdef REDUCE_CARD_SIZE_AFTER_BIGGY /* Define if occasional large lines. */
1595 #error "need to handle possible reduction of card size here!!"
1597 assert (ffelex_card_size_
>= card_length
); /* It shrunk?? */
1598 memcpy (ffelex_card_image_
, card_image
, card_length
);
1600 ffelex_card_image_
[card_length
] = '\0';
1602 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1603 input_filename
= old_input_filename
;
1604 lineno
= old_lineno
;
1606 ffelex_linecount_current_
= linecount_current
;
1607 ffelex_current_wf_
= current_wf
;
1608 ffelex_final_nontab_column_
= final_nontab_column
;
1609 ffelex_saw_tab_
= saw_tab
;
1610 ffelex_current_wc_
= current_wc
;
1611 ffelex_current_wl_
= current_wl
;
1612 ffelex_card_length_
= card_length
;
1613 ffelex_card_size_
= card_size
;
1616 /* ffelex_is_free_char_ctx_contin_ -- Character Context Continuation?
1618 ffewhereColumnNumber col;
1619 int c; // Char at col.
1620 if ((c == '&') && ffelex_is_free_char_ctx_contin_(col + 1))
1621 // We have a continuation indicator.
1623 If there are <n> spaces starting at ffelex_card_image_[col] up through
1624 the null character, where <n> is 0 or greater, returns TRUE. */
1627 ffelex_is_free_char_ctx_contin_ (ffewhereColumnNumber col
)
1629 while (ffelex_card_image_
[col
] != '\0')
1631 if (ffelex_card_image_
[col
++] != ' ')
1637 /* ffelex_is_free_nonc_ctx_contin_ -- Noncharacter Context Continuation?
1639 ffewhereColumnNumber col;
1640 int c; // Char at col.
1641 if ((c == '&') && ffelex_is_free_nonc_ctx_contin_(col + 1))
1642 // We have a continuation indicator.
1644 If there are <n> spaces starting at ffelex_card_image_[col] up through
1645 the null character or '!', where <n> is 0 or greater, returns TRUE. */
1648 ffelex_is_free_nonc_ctx_contin_ (ffewhereColumnNumber col
)
1650 while ((ffelex_card_image_
[col
] != '\0') && (ffelex_card_image_
[col
] != '!'))
1652 if (ffelex_card_image_
[col
++] != ' ')
1659 ffelex_next_line_ ()
1661 ffelex_linecount_current_
= ffelex_linecount_next_
;
1662 ++ffelex_linecount_next_
;
1663 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1669 ffelex_send_token_ ()
1671 ++ffelex_number_of_tokens_
;
1673 ffelex_backslash_ (EOF
, 0);
1675 if (ffelex_token_
->text
== NULL
)
1677 if (ffelex_token_
->type
== FFELEX_typeCHARACTER
)
1679 ffelex_append_to_token_ ('\0');
1680 ffelex_token_
->length
= 0;
1684 ffelex_token_
->text
[ffelex_token_
->length
] = '\0';
1686 assert (ffelex_raw_mode_
== 0);
1688 if (ffelex_token_
->type
== FFELEX_typeNAMES
)
1690 ffewhere_line_kill (ffelex_token_
->currentnames_line
);
1691 ffewhere_column_kill (ffelex_token_
->currentnames_col
);
1694 assert (ffelex_handler_
!= NULL
);
1695 ffelex_handler_
= (ffelexHandler
) (*ffelex_handler_
) (ffelex_token_
);
1696 assert (ffelex_handler_
!= NULL
);
1698 ffelex_token_kill (ffelex_token_
);
1700 ffelex_token_
= ffelex_token_new_ ();
1701 ffelex_token_
->uses
= 1;
1702 ffelex_token_
->text
= NULL
;
1703 if (ffelex_raw_mode_
< 0)
1705 ffelex_token_
->type
= FFELEX_typeCHARACTER
;
1706 ffelex_token_
->where_line
= ffelex_raw_where_line_
;
1707 ffelex_token_
->where_col
= ffelex_raw_where_col_
;
1708 ffelex_raw_where_line_
= ffewhere_line_unknown ();
1709 ffelex_raw_where_col_
= ffewhere_column_unknown ();
1713 ffelex_token_
->type
= FFELEX_typeNONE
;
1714 ffelex_token_
->where_line
= ffewhere_line_unknown ();
1715 ffelex_token_
->where_col
= ffewhere_column_unknown ();
1718 if (ffelex_set_include_
)
1722 /* ffelex_swallow_tokens_ -- Eat all tokens delivered to me
1724 return ffelex_swallow_tokens_;
1726 Return this handler when you don't want to look at any more tokens in the
1727 statement because you've encountered an unrecoverable error in the
1730 static ffelexHandler
1731 ffelex_swallow_tokens_ (ffelexToken t
)
1733 assert (ffelex_eos_handler_
!= NULL
);
1735 if ((ffelex_token_type (t
) == FFELEX_typeEOS
)
1736 || (ffelex_token_type (t
) == FFELEX_typeSEMICOLON
))
1737 return (ffelexHandler
) (*ffelex_eos_handler_
) (t
);
1739 return (ffelexHandler
) ffelex_swallow_tokens_
;
1743 ffelex_token_new_ ()
1747 ++ffelex_total_tokens_
;
1749 t
= (ffelexToken
) malloc_new_ks (malloc_pool_image (),
1750 "FFELEX token", sizeof (*t
));
1751 t
->id_
= ffelex_token_nextid_
++;
1756 ffelex_type_string_ (ffelexType type
)
1758 static const char *types
[] = {
1760 "FFELEX_typeCOMMENT",
1766 "FFELEX_typeDOLLAR",
1768 "FFELEX_typePERCENT",
1769 "FFELEX_typeAMPERSAND",
1770 "FFELEX_typeAPOSTROPHE",
1771 "FFELEX_typeOPEN_PAREN",
1772 "FFELEX_typeCLOSE_PAREN",
1773 "FFELEX_typeASTERISK",
1776 "FFELEX_typePERIOD",
1778 "FFELEX_typeNUMBER",
1779 "FFELEX_typeOPEN_ANGLE",
1780 "FFELEX_typeEQUALS",
1781 "FFELEX_typeCLOSE_ANGLE",
1785 "FFELEX_typeCONCAT",
1788 "FFELEX_typeHOLLERITH",
1789 "FFELEX_typeCHARACTER",
1791 "FFELEX_typeSEMICOLON",
1792 "FFELEX_typeUNDERSCORE",
1793 "FFELEX_typeQUESTION",
1794 "FFELEX_typeOPEN_ARRAY",
1795 "FFELEX_typeCLOSE_ARRAY",
1796 "FFELEX_typeCOLONCOLON",
1797 "FFELEX_typeREL_LE",
1798 "FFELEX_typeREL_NE",
1799 "FFELEX_typeREL_EQ",
1800 "FFELEX_typePOINTS",
1804 if (type
>= ARRAY_SIZE (types
))
1810 ffelex_display_token (ffelexToken t
)
1815 fprintf (dmpout
, "; Token #%lu is %s (line %" ffewhereLineNumber_f
"u, col %"
1816 ffewhereColumnNumber_f
"u)",
1818 ffelex_type_string_ (t
->type
),
1819 ffewhere_line_number (t
->where_line
),
1820 ffewhere_column_number (t
->where_col
));
1822 if (t
->text
!= NULL
)
1823 fprintf (dmpout
, ": \"%.*s\"\n",
1827 fprintf (dmpout
, ".\n");
1830 /* ffelex_expecting_character -- Tells if next token expected to be CHARACTER
1832 if (ffelex_expecting_character())
1833 // next token delivered by lexer will be CHARACTER.
1835 If the most recent call to ffelex_set_expecting_hollerith since the last
1836 token was delivered by the lexer passed a length of -1, then we return
1837 TRUE, because the next token we deliver will be typeCHARACTER, else we
1841 ffelex_expecting_character ()
1843 return (ffelex_raw_mode_
!= 0);
1846 /* ffelex_file_fixed -- Lex a given file in fixed source form
1850 ffelex_file_fixed(wf,f);
1852 Lexes the file according to Fortran 90 ANSI + VXT specifications. */
1855 ffelex_file_fixed (ffewhereFile wf
, FILE *f
)
1857 register int c
= 0; /* Character currently under consideration. */
1858 register ffewhereColumnNumber column
= 0; /* Not really; 0 means column 1... */
1859 bool disallow_continuation_line
;
1860 bool ignore_disallowed_continuation
= FALSE
;
1861 int latest_char_in_file
= 0; /* For getting back into comment-skipping
1864 ffewhereColumnNumber first_label_char
; /* First char of label --
1866 char label_string
[6]; /* Text of label. */
1867 int labi
; /* Length of label text. */
1868 bool finish_statement
; /* Previous statement finished? */
1869 bool have_content
; /* This line have content? */
1870 bool just_do_label
; /* Nothing but label (and continuation?) on
1873 /* Lex is called for a particular file, not for a particular program unit.
1874 Yet the two events do share common characteristics. The first line in a
1875 file or in a program unit cannot be a continuation line. No token can
1876 be in mid-formation. No current label for the statement exists, since
1877 there is no current statement. */
1879 assert (ffelex_handler_
!= NULL
);
1881 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1883 input_filename
= ffewhere_file_name (wf
);
1885 ffelex_current_wf_
= wf
;
1886 disallow_continuation_line
= TRUE
;
1887 ignore_disallowed_continuation
= FALSE
;
1888 ffelex_token_
->type
= FFELEX_typeNONE
;
1889 ffelex_number_of_tokens_
= 0;
1890 ffelex_label_tokens_
= 0;
1891 ffelex_current_wl_
= ffewhere_line_unknown ();
1892 ffelex_current_wc_
= ffewhere_column_unknown ();
1893 latest_char_in_file
= '\n';
1895 if (ffe_is_null_version ())
1897 /* Just substitute a "program" directly here. */
1899 char line
[] = " call g77__fvers;call g77__ivers;call g77__uvers;end";
1903 for (p
= &line
[0]; *p
!= '\0'; ++p
)
1904 column
= ffelex_image_char_ (*p
, column
);
1908 goto have_line
; /* :::::::::::::::::::: */
1911 goto first_line
; /* :::::::::::::::::::: */
1913 /* Come here to get a new line. */
1915 beginning_of_line
: /* :::::::::::::::::::: */
1917 disallow_continuation_line
= FALSE
;
1919 /* Come here directly when last line didn't clarify the continuation issue. */
1921 beginning_of_line_again
: /* :::::::::::::::::::: */
1923 #ifdef REDUCE_CARD_SIZE_AFTER_BIGGY /* Define if occasional large lines. */
1924 if (ffelex_card_size_
!= FFELEX_columnINITIAL_SIZE_
)
1927 = malloc_resize_ks (malloc_pool_image (),
1929 FFELEX_columnINITIAL_SIZE_
+ 9,
1930 ffelex_card_size_
+ 9);
1931 ffelex_card_size_
= FFELEX_columnINITIAL_SIZE_
;
1935 first_line
: /* :::::::::::::::::::: */
1937 c
= latest_char_in_file
;
1938 if ((c
== EOF
) || ((c
= ffelex_getc_ (f
)) == EOF
))
1941 end_of_file
: /* :::::::::::::::::::: */
1943 /* Line ending in EOF instead of \n still counts as a whole line. */
1945 ffelex_finish_statement_ ();
1946 ffewhere_line_kill (ffelex_current_wl_
);
1947 ffewhere_column_kill (ffelex_current_wc_
);
1948 return (ffelexHandler
) ffelex_handler_
;
1951 ffelex_next_line_ ();
1953 ffelex_bad_line_
= FALSE
;
1955 /* Skip over comment (and otherwise ignored) lines as quickly as possible! */
1957 while (((lextype
= ffelex_first_char_
[c
]) == FFELEX_typeCOMMENT
)
1958 || (lextype
== FFELEX_typeERROR
)
1959 || (lextype
== FFELEX_typeSLASH
)
1960 || (lextype
== FFELEX_typeHASH
))
1962 /* Test most frequent type of line first, etc. */
1963 if ((lextype
== FFELEX_typeCOMMENT
)
1964 || ((lextype
== FFELEX_typeSLASH
)
1965 && ((c
= getc (f
)) == '*'))) /* NOTE SIDE-EFFECT. */
1967 /* Typical case (straight comment), just ignore rest of line. */
1968 comment_line
: /* :::::::::::::::::::: */
1970 while ((c
!= '\n') && (c
!= EOF
))
1973 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1974 else if (lextype
== FFELEX_typeHASH
)
1975 c
= ffelex_hash_ (f
);
1977 else if (lextype
== FFELEX_typeSLASH
)
1979 /* SIDE-EFFECT ABOVE HAS HAPPENED. */
1980 ffelex_card_image_
[0] = '/';
1981 ffelex_card_image_
[1] = c
;
1983 goto bad_first_character
; /* :::::::::::::::::::: */
1986 /* typeERROR or unsupported typeHASH. */
1987 { /* Bad first character, get line and display
1989 column
= ffelex_image_char_ (c
, 0);
1991 bad_first_character
: /* :::::::::::::::::::: */
1993 ffelex_bad_line_
= TRUE
;
1994 while (((c
= getc (f
)) != '\n') && (c
!= EOF
))
1995 column
= ffelex_image_char_ (c
, column
);
1996 ffelex_card_image_
[column
] = '\0';
1997 ffelex_card_length_
= column
;
1998 ffelex_bad_1_ (FFEBAD_FIRST_CHAR_INVALID
,
1999 ffelex_linecount_current_
, 1);
2002 /* Read past last char in line. */
2006 ffelex_next_line_ ();
2007 goto end_of_file
; /* :::::::::::::::::::: */
2012 ffelex_next_line_ ();
2015 goto end_of_file
; /* :::::::::::::::::::: */
2017 ffelex_bad_line_
= FALSE
;
2018 } /* while [c, first char, means comment] */
2022 || (ffelex_final_nontab_column_
== 0);
2024 if (lextype
== FFELEX_typeDEBUG
)
2025 c
= ' '; /* A 'D' or 'd' in column 1 with the
2026 debug-lines option on. */
2028 column
= ffelex_image_char_ (c
, 0);
2030 /* Read the entire line in as is (with whitespace processing). */
2032 while (((c
= getc (f
)) != '\n') && (c
!= EOF
))
2033 column
= ffelex_image_char_ (c
, column
);
2035 if (ffelex_bad_line_
)
2037 ffelex_card_image_
[column
] = '\0';
2038 ffelex_card_length_
= column
;
2039 goto comment_line
; /* :::::::::::::::::::: */
2042 /* If no tab, cut off line after column 72/132. */
2044 if (!ffelex_saw_tab_
&& (column
> ffelex_final_nontab_column_
))
2046 /* Technically, we should now fill ffelex_card_image_ up thru column
2047 72/132 with spaces, since character/hollerith constants must count
2048 them in that manner. To save CPU time in several ways (avoid a loop
2049 here that would be used only when we actually end a line in
2050 character-constant mode; avoid writing memory unnecessarily; avoid a
2051 loop later checking spaces when not scanning for character-constant
2052 characters), we don't do this, and we do the appropriate thing when
2053 we encounter end-of-line while actually processing a character
2056 column
= ffelex_final_nontab_column_
;
2059 have_line
: /* :::::::::::::::::::: */
2061 ffelex_card_image_
[column
] = '\0';
2062 ffelex_card_length_
= column
;
2064 /* Save next char in file so we can use register-based c while analyzing
2065 line we just read. */
2067 latest_char_in_file
= c
; /* Should be either '\n' or EOF. */
2069 have_content
= FALSE
;
2071 /* Handle label, if any. */
2074 first_label_char
= FFEWHERE_columnUNKNOWN
;
2075 for (column
= 0; column
< 5; ++column
)
2077 switch (c
= ffelex_card_image_
[column
])
2081 goto stop_looking
; /* :::::::::::::::::::: */
2096 label_string
[labi
++] = c
;
2097 if (first_label_char
== FFEWHERE_columnUNKNOWN
)
2098 first_label_char
= column
+ 1;
2104 ffelex_bad_1_ (FFEBAD_LABEL_FIELD_NOT_NUMERIC
,
2105 ffelex_linecount_current_
,
2107 goto beginning_of_line_again
; /* :::::::::::::::::::: */
2109 if (ffe_is_pedantic ())
2110 ffelex_bad_1_ (FFEBAD_AMPERSAND
,
2111 ffelex_linecount_current_
, 1);
2112 finish_statement
= FALSE
;
2113 just_do_label
= FALSE
;
2114 goto got_a_continuation
; /* :::::::::::::::::::: */
2117 if (ffelex_card_image_
[column
+ 1] == '*')
2118 goto stop_looking
; /* :::::::::::::::::::: */
2121 ffelex_bad_1_ (FFEBAD_LABEL_FIELD_NOT_NUMERIC
,
2122 ffelex_linecount_current_
, column
+ 1);
2123 goto beginning_of_line_again
; /* :::::::::::::::::::: */
2127 stop_looking
: /* :::::::::::::::::::: */
2129 label_string
[labi
] = '\0';
2131 /* Find first nonblank char starting with continuation column. */
2133 if (column
== 5) /* In which case we didn't see end of line in
2135 while ((c
= ffelex_card_image_
[column
]) == ' ')
2138 /* Now we're trying to figure out whether this is a continuation line and
2139 whether there's anything else of substance on the line. The cases are
2142 1. If a line has an explicit continuation character (other than the digit
2143 zero), then if it also has a label, the label is ignored and an error
2144 message is printed. Any remaining text on the line is passed to the
2145 parser tasks, thus even an all-blank line (possibly with an ignored
2146 label) aside from a positive continuation character might have meaning
2147 in the midst of a character or hollerith constant.
2149 2. If a line has no explicit continuation character (that is, it has a
2150 space in column 6 and the first non-space character past column 6 is
2151 not a digit 0-9), then there are two possibilities:
2153 A. A label is present and/or a non-space (and non-comment) character
2154 appears somewhere after column 6. Terminate processing of the previous
2155 statement, if any, send the new label for the next statement, if any,
2156 and start processing a new statement with this non-blank character, if
2159 B. The line is essentially blank, except for a possible comment character.
2160 Don't terminate processing of the previous statement and don't pass any
2161 characters to the parser tasks, since the line is not flagged as a
2162 continuation line. We treat it just like a completely blank line.
2164 3. If a line has a continuation character of zero (0), then we terminate
2165 processing of the previous statement, if any, send the new label for the
2166 next statement, if any, and start processing a new statement, if any
2167 non-blank characters are present.
2169 If, when checking to see if we should terminate the previous statement, it
2170 is found that there is no previous statement but that there is an
2171 outstanding label, substitute CONTINUE as the statement for the label
2172 and display an error message. */
2174 finish_statement
= FALSE
;
2175 just_do_label
= FALSE
;
2179 case '!': /* ANSI Fortran 90 says ! in column 6 is
2181 /* VXT Fortran says ! anywhere is comment, even column 6. */
2182 if (ffe_is_vxt () || (column
!= 5))
2183 goto no_tokens_on_line
; /* :::::::::::::::::::: */
2184 goto got_a_continuation
; /* :::::::::::::::::::: */
2187 if (ffelex_card_image_
[column
+ 1] != '*')
2188 goto some_other_character
; /* :::::::::::::::::::: */
2192 /* This seems right to do. But it is close to call, since / * starting
2193 in column 6 will thus be interpreted as a continuation line
2194 beginning with '*'. */
2196 goto got_a_continuation
;/* :::::::::::::::::::: */
2200 /* End of line. Therefore may be continued-through line, so handle
2201 pending label as possible to-be-continued and drive end-of-statement
2202 for any previous statement, else treat as blank line. */
2204 no_tokens_on_line
: /* :::::::::::::::::::: */
2206 if (ffe_is_pedantic () && (c
== '/'))
2207 ffelex_bad_1_ (FFEBAD_NON_ANSI_COMMENT
,
2208 ffelex_linecount_current_
, column
+ 1);
2209 if (first_label_char
!= FFEWHERE_columnUNKNOWN
)
2210 { /* Can't be a continued-through line if it
2212 finish_statement
= TRUE
;
2213 have_content
= TRUE
;
2214 just_do_label
= TRUE
;
2217 goto beginning_of_line_again
; /* :::::::::::::::::::: */
2220 if (ffe_is_pedantic () && (column
!= 5))
2221 ffelex_bad_1_ (FFEBAD_NON_ANSI_CONTINUATION_COLUMN
,
2222 ffelex_linecount_current_
, column
+ 1);
2223 finish_statement
= TRUE
;
2224 goto check_for_content
; /* :::::::::::::::::::: */
2236 /* NOTE: This label can be reached directly from the code
2237 that lexes the label field in columns 1-5. */
2238 got_a_continuation
: /* :::::::::::::::::::: */
2240 if (first_label_char
!= FFEWHERE_columnUNKNOWN
)
2242 ffelex_bad_2_ (FFEBAD_LABEL_ON_CONTINUATION
,
2243 ffelex_linecount_current_
,
2245 ffelex_linecount_current_
,
2247 first_label_char
= FFEWHERE_columnUNKNOWN
;
2249 if (disallow_continuation_line
)
2251 if (!ignore_disallowed_continuation
)
2252 ffelex_bad_1_ (FFEBAD_INVALID_CONTINUATION
,
2253 ffelex_linecount_current_
, column
+ 1);
2254 goto beginning_of_line_again
; /* :::::::::::::::::::: */
2256 if (ffe_is_pedantic () && (column
!= 5))
2257 ffelex_bad_1_ (FFEBAD_NON_ANSI_CONTINUATION_COLUMN
,
2258 ffelex_linecount_current_
, column
+ 1);
2259 if ((ffelex_raw_mode_
!= 0)
2260 && (((c
= ffelex_card_image_
[column
+ 1]) != '\0')
2261 || !ffelex_saw_tab_
))
2264 have_content
= TRUE
;
2268 check_for_content
: /* :::::::::::::::::::: */
2270 while ((c
= ffelex_card_image_
[++column
]) == ' ')
2275 && (ffelex_card_image_
[column
+ 1] == '*')))
2277 if (ffe_is_pedantic () && (c
== '/'))
2278 ffelex_bad_1_ (FFEBAD_NON_ANSI_COMMENT
,
2279 ffelex_linecount_current_
, column
+ 1);
2280 just_do_label
= TRUE
;
2283 have_content
= TRUE
;
2288 some_other_character
: /* :::::::::::::::::::: */
2291 goto got_a_continuation
;/* :::::::::::::::::::: */
2293 /* Here is the very normal case of a regular character starting in
2294 column 7 or beyond with a blank in column 6. */
2296 finish_statement
= TRUE
;
2297 have_content
= TRUE
;
2302 || (first_label_char
!= FFEWHERE_columnUNKNOWN
))
2304 /* The line has content of some kind, install new end-statement
2305 point for error messages. Note that "content" includes cases
2306 where there's little apparent content but enough to finish
2307 a statement. That's because finishing a statement can trigger
2308 an impending INCLUDE, and that requires accurate line info being
2309 maintained by the lexer. */
2311 if (finish_statement
)
2312 ffelex_prepare_eos_ (); /* Prepare EOS before we move current pointer. */
2314 ffewhere_line_kill (ffelex_current_wl_
);
2315 ffewhere_column_kill (ffelex_current_wc_
);
2316 ffelex_current_wl_
= ffewhere_line_new (ffelex_linecount_current_
);
2317 ffelex_current_wc_
= ffewhere_column_new (ffelex_card_length_
+ 1);
2320 /* We delay this for a combination of reasons. Mainly, it can start
2321 INCLUDE processing, and we want to delay that until the lexer's
2322 info on the line is coherent. And we want to delay that until we're
2323 sure there's a reason to make that info coherent, to avoid saving
2324 lots of useless lines. */
2326 if (finish_statement
)
2327 ffelex_finish_statement_ ();
2329 /* If label is present, enclose it in a NUMBER token and send it along. */
2331 if (first_label_char
!= FFEWHERE_columnUNKNOWN
)
2333 assert (ffelex_token_
->type
== FFELEX_typeNONE
);
2334 ffelex_token_
->type
= FFELEX_typeNUMBER
;
2335 ffelex_append_to_token_ ('\0'); /* Make room for label text. */
2336 strcpy (ffelex_token_
->text
, label_string
);
2337 ffelex_token_
->where_line
2338 = ffewhere_line_use (ffelex_current_wl_
);
2339 ffelex_token_
->where_col
= ffewhere_column_new (first_label_char
);
2340 ffelex_token_
->length
= labi
;
2341 ffelex_send_token_ ();
2342 ++ffelex_label_tokens_
;
2346 goto beginning_of_line
; /* :::::::::::::::::::: */
2348 /* Here is the main engine for parsing. c holds the character at column.
2349 It is already known that c is not a blank, end of line, or shriek,
2350 unless ffelex_raw_mode_ is not 0 (indicating we are in a
2351 character/hollerith constant). A partially filled token may already
2352 exist in ffelex_token_. One special case: if, when the end of the line
2353 is reached, continuation_line is FALSE and the only token on the line is
2354 END, then it is indeed the last statement. We don't look for
2355 continuation lines during this program unit in that case. This is
2356 according to ANSI. */
2358 if (ffelex_raw_mode_
!= 0)
2361 parse_raw_character
: /* :::::::::::::::::::: */
2365 ffewhereColumnNumber i
;
2367 if (ffelex_saw_tab_
|| (column
>= ffelex_final_nontab_column_
))
2368 goto beginning_of_line
; /* :::::::::::::::::::: */
2370 /* Pad out line with "virtual" spaces. */
2372 for (i
= column
; i
< ffelex_final_nontab_column_
; ++i
)
2373 ffelex_card_image_
[i
] = ' ';
2374 ffelex_card_image_
[i
] = '\0';
2375 ffelex_card_length_
= i
;
2379 switch (ffelex_raw_mode_
)
2382 c
= ffelex_backslash_ (c
, column
);
2386 if (!ffelex_backslash_reconsider_
)
2387 ffelex_append_to_token_ (c
);
2388 ffelex_raw_mode_
= -1;
2392 if (c
== ffelex_raw_char_
)
2394 ffelex_raw_mode_
= -1;
2395 ffelex_append_to_token_ (c
);
2399 ffelex_raw_mode_
= 0;
2400 ffelex_backslash_reconsider_
= TRUE
;
2405 if (c
== ffelex_raw_char_
)
2406 ffelex_raw_mode_
= -2;
2409 c
= ffelex_backslash_ (c
, column
);
2412 ffelex_raw_mode_
= -3;
2416 ffelex_append_to_token_ (c
);
2421 c
= ffelex_backslash_ (c
, column
);
2425 if (!ffelex_backslash_reconsider_
)
2427 ffelex_append_to_token_ (c
);
2433 if (ffelex_backslash_reconsider_
)
2434 ffelex_backslash_reconsider_
= FALSE
;
2436 c
= ffelex_card_image_
[++column
];
2438 if (ffelex_raw_mode_
== 0)
2440 ffelex_send_token_ ();
2441 assert (ffelex_raw_mode_
== 0);
2443 c
= ffelex_card_image_
[++column
];
2447 && (ffelex_card_image_
[column
+ 1] == '*')))
2448 goto beginning_of_line
; /* :::::::::::::::::::: */
2449 goto parse_nonraw_character
; /* :::::::::::::::::::: */
2451 goto parse_raw_character
; /* :::::::::::::::::::: */
2454 parse_nonraw_character
: /* :::::::::::::::::::: */
2456 switch (ffelex_token_
->type
)
2458 case FFELEX_typeNONE
:
2462 ffelex_token_
->type
= FFELEX_typeQUOTE
;
2463 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2464 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2465 ffelex_send_token_ ();
2469 ffelex_token_
->type
= FFELEX_typeDOLLAR
;
2470 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2471 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2472 ffelex_send_token_ ();
2476 ffelex_token_
->type
= FFELEX_typePERCENT
;
2477 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2478 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2479 ffelex_send_token_ ();
2483 ffelex_token_
->type
= FFELEX_typeAMPERSAND
;
2484 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2485 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2486 ffelex_send_token_ ();
2490 ffelex_token_
->type
= FFELEX_typeAPOSTROPHE
;
2491 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2492 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2493 ffelex_send_token_ ();
2497 ffelex_token_
->type
= FFELEX_typeOPEN_PAREN
;
2498 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2499 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2503 ffelex_token_
->type
= FFELEX_typeCLOSE_PAREN
;
2504 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2505 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2506 ffelex_send_token_ ();
2510 ffelex_token_
->type
= FFELEX_typeASTERISK
;
2511 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2512 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2516 ffelex_token_
->type
= FFELEX_typePLUS
;
2517 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2518 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2519 ffelex_send_token_ ();
2523 ffelex_token_
->type
= FFELEX_typeCOMMA
;
2524 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2525 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2526 ffelex_send_token_ ();
2530 ffelex_token_
->type
= FFELEX_typeMINUS
;
2531 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2532 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2533 ffelex_send_token_ ();
2537 ffelex_token_
->type
= FFELEX_typePERIOD
;
2538 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2539 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2540 ffelex_send_token_ ();
2544 ffelex_token_
->type
= FFELEX_typeSLASH
;
2545 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2546 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2560 = ffelex_hexnum_
? FFELEX_typeNAME
: FFELEX_typeNUMBER
;
2561 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2562 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2563 ffelex_append_to_token_ (c
);
2567 ffelex_token_
->type
= FFELEX_typeCOLON
;
2568 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2569 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2573 ffelex_token_
->type
= FFELEX_typeSEMICOLON
;
2574 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2575 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2576 ffelex_permit_include_
= TRUE
;
2577 ffelex_send_token_ ();
2578 ffelex_permit_include_
= FALSE
;
2582 ffelex_token_
->type
= FFELEX_typeOPEN_ANGLE
;
2583 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2584 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2588 ffelex_token_
->type
= FFELEX_typeEQUALS
;
2589 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2590 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2594 ffelex_token_
->type
= FFELEX_typeCLOSE_ANGLE
;
2595 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2596 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2600 ffelex_token_
->type
= FFELEX_typeQUESTION
;
2601 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
2602 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2603 ffelex_send_token_ ();
2607 if (1 || ffe_is_90 ())
2609 ffelex_token_
->type
= FFELEX_typeUNDERSCORE
;
2610 ffelex_token_
->where_line
2611 = ffewhere_line_use (ffelex_current_wl_
);
2612 ffelex_token_
->where_col
2613 = ffewhere_column_new (column
+ 1);
2614 ffelex_send_token_ ();
2670 c
= ffesrc_char_source (c
);
2672 if (ffesrc_char_match_init (c
, 'H', 'h')
2673 && ffelex_expecting_hollerith_
!= 0)
2675 ffelex_raw_mode_
= ffelex_expecting_hollerith_
;
2676 ffelex_token_
->type
= FFELEX_typeHOLLERITH
;
2677 ffelex_token_
->where_line
= ffelex_raw_where_line_
;
2678 ffelex_token_
->where_col
= ffelex_raw_where_col_
;
2679 ffelex_raw_where_line_
= ffewhere_line_unknown ();
2680 ffelex_raw_where_col_
= ffewhere_column_unknown ();
2681 c
= ffelex_card_image_
[++column
];
2682 goto parse_raw_character
; /* :::::::::::::::::::: */
2687 ffelex_token_
->where_line
2688 = ffewhere_line_use (ffelex_token_
->currentnames_line
2689 = ffewhere_line_use (ffelex_current_wl_
));
2690 ffelex_token_
->where_col
2691 = ffewhere_column_use (ffelex_token_
->currentnames_col
2692 = ffewhere_column_new (column
+ 1));
2693 ffelex_token_
->type
= FFELEX_typeNAMES
;
2697 ffelex_token_
->where_line
2698 = ffewhere_line_use (ffelex_current_wl_
);
2699 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
2700 ffelex_token_
->type
= FFELEX_typeNAME
;
2702 ffelex_append_to_token_ (c
);
2706 ffelex_bad_1_ (FFEBAD_UNRECOGNIZED_CHARACTER
,
2707 ffelex_linecount_current_
, column
+ 1);
2708 ffelex_finish_statement_ ();
2709 disallow_continuation_line
= TRUE
;
2710 ignore_disallowed_continuation
= TRUE
;
2711 goto beginning_of_line_again
; /* :::::::::::::::::::: */
2715 case FFELEX_typeNAME
:
2770 c
= ffesrc_char_source (c
);
2785 && !ffe_is_dollar_ok ())
2787 ffelex_send_token_ ();
2788 goto parse_next_character
; /* :::::::::::::::::::: */
2790 ffelex_append_to_token_ (c
);
2794 ffelex_send_token_ ();
2795 goto parse_next_character
; /* :::::::::::::::::::: */
2799 case FFELEX_typeNAMES
:
2854 c
= ffesrc_char_source (c
);
2869 && !ffe_is_dollar_ok ())
2871 ffelex_send_token_ ();
2872 goto parse_next_character
; /* :::::::::::::::::::: */
2874 if (ffelex_token_
->length
< FFEWHERE_indexMAX
)
2876 ffewhere_track (&ffelex_token_
->currentnames_line
,
2877 &ffelex_token_
->currentnames_col
,
2878 ffelex_token_
->wheretrack
,
2879 ffelex_token_
->length
,
2880 ffelex_linecount_current_
,
2883 ffelex_append_to_token_ (c
);
2887 ffelex_send_token_ ();
2888 goto parse_next_character
; /* :::::::::::::::::::: */
2892 case FFELEX_typeNUMBER
:
2905 ffelex_append_to_token_ (c
);
2909 ffelex_send_token_ ();
2910 goto parse_next_character
; /* :::::::::::::::::::: */
2914 case FFELEX_typeASTERISK
:
2918 ffelex_token_
->type
= FFELEX_typePOWER
;
2919 ffelex_send_token_ ();
2922 default: /* * not followed by another *. */
2923 ffelex_send_token_ ();
2924 goto parse_next_character
; /* :::::::::::::::::::: */
2928 case FFELEX_typeCOLON
:
2932 ffelex_token_
->type
= FFELEX_typeCOLONCOLON
;
2933 ffelex_send_token_ ();
2936 default: /* : not followed by another :. */
2937 ffelex_send_token_ ();
2938 goto parse_next_character
; /* :::::::::::::::::::: */
2942 case FFELEX_typeSLASH
:
2946 ffelex_token_
->type
= FFELEX_typeCONCAT
;
2947 ffelex_send_token_ ();
2951 ffelex_token_
->type
= FFELEX_typeCLOSE_ARRAY
;
2952 ffelex_send_token_ ();
2956 ffelex_token_
->type
= FFELEX_typeREL_NE
;
2957 ffelex_send_token_ ();
2961 ffelex_send_token_ ();
2962 goto parse_next_character
; /* :::::::::::::::::::: */
2966 case FFELEX_typeOPEN_PAREN
:
2970 ffelex_token_
->type
= FFELEX_typeOPEN_ARRAY
;
2971 ffelex_send_token_ ();
2975 ffelex_send_token_ ();
2976 goto parse_next_character
; /* :::::::::::::::::::: */
2980 case FFELEX_typeOPEN_ANGLE
:
2984 ffelex_token_
->type
= FFELEX_typeREL_LE
;
2985 ffelex_send_token_ ();
2989 ffelex_send_token_ ();
2990 goto parse_next_character
; /* :::::::::::::::::::: */
2994 case FFELEX_typeEQUALS
:
2998 ffelex_token_
->type
= FFELEX_typeREL_EQ
;
2999 ffelex_send_token_ ();
3003 ffelex_token_
->type
= FFELEX_typePOINTS
;
3004 ffelex_send_token_ ();
3008 ffelex_send_token_ ();
3009 goto parse_next_character
; /* :::::::::::::::::::: */
3013 case FFELEX_typeCLOSE_ANGLE
:
3017 ffelex_token_
->type
= FFELEX_typeREL_GE
;
3018 ffelex_send_token_ ();
3022 ffelex_send_token_ ();
3023 goto parse_next_character
; /* :::::::::::::::::::: */
3028 assert ("Serious error!!" == NULL
);
3033 c
= ffelex_card_image_
[++column
];
3035 parse_next_character
: /* :::::::::::::::::::: */
3037 if (ffelex_raw_mode_
!= 0)
3038 goto parse_raw_character
; /* :::::::::::::::::::: */
3041 c
= ffelex_card_image_
[++column
];
3046 && (ffelex_card_image_
[column
+ 1] == '*')))
3048 if ((ffelex_number_of_tokens_
== ffelex_label_tokens_
)
3049 && (ffelex_token_
->type
== FFELEX_typeNAMES
)
3050 && (ffelex_token_
->length
== 3)
3051 && (ffesrc_strncmp_2c (ffe_case_match (),
3052 ffelex_token_
->text
,
3053 "END", "end", "End",
3057 ffelex_finish_statement_ ();
3058 disallow_continuation_line
= TRUE
;
3059 ignore_disallowed_continuation
= FALSE
;
3060 goto beginning_of_line_again
; /* :::::::::::::::::::: */
3062 goto beginning_of_line
; /* :::::::::::::::::::: */
3064 goto parse_nonraw_character
; /* :::::::::::::::::::: */
3067 /* ffelex_file_free -- Lex a given file in free source form
3071 ffelex_file_free(wf,f);
3073 Lexes the file according to Fortran 90 ANSI + VXT specifications. */
3076 ffelex_file_free (ffewhereFile wf
, FILE *f
)
3078 register int c
= 0; /* Character currently under consideration. */
3079 register ffewhereColumnNumber column
= 0; /* Not really; 0 means column 1... */
3080 bool continuation_line
= FALSE
;
3081 ffewhereColumnNumber continuation_column
;
3082 int latest_char_in_file
= 0; /* For getting back into comment-skipping
3085 /* Lex is called for a particular file, not for a particular program unit.
3086 Yet the two events do share common characteristics. The first line in a
3087 file or in a program unit cannot be a continuation line. No token can
3088 be in mid-formation. No current label for the statement exists, since
3089 there is no current statement. */
3091 assert (ffelex_handler_
!= NULL
);
3093 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3095 input_filename
= ffewhere_file_name (wf
);
3097 ffelex_current_wf_
= wf
;
3098 continuation_line
= FALSE
;
3099 ffelex_token_
->type
= FFELEX_typeNONE
;
3100 ffelex_number_of_tokens_
= 0;
3101 ffelex_current_wl_
= ffewhere_line_unknown ();
3102 ffelex_current_wc_
= ffewhere_column_unknown ();
3103 latest_char_in_file
= '\n';
3105 /* Come here to get a new line. */
3107 beginning_of_line
: /* :::::::::::::::::::: */
3109 c
= latest_char_in_file
;
3110 if ((c
== EOF
) || ((c
= ffelex_getc_ (f
)) == EOF
))
3113 end_of_file
: /* :::::::::::::::::::: */
3115 /* Line ending in EOF instead of \n still counts as a whole line. */
3117 ffelex_finish_statement_ ();
3118 ffewhere_line_kill (ffelex_current_wl_
);
3119 ffewhere_column_kill (ffelex_current_wc_
);
3120 return (ffelexHandler
) ffelex_handler_
;
3123 ffelex_next_line_ ();
3125 ffelex_bad_line_
= FALSE
;
3127 /* Skip over initial-comment and empty lines as quickly as possible! */
3135 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3136 c
= ffelex_hash_ (f
);
3138 /* Don't skip over # line after all. */
3143 comment_line
: /* :::::::::::::::::::: */
3145 while ((c
!= '\n') && (c
!= EOF
))
3150 ffelex_next_line_ ();
3151 goto end_of_file
; /* :::::::::::::::::::: */
3156 ffelex_next_line_ ();
3159 goto end_of_file
; /* :::::::::::::::::::: */
3162 ffelex_saw_tab_
= FALSE
;
3164 column
= ffelex_image_char_ (c
, 0);
3166 /* Read the entire line in as is (with whitespace processing). */
3168 while (((c
= getc (f
)) != '\n') && (c
!= EOF
))
3169 column
= ffelex_image_char_ (c
, column
);
3171 if (ffelex_bad_line_
)
3173 ffelex_card_image_
[column
] = '\0';
3174 ffelex_card_length_
= column
;
3175 goto comment_line
; /* :::::::::::::::::::: */
3178 /* If no tab, cut off line after column 132. */
3180 if (!ffelex_saw_tab_
&& (column
> FFELEX_FREE_MAX_COLUMNS_
))
3181 column
= FFELEX_FREE_MAX_COLUMNS_
;
3183 ffelex_card_image_
[column
] = '\0';
3184 ffelex_card_length_
= column
;
3186 /* Save next char in file so we can use register-based c while analyzing
3187 line we just read. */
3189 latest_char_in_file
= c
; /* Should be either '\n' or EOF. */
3192 continuation_column
= 0;
3194 /* Skip over initial spaces to see if the first nonblank character
3195 is exclamation point, newline, or EOF (line is therefore a comment) or
3196 ampersand (line is therefore a continuation line). */
3198 while ((c
= ffelex_card_image_
[column
]) == ' ')
3205 goto beginning_of_line
; /* :::::::::::::::::::: */
3208 continuation_column
= column
+ 1;
3215 /* The line definitely has content of some kind, install new end-statement
3216 point for error messages. */
3218 ffewhere_line_kill (ffelex_current_wl_
);
3219 ffewhere_column_kill (ffelex_current_wc_
);
3220 ffelex_current_wl_
= ffewhere_line_new (ffelex_linecount_current_
);
3221 ffelex_current_wc_
= ffewhere_column_new (ffelex_card_length_
+ 1);
3223 /* Figure out which column to start parsing at. */
3225 if (continuation_line
)
3227 if (continuation_column
== 0)
3229 if (ffelex_raw_mode_
!= 0)
3231 ffelex_bad_1_ (FFEBAD_BAD_CHAR_CONTINUE
,
3232 ffelex_linecount_current_
, column
+ 1);
3234 else if (ffelex_token_
->type
!= FFELEX_typeNONE
)
3236 ffelex_bad_1_ (FFEBAD_BAD_LEXTOK_CONTINUE
,
3237 ffelex_linecount_current_
, column
+ 1);
3240 else if (ffelex_is_free_char_ctx_contin_ (continuation_column
))
3241 { /* Line contains only a single "&" as only
3242 nonblank character. */
3243 ffelex_bad_1_ (FFEBAD_BAD_FREE_CONTINUE
,
3244 ffelex_linecount_current_
, continuation_column
);
3245 goto beginning_of_line
; /* :::::::::::::::::::: */
3247 column
= continuation_column
;
3252 c
= ffelex_card_image_
[column
];
3253 continuation_line
= FALSE
;
3255 /* Here is the main engine for parsing. c holds the character at column.
3256 It is already known that c is not a blank, end of line, or shriek,
3257 unless ffelex_raw_mode_ is not 0 (indicating we are in a
3258 character/hollerith constant). A partially filled token may already
3259 exist in ffelex_token_. */
3261 if (ffelex_raw_mode_
!= 0)
3264 parse_raw_character
: /* :::::::::::::::::::: */
3269 if (ffelex_is_free_char_ctx_contin_ (column
+ 1))
3271 continuation_line
= TRUE
;
3272 goto beginning_of_line
; /* :::::::::::::::::::: */
3277 ffelex_finish_statement_ ();
3278 goto beginning_of_line
; /* :::::::::::::::::::: */
3284 switch (ffelex_raw_mode_
)
3287 c
= ffelex_backslash_ (c
, column
);
3291 if (!ffelex_backslash_reconsider_
)
3292 ffelex_append_to_token_ (c
);
3293 ffelex_raw_mode_
= -1;
3297 if (c
== ffelex_raw_char_
)
3299 ffelex_raw_mode_
= -1;
3300 ffelex_append_to_token_ (c
);
3304 ffelex_raw_mode_
= 0;
3305 ffelex_backslash_reconsider_
= TRUE
;
3310 if (c
== ffelex_raw_char_
)
3311 ffelex_raw_mode_
= -2;
3314 c
= ffelex_backslash_ (c
, column
);
3317 ffelex_raw_mode_
= -3;
3321 ffelex_append_to_token_ (c
);
3326 c
= ffelex_backslash_ (c
, column
);
3330 if (!ffelex_backslash_reconsider_
)
3332 ffelex_append_to_token_ (c
);
3338 if (ffelex_backslash_reconsider_
)
3339 ffelex_backslash_reconsider_
= FALSE
;
3341 c
= ffelex_card_image_
[++column
];
3343 if (ffelex_raw_mode_
== 0)
3345 ffelex_send_token_ ();
3346 assert (ffelex_raw_mode_
== 0);
3348 c
= ffelex_card_image_
[++column
];
3349 if ((c
== '\0') || (c
== '!'))
3351 ffelex_finish_statement_ ();
3352 goto beginning_of_line
; /* :::::::::::::::::::: */
3354 if ((c
== '&') && ffelex_is_free_nonc_ctx_contin_ (column
+ 1))
3356 continuation_line
= TRUE
;
3357 goto beginning_of_line
; /* :::::::::::::::::::: */
3359 goto parse_nonraw_character_noncontin
; /* :::::::::::::::::::: */
3361 goto parse_raw_character
; /* :::::::::::::::::::: */
3364 parse_nonraw_character
: /* :::::::::::::::::::: */
3366 if ((c
== '&') && ffelex_is_free_nonc_ctx_contin_ (column
+ 1))
3368 continuation_line
= TRUE
;
3369 goto beginning_of_line
; /* :::::::::::::::::::: */
3372 parse_nonraw_character_noncontin
: /* :::::::::::::::::::: */
3374 switch (ffelex_token_
->type
)
3376 case FFELEX_typeNONE
:
3379 finish-statement/continue-statement
3382 c
= ffelex_card_image_
[++column
];
3383 if ((c
== '\0') || (c
== '!'))
3385 ffelex_finish_statement_ ();
3386 goto beginning_of_line
; /* :::::::::::::::::::: */
3388 if ((c
== '&') && ffelex_is_free_nonc_ctx_contin_ (column
+ 1))
3390 continuation_line
= TRUE
;
3391 goto beginning_of_line
; /* :::::::::::::::::::: */
3398 ffelex_token_
->type
= FFELEX_typeQUOTE
;
3399 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3400 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3401 ffelex_send_token_ ();
3405 ffelex_token_
->type
= FFELEX_typeDOLLAR
;
3406 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3407 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3408 ffelex_send_token_ ();
3412 ffelex_token_
->type
= FFELEX_typePERCENT
;
3413 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3414 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3415 ffelex_send_token_ ();
3419 ffelex_token_
->type
= FFELEX_typeAMPERSAND
;
3420 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3421 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3422 ffelex_send_token_ ();
3426 ffelex_token_
->type
= FFELEX_typeAPOSTROPHE
;
3427 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3428 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3429 ffelex_send_token_ ();
3433 ffelex_token_
->type
= FFELEX_typeOPEN_PAREN
;
3434 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3435 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3439 ffelex_token_
->type
= FFELEX_typeCLOSE_PAREN
;
3440 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3441 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3442 ffelex_send_token_ ();
3446 ffelex_token_
->type
= FFELEX_typeASTERISK
;
3447 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3448 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3452 ffelex_token_
->type
= FFELEX_typePLUS
;
3453 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3454 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3455 ffelex_send_token_ ();
3459 ffelex_token_
->type
= FFELEX_typeCOMMA
;
3460 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3461 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3462 ffelex_send_token_ ();
3466 ffelex_token_
->type
= FFELEX_typeMINUS
;
3467 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3468 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3469 ffelex_send_token_ ();
3473 ffelex_token_
->type
= FFELEX_typePERIOD
;
3474 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3475 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3476 ffelex_send_token_ ();
3480 ffelex_token_
->type
= FFELEX_typeSLASH
;
3481 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3482 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3496 = ffelex_hexnum_
? FFELEX_typeNAME
: FFELEX_typeNUMBER
;
3497 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3498 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3499 ffelex_append_to_token_ (c
);
3503 ffelex_token_
->type
= FFELEX_typeCOLON
;
3504 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3505 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3509 ffelex_token_
->type
= FFELEX_typeSEMICOLON
;
3510 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3511 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3512 ffelex_permit_include_
= TRUE
;
3513 ffelex_send_token_ ();
3514 ffelex_permit_include_
= FALSE
;
3518 ffelex_token_
->type
= FFELEX_typeOPEN_ANGLE
;
3519 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3520 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3524 ffelex_token_
->type
= FFELEX_typeEQUALS
;
3525 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3526 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3530 ffelex_token_
->type
= FFELEX_typeCLOSE_ANGLE
;
3531 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3532 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3536 ffelex_token_
->type
= FFELEX_typeQUESTION
;
3537 ffelex_token_
->where_line
= ffewhere_line_use (ffelex_current_wl_
);
3538 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3539 ffelex_send_token_ ();
3543 if (1 || ffe_is_90 ())
3545 ffelex_token_
->type
= FFELEX_typeUNDERSCORE
;
3546 ffelex_token_
->where_line
3547 = ffewhere_line_use (ffelex_current_wl_
);
3548 ffelex_token_
->where_col
3549 = ffewhere_column_new (column
+ 1);
3550 ffelex_send_token_ ();
3606 c
= ffesrc_char_source (c
);
3608 if (ffesrc_char_match_init (c
, 'H', 'h')
3609 && ffelex_expecting_hollerith_
!= 0)
3611 ffelex_raw_mode_
= ffelex_expecting_hollerith_
;
3612 ffelex_token_
->type
= FFELEX_typeHOLLERITH
;
3613 ffelex_token_
->where_line
= ffelex_raw_where_line_
;
3614 ffelex_token_
->where_col
= ffelex_raw_where_col_
;
3615 ffelex_raw_where_line_
= ffewhere_line_unknown ();
3616 ffelex_raw_where_col_
= ffewhere_column_unknown ();
3617 c
= ffelex_card_image_
[++column
];
3618 goto parse_raw_character
; /* :::::::::::::::::::: */
3621 if (ffelex_names_pure_
)
3623 ffelex_token_
->where_line
3624 = ffewhere_line_use (ffelex_token_
->currentnames_line
3625 = ffewhere_line_use (ffelex_current_wl_
));
3626 ffelex_token_
->where_col
3627 = ffewhere_column_use (ffelex_token_
->currentnames_col
3628 = ffewhere_column_new (column
+ 1));
3629 ffelex_token_
->type
= FFELEX_typeNAMES
;
3633 ffelex_token_
->where_line
3634 = ffewhere_line_use (ffelex_current_wl_
);
3635 ffelex_token_
->where_col
= ffewhere_column_new (column
+ 1);
3636 ffelex_token_
->type
= FFELEX_typeNAME
;
3638 ffelex_append_to_token_ (c
);
3642 ffelex_bad_1_ (FFEBAD_UNRECOGNIZED_CHARACTER
,
3643 ffelex_linecount_current_
, column
+ 1);
3644 ffelex_finish_statement_ ();
3645 goto beginning_of_line
; /* :::::::::::::::::::: */
3649 case FFELEX_typeNAME
:
3704 c
= ffesrc_char_source (c
);
3719 && !ffe_is_dollar_ok ())
3721 ffelex_send_token_ ();
3722 goto parse_next_character
; /* :::::::::::::::::::: */
3724 ffelex_append_to_token_ (c
);
3728 ffelex_send_token_ ();
3729 goto parse_next_character
; /* :::::::::::::::::::: */
3733 case FFELEX_typeNAMES
:
3788 c
= ffesrc_char_source (c
);
3803 && !ffe_is_dollar_ok ())
3805 ffelex_send_token_ ();
3806 goto parse_next_character
; /* :::::::::::::::::::: */
3808 if (ffelex_token_
->length
< FFEWHERE_indexMAX
)
3810 ffewhere_track (&ffelex_token_
->currentnames_line
,
3811 &ffelex_token_
->currentnames_col
,
3812 ffelex_token_
->wheretrack
,
3813 ffelex_token_
->length
,
3814 ffelex_linecount_current_
,
3817 ffelex_append_to_token_ (c
);
3821 ffelex_send_token_ ();
3822 goto parse_next_character
; /* :::::::::::::::::::: */
3826 case FFELEX_typeNUMBER
:
3839 ffelex_append_to_token_ (c
);
3843 ffelex_send_token_ ();
3844 goto parse_next_character
; /* :::::::::::::::::::: */
3848 case FFELEX_typeASTERISK
:
3852 ffelex_token_
->type
= FFELEX_typePOWER
;
3853 ffelex_send_token_ ();
3856 default: /* * not followed by another *. */
3857 ffelex_send_token_ ();
3858 goto parse_next_character
; /* :::::::::::::::::::: */
3862 case FFELEX_typeCOLON
:
3866 ffelex_token_
->type
= FFELEX_typeCOLONCOLON
;
3867 ffelex_send_token_ ();
3870 default: /* : not followed by another :. */
3871 ffelex_send_token_ ();
3872 goto parse_next_character
; /* :::::::::::::::::::: */
3876 case FFELEX_typeSLASH
:
3880 ffelex_token_
->type
= FFELEX_typeCONCAT
;
3881 ffelex_send_token_ ();
3885 ffelex_token_
->type
= FFELEX_typeCLOSE_ARRAY
;
3886 ffelex_send_token_ ();
3890 ffelex_token_
->type
= FFELEX_typeREL_NE
;
3891 ffelex_send_token_ ();
3895 ffelex_send_token_ ();
3896 goto parse_next_character
; /* :::::::::::::::::::: */
3900 case FFELEX_typeOPEN_PAREN
:
3904 ffelex_token_
->type
= FFELEX_typeOPEN_ARRAY
;
3905 ffelex_send_token_ ();
3909 ffelex_send_token_ ();
3910 goto parse_next_character
; /* :::::::::::::::::::: */
3914 case FFELEX_typeOPEN_ANGLE
:
3918 ffelex_token_
->type
= FFELEX_typeREL_LE
;
3919 ffelex_send_token_ ();
3923 ffelex_send_token_ ();
3924 goto parse_next_character
; /* :::::::::::::::::::: */
3928 case FFELEX_typeEQUALS
:
3932 ffelex_token_
->type
= FFELEX_typeREL_EQ
;
3933 ffelex_send_token_ ();
3937 ffelex_token_
->type
= FFELEX_typePOINTS
;
3938 ffelex_send_token_ ();
3942 ffelex_send_token_ ();
3943 goto parse_next_character
; /* :::::::::::::::::::: */
3947 case FFELEX_typeCLOSE_ANGLE
:
3951 ffelex_token_
->type
= FFELEX_typeREL_GE
;
3952 ffelex_send_token_ ();
3956 ffelex_send_token_ ();
3957 goto parse_next_character
; /* :::::::::::::::::::: */
3962 assert ("Serious error!" == NULL
);
3967 c
= ffelex_card_image_
[++column
];
3969 parse_next_character
: /* :::::::::::::::::::: */
3971 if (ffelex_raw_mode_
!= 0)
3972 goto parse_raw_character
; /* :::::::::::::::::::: */
3974 if ((c
== '\0') || (c
== '!'))
3976 ffelex_finish_statement_ ();
3977 goto beginning_of_line
; /* :::::::::::::::::::: */
3979 goto parse_nonraw_character
; /* :::::::::::::::::::: */
3982 /* See the code in com.c that calls this to understand why. */
3984 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3986 ffelex_hash_kludge (FILE *finput
)
3988 /* If you change this constant string, you have to change whatever
3989 code might thus be affected by it in terms of having to use
3990 ffelex_getc_() instead of getc() in the lexers and _hash_. */
3991 static char match
[] = "# 1 \"";
3992 static int kludge
[ARRAY_SIZE (match
) + 1];
3997 /* Read chars as long as they match the target string.
3998 Copy them into an array that will serve as a record
3999 of what we read (essentially a multi-char ungetc(),
4000 for code that uses ffelex_getc_ instead of getc() elsewhere
4002 for (p
= &match
[0], q
= &kludge
[0], c
= getc (finput
);
4003 (c
== *p
) && (*p
!= '\0') && (c
!= EOF
);
4004 ++p
, ++q
, c
= getc (finput
))
4007 *q
= c
; /* Might be EOF, which requires int. */
4010 ffelex_kludge_chars_
= &kludge
[0];
4014 ffelex_kludge_flag_
= TRUE
;
4015 ++ffelex_kludge_chars_
;
4016 ffelex_hash_ (finput
); /* Handle it NOW rather than later. */
4017 ffelex_kludge_flag_
= FALSE
;
4027 ffelex_final_nontab_column_
= ffe_fixed_line_length ();
4028 ffelex_card_size_
= FFELEX_columnINITIAL_SIZE_
;
4029 ffelex_card_image_
= malloc_new_ksr (malloc_pool_image (),
4030 "FFELEX card image",
4031 FFELEX_columnINITIAL_SIZE_
+ 9);
4032 ffelex_card_image_
[0] = '\0';
4034 for (i
= 0; i
< 256; ++i
)
4035 ffelex_first_char_
[i
] = FFELEX_typeERROR
;
4037 ffelex_first_char_
['\t'] = FFELEX_typeRAW
;
4038 ffelex_first_char_
['\n'] = FFELEX_typeCOMMENT
;
4039 ffelex_first_char_
['\v'] = FFELEX_typeCOMMENT
;
4040 ffelex_first_char_
['\f'] = FFELEX_typeCOMMENT
;
4041 ffelex_first_char_
['\r'] = FFELEX_typeRAW
;
4042 ffelex_first_char_
[' '] = FFELEX_typeRAW
;
4043 ffelex_first_char_
['!'] = FFELEX_typeCOMMENT
;
4044 ffelex_first_char_
['*'] = FFELEX_typeCOMMENT
;
4045 ffelex_first_char_
['/'] = FFELEX_typeSLASH
;
4046 ffelex_first_char_
['&'] = FFELEX_typeRAW
;
4047 ffelex_first_char_
['#'] = FFELEX_typeHASH
;
4049 for (i
= '0'; i
<= '9'; ++i
)
4050 ffelex_first_char_
[i
] = FFELEX_typeRAW
;
4052 if ((ffe_case_match () == FFE_caseNONE
)
4053 || ((ffe_case_match () == FFE_caseUPPER
)
4054 && (ffe_case_source () != FFE_caseLOWER
)) /* Idiot! :-) */
4055 || ((ffe_case_match () == FFE_caseLOWER
)
4056 && (ffe_case_source () == FFE_caseLOWER
)))
4058 ffelex_first_char_
['C'] = FFELEX_typeCOMMENT
;
4059 ffelex_first_char_
['D'] = FFELEX_typeCOMMENT
;
4061 if ((ffe_case_match () == FFE_caseNONE
)
4062 || ((ffe_case_match () == FFE_caseLOWER
)
4063 && (ffe_case_source () != FFE_caseUPPER
)) /* Idiot! :-) */
4064 || ((ffe_case_match () == FFE_caseUPPER
)
4065 && (ffe_case_source () == FFE_caseUPPER
)))
4067 ffelex_first_char_
['c'] = FFELEX_typeCOMMENT
;
4068 ffelex_first_char_
['d'] = FFELEX_typeCOMMENT
;
4071 ffelex_linecount_current_
= 0;
4072 ffelex_linecount_next_
= 1;
4073 ffelex_raw_mode_
= 0;
4074 ffelex_set_include_
= FALSE
;
4075 ffelex_permit_include_
= FALSE
;
4076 ffelex_names_
= TRUE
; /* First token in program is a names. */
4077 ffelex_names_pure_
= FALSE
; /* Free-form lexer does NAMES only for
4079 ffelex_hexnum_
= FALSE
;
4080 ffelex_expecting_hollerith_
= 0;
4081 ffelex_raw_where_line_
= ffewhere_line_unknown ();
4082 ffelex_raw_where_col_
= ffewhere_column_unknown ();
4084 ffelex_token_
= ffelex_token_new_ ();
4085 ffelex_token_
->type
= FFELEX_typeNONE
;
4086 ffelex_token_
->uses
= 1;
4087 ffelex_token_
->where_line
= ffewhere_line_unknown ();
4088 ffelex_token_
->where_col
= ffewhere_column_unknown ();
4089 ffelex_token_
->text
= NULL
;
4091 ffelex_handler_
= NULL
;
4094 /* ffelex_is_names_expected -- Is the current parser expecting NAMES vs. NAME?
4096 if (ffelex_is_names_expected())
4097 // Deliver NAMES token
4099 // Deliver NAME token
4101 Must be called while lexer is active, obviously. */
4104 ffelex_is_names_expected ()
4106 return ffelex_names_
;
4109 /* Current card image, which has the master linecount number
4110 ffelex_linecount_current_. */
4115 return ffelex_card_image_
;
4118 /* ffelex_line_length -- Return length of current lexer line
4120 printf("Length is %lu\n",ffelex_line_length());
4122 Must be called while lexer is active, obviously. */
4124 ffewhereColumnNumber
4125 ffelex_line_length ()
4127 return ffelex_card_length_
;
4130 /* Master line count of current card image, or 0 if no card image
4134 ffelex_line_number ()
4136 return ffelex_linecount_current_
;
4139 /* ffelex_set_expecting_hollerith -- Set hollerith expectation status
4141 ffelex_set_expecting_hollerith(0);
4143 Lex initially assumes no hollerith constant is about to show up. If
4144 syntactic analysis expects one, it should call this function with the
4145 number of characters expected in the constant immediately after recognizing
4146 the decimal number preceding the "H" and the constant itself. Then, if
4147 the next character is indeed H, the lexer will interpret it as beginning
4148 a hollerith constant and ship the token formed by reading the specified
4149 number of characters (interpreting blanks and otherwise-comments too)
4150 from the input file. It is up to syntactic analysis to call this routine
4151 again with 0 to turn hollerith detection off immediately upon receiving
4152 the token that might or might not be HOLLERITH.
4154 Also call this after seeing an APOSTROPHE or QUOTE token that begins a
4155 character constant. Pass the expected termination character (apostrophe
4158 Pass for length either the length of the hollerith (must be > 0), -1
4159 meaning expecting a character constant, or 0 to cancel expectation of
4160 a hollerith only after calling it with a length of > 0 and receiving the
4161 next token (which may or may not have been a HOLLERITH token).
4163 Pass for which either an apostrophe or quote when passing length of -1.
4164 Else which is a don't-care.
4166 Pass for line and column the line/column info for the token beginning the
4167 character or hollerith constant, for use in error messages, when passing
4168 a length of -1 -- this function will invoke ffewhere_line/column_use to
4169 make its own copies. Else line and column are don't-cares (when length
4170 is 0) and the outstanding copies of the previous line/column info, if
4171 still around, are killed.
4174 When called with length of 0, also zero ffelex_raw_mode_. This is
4175 so ffest_save_ can undo the effects of replaying tokens like
4176 APOSTROPHE and QUOTE.
4178 New line, column arguments allow error messages to point to the true
4179 beginning of a character/hollerith constant, rather than the beginning
4180 of the content part, which makes them more consistent and helpful.
4182 New "which" argument allows caller to specify termination character,
4183 which should be apostrophe or double-quote, to support Fortran 90. */
4186 ffelex_set_expecting_hollerith (long length
, char which
,
4187 ffewhereLine line
, ffewhereColumn column
)
4190 /* First kill the pending line/col info, if any (should only be pending
4191 when this call has length==0, the previous call had length>0, and a
4192 non-HOLLERITH token was sent in between the calls, but play it safe). */
4194 ffewhere_line_kill (ffelex_raw_where_line_
);
4195 ffewhere_column_kill (ffelex_raw_where_col_
);
4197 /* Now handle the length function. */
4201 ffelex_expecting_hollerith_
= 0;
4202 ffelex_raw_mode_
= 0;
4203 ffelex_raw_where_line_
= ffewhere_line_unknown ();
4204 ffelex_raw_where_col_
= ffewhere_column_unknown ();
4205 return; /* Don't set new line/column info from args. */
4208 ffelex_raw_mode_
= -1;
4209 ffelex_raw_char_
= which
;
4212 default: /* length > 0 */
4213 ffelex_expecting_hollerith_
= length
;
4217 /* Now set new line/column information from passed args. */
4219 ffelex_raw_where_line_
= ffewhere_line_use (line
);
4220 ffelex_raw_where_col_
= ffewhere_column_use (column
);
4223 /* ffelex_set_handler -- Set handler for tokens before calling _fixed or _free
4225 ffelex_set_handler((ffelexHandler) my_first_handler);
4227 Must be called before calling ffelex_file_fixed or ffelex_file_free or
4228 after they return, but not while they are active. */
4231 ffelex_set_handler (ffelexHandler first
)
4233 ffelex_handler_
= first
;
4236 /* ffelex_set_hexnum -- Set hexnum flag
4238 ffelex_set_hexnum(TRUE);
4240 Lex normally interprets a token starting with [0-9] as a NUMBER token,
4241 so if it sees a [A-Za-z] in it, it stops parsing the NUMBER and leaves
4242 the character as the first of the next token. But when parsing a
4243 hexadecimal number, by calling this function with TRUE before starting
4244 the parse of the token itself, lex will interpret [0-9] as the start
4248 ffelex_set_hexnum (bool f
)
4253 /* ffelex_set_include -- Set INCLUDE file to be processed next
4255 ffewhereFile wf; // The ffewhereFile object for the file.
4256 bool free_form; // TRUE means read free-form file, FALSE fixed-form.
4257 FILE *fi; // The file to INCLUDE.
4258 ffelex_set_include(wf,free_form,fi);
4260 Must be called only after receiving the EOS token following a valid
4261 INCLUDE statement specifying a file that has already been successfully
4265 ffelex_set_include (ffewhereFile wf
, bool free_form
, FILE *fi
)
4267 assert (ffelex_permit_include_
);
4268 assert (!ffelex_set_include_
);
4269 ffelex_set_include_
= TRUE
;
4270 ffelex_include_free_form_
= free_form
;
4271 ffelex_include_file_
= fi
;
4272 ffelex_include_wherefile_
= wf
;
4275 /* ffelex_set_names -- Set names/name flag, names = TRUE
4277 ffelex_set_names(FALSE);
4279 Lex initially assumes multiple names should be formed. If this function is
4280 called with FALSE, then single names are formed instead. The differences
4281 are a difference in the token type (FFELEX_typeNAMES vs. FFELEX_typeNAME)
4282 and in whether full source-location tracking is performed (it is for
4283 multiple names, not for single names), which is more expensive in terms of
4287 ffelex_set_names (bool f
)
4291 ffelex_names_pure_
= FALSE
;
4294 /* ffelex_set_names_pure -- Set names/name (pure) flag, names = TRUE
4296 ffelex_set_names_pure(FALSE);
4298 Like ffelex_set_names, except affects both lexers. Normally, the
4299 free-form lexer need not generate NAMES tokens because adjacent NAME
4300 tokens must be separated by spaces which causes the lexer to generate
4301 separate tokens for analysis (whereas in fixed-form the spaces are
4302 ignored resulting in one long token). But in FORMAT statements, for
4303 some reason, the Fortran 90 standard specifies that spaces can occur
4304 anywhere within a format-item-list with no effect on the format spec
4305 (except of course within character string edit descriptors), which means
4306 that "1PE14.2" and "1 P E 1 4 . 2" are equivalent. For the FORMAT
4307 statement handling, the existence of spaces makes it hard to deal with,
4308 because each token is seen distinctly (i.e. seven tokens in the latter
4309 example). But when no spaces are provided, as in the former example,
4310 then only four tokens are generated, NUMBER("1"), NAME("PE14"), PERIOD,
4311 NUMBER ("2"). By generating a NAMES instead of NAME, three things happen:
4312 One, ffest_kw_format_ does a substring rather than full-string match,
4313 and thus matches "PE14" to "PE"; two, ffelex_token_xyz_from_names functions
4314 may be used to pull NAME/NAMES and NUMBER tokens out of the NAMES token;
4315 and three, error reporting can point to the actual character rather than
4316 at or prior to it. The first two things could be resolved by providing
4317 alternate functions fairly easy, thus allowing FORMAT handling to expect
4318 both lexers to generate NAME tokens instead of NAMES (with otherwise minor
4319 changes to FORMAT parsing), but the third, error reporting, would suffer,
4320 and when one makes mistakes in a FORMAT, believe me, one wants a pointer
4321 to exactly where the compilers thinks the problem is, to even begin to get
4322 a handle on it. So there. */
4325 ffelex_set_names_pure (bool f
)
4327 ffelex_names_pure_
= f
;
4331 /* ffelex_splice_tokens -- Splice off and send tokens from a NAMES
4333 return (ffelexHandler) ffelex_splice_tokens(first_handler,master_token,
4336 Returns first_handler if start_char_index chars into master_token (which
4337 must be a NAMES token) is '\0'. Else, creates a subtoken from that
4338 char, either NUMBER (if it is a digit), a NAME (if a valid firstnamechar),
4339 an UNDERSCORE (if an underscore), or DOLLAR (if a dollar sign)
4340 and sends it to first_handler. If anything other than NAME is sent, the
4341 character at the end of it in the master token is examined to see if it
4342 begins a NAME, NUMBER, UNDERSCORE, or DOLLAR, and, if so,
4343 the handler returned by first_handler is invoked with that token, and
4344 this process is repeated until the end of the master token or a NAME
4345 token is reached. */
4348 ffelex_splice_tokens (ffelexHandler first
, ffelexToken master
,
4349 ffeTokenLength start
)
4355 p
= ffelex_token_text (master
) + (i
= start
);
4361 t
= ffelex_token_number_from_names (master
, i
);
4362 p
+= ffelex_token_length (t
);
4363 i
+= ffelex_token_length (t
);
4365 else if (ffesrc_is_name_init (*p
))
4367 t
= ffelex_token_name_from_names (master
, i
, 0);
4368 p
+= ffelex_token_length (t
);
4369 i
+= ffelex_token_length (t
);
4373 t
= ffelex_token_dollar_from_names (master
, i
);
4379 t
= ffelex_token_uscore_from_names (master
, i
);
4385 assert ("not a valid NAMES character" == NULL
);
4388 assert (first
!= NULL
);
4389 first
= (ffelexHandler
) (*first
) (t
);
4390 ffelex_token_kill (t
);
4396 /* ffelex_swallow_tokens -- Eat all tokens delivered to me
4398 return ffelex_swallow_tokens;
4400 Return this handler when you don't want to look at any more tokens in the
4401 statement because you've encountered an unrecoverable error in the
4405 ffelex_swallow_tokens (ffelexToken t
, ffelexHandler handler
)
4407 assert (handler
!= NULL
);
4409 if ((t
!= NULL
) && ((ffelex_token_type (t
) == FFELEX_typeEOS
)
4410 || (ffelex_token_type (t
) == FFELEX_typeSEMICOLON
)))
4411 return (ffelexHandler
) (*handler
) (t
);
4413 ffelex_eos_handler_
= handler
;
4414 return (ffelexHandler
) ffelex_swallow_tokens_
;
4417 /* ffelex_token_dollar_from_names -- Return a dollar from within a names token
4420 t = ffelex_token_dollar_from_names(t,6);
4422 It's as if you made a new token of dollar type having the dollar
4423 at, in the example above, the sixth character of the NAMES token. */
4426 ffelex_token_dollar_from_names (ffelexToken t
, ffeTokenLength start
)
4431 assert (ffelex_token_type (t
) == FFELEX_typeNAMES
);
4432 assert (start
< t
->length
);
4433 assert (t
->text
[start
] == '$');
4435 /* Now make the token. */
4437 nt
= ffelex_token_new_ ();
4438 nt
->type
= FFELEX_typeDOLLAR
;
4441 ffewhere_set_from_track (&nt
->where_line
, &nt
->where_col
, t
->where_line
,
4442 t
->where_col
, t
->wheretrack
, start
);
4447 /* ffelex_token_kill -- Decrement use count for token, kill if no uses left
4450 ffelex_token_kill(t);
4452 Complements a call to ffelex_token_use or ffelex_token_new_.... */
4455 ffelex_token_kill (ffelexToken t
)
4459 assert (t
->uses
> 0);
4464 --ffelex_total_tokens_
;
4466 if (t
->type
== FFELEX_typeNAMES
)
4467 ffewhere_track_kill (t
->where_line
, t
->where_col
,
4468 t
->wheretrack
, t
->length
);
4469 ffewhere_line_kill (t
->where_line
);
4470 ffewhere_column_kill (t
->where_col
);
4471 if (t
->text
!= NULL
)
4472 malloc_kill_ksr (malloc_pool_image (), t
->text
, t
->size
+ 1);
4473 malloc_kill_ks (malloc_pool_image (), t
, sizeof (*t
));
4476 /* Make a new NAME token that is a substring of a NAMES token. */
4479 ffelex_token_name_from_names (ffelexToken t
, ffeTokenLength start
,
4485 assert (ffelex_token_type (t
) == FFELEX_typeNAMES
);
4486 assert (start
< t
->length
);
4488 len
= t
->length
- start
;
4492 assert ((start
+ len
) <= t
->length
);
4494 assert (ffelex_is_firstnamechar ((unsigned char)(t
->text
[start
])));
4496 nt
= ffelex_token_new_ ();
4497 nt
->type
= FFELEX_typeNAME
;
4498 nt
->size
= len
; /* Assume nobody's gonna fiddle with token
4502 ffewhere_set_from_track (&nt
->where_line
, &nt
->where_col
, t
->where_line
,
4503 t
->where_col
, t
->wheretrack
, start
);
4504 nt
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4506 strncpy (nt
->text
, t
->text
+ start
, len
);
4507 nt
->text
[len
] = '\0';
4511 /* Make a new NAMES token that is a substring of another NAMES token. */
4514 ffelex_token_names_from_names (ffelexToken t
, ffeTokenLength start
,
4520 assert (ffelex_token_type (t
) == FFELEX_typeNAMES
);
4521 assert (start
< t
->length
);
4523 len
= t
->length
- start
;
4527 assert ((start
+ len
) <= t
->length
);
4529 assert (ffelex_is_firstnamechar ((unsigned char)(t
->text
[start
])));
4531 nt
= ffelex_token_new_ ();
4532 nt
->type
= FFELEX_typeNAMES
;
4533 nt
->size
= len
; /* Assume nobody's gonna fiddle with token
4537 ffewhere_set_from_track (&nt
->where_line
, &nt
->where_col
, t
->where_line
,
4538 t
->where_col
, t
->wheretrack
, start
);
4539 ffewhere_track_copy (nt
->wheretrack
, t
->wheretrack
, start
, len
);
4540 nt
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4542 strncpy (nt
->text
, t
->text
+ start
, len
);
4543 nt
->text
[len
] = '\0';
4547 /* Make a new CHARACTER token. */
4550 ffelex_token_new_character (const char *s
, ffewhereLine l
, ffewhereColumn c
)
4554 t
= ffelex_token_new_ ();
4555 t
->type
= FFELEX_typeCHARACTER
;
4556 t
->length
= t
->size
= strlen (s
); /* Assume it won't get bigger. */
4558 t
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4560 strcpy (t
->text
, s
);
4561 t
->where_line
= ffewhere_line_use (l
);
4562 t
->where_col
= ffewhere_column_new (c
);
4566 /* Make a new EOF token right after end of file. */
4569 ffelex_token_new_eof ()
4573 t
= ffelex_token_new_ ();
4574 t
->type
= FFELEX_typeEOF
;
4577 t
->where_line
= ffewhere_line_new (ffelex_linecount_current_
);
4578 t
->where_col
= ffewhere_column_new (1);
4582 /* Make a new NAME token. */
4585 ffelex_token_new_name (const char *s
, ffewhereLine l
, ffewhereColumn c
)
4589 assert (ffelex_is_firstnamechar ((unsigned char)*s
));
4591 t
= ffelex_token_new_ ();
4592 t
->type
= FFELEX_typeNAME
;
4593 t
->length
= t
->size
= strlen (s
); /* Assume it won't get bigger. */
4595 t
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4597 strcpy (t
->text
, s
);
4598 t
->where_line
= ffewhere_line_use (l
);
4599 t
->where_col
= ffewhere_column_new (c
);
4603 /* Make a new NAMES token. */
4606 ffelex_token_new_names (const char *s
, ffewhereLine l
, ffewhereColumn c
)
4610 assert (ffelex_is_firstnamechar ((unsigned char)*s
));
4612 t
= ffelex_token_new_ ();
4613 t
->type
= FFELEX_typeNAMES
;
4614 t
->length
= t
->size
= strlen (s
); /* Assume it won't get bigger. */
4616 t
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4618 strcpy (t
->text
, s
);
4619 t
->where_line
= ffewhere_line_use (l
);
4620 t
->where_col
= ffewhere_column_new (c
);
4621 ffewhere_track_clear (t
->wheretrack
, t
->length
); /* Assume contiguous
4626 /* Make a new NUMBER token.
4628 The first character of the string must be a digit, and only the digits
4629 are copied into the new number. So this may be used to easily extract
4630 a NUMBER token from within any text string. Then the length of the
4631 resulting token may be used to calculate where the digits stopped
4632 in the original string. */
4635 ffelex_token_new_number (const char *s
, ffewhereLine l
, ffewhereColumn c
)
4640 /* How long is the string of decimal digits at s? */
4642 len
= strspn (s
, "0123456789");
4644 /* Make sure there is at least one digit. */
4648 /* Now make the token. */
4650 t
= ffelex_token_new_ ();
4651 t
->type
= FFELEX_typeNUMBER
;
4652 t
->length
= t
->size
= len
; /* Assume it won't get bigger. */
4654 t
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4656 strncpy (t
->text
, s
, len
);
4657 t
->text
[len
] = '\0';
4658 t
->where_line
= ffewhere_line_use (l
);
4659 t
->where_col
= ffewhere_column_new (c
);
4663 /* Make a new token of any type that doesn't contain text. A private
4664 function that is used by public macros in the interface file. */
4667 ffelex_token_new_simple_ (ffelexType type
, ffewhereLine l
, ffewhereColumn c
)
4671 t
= ffelex_token_new_ ();
4675 t
->where_line
= ffewhere_line_use (l
);
4676 t
->where_col
= ffewhere_column_new (c
);
4680 /* Make a new NUMBER token from an existing NAMES token.
4682 Like ffelex_token_new_number, this function calculates the length
4683 of the digit string itself. */
4686 ffelex_token_number_from_names (ffelexToken t
, ffeTokenLength start
)
4692 assert (ffelex_token_type (t
) == FFELEX_typeNAMES
);
4693 assert (start
< t
->length
);
4695 /* How long is the string of decimal digits at s? */
4697 len
= strspn (t
->text
+ start
, "0123456789");
4699 /* Make sure there is at least one digit. */
4703 /* Now make the token. */
4705 nt
= ffelex_token_new_ ();
4706 nt
->type
= FFELEX_typeNUMBER
;
4707 nt
->size
= len
; /* Assume nobody's gonna fiddle with token
4711 ffewhere_set_from_track (&nt
->where_line
, &nt
->where_col
, t
->where_line
,
4712 t
->where_col
, t
->wheretrack
, start
);
4713 nt
->text
= malloc_new_ksr (malloc_pool_image (), "FFELEX token text",
4715 strncpy (nt
->text
, t
->text
+ start
, len
);
4716 nt
->text
[len
] = '\0';
4720 /* Make a new UNDERSCORE token from a NAMES token. */
4723 ffelex_token_uscore_from_names (ffelexToken t
, ffeTokenLength start
)
4728 assert (ffelex_token_type (t
) == FFELEX_typeNAMES
);
4729 assert (start
< t
->length
);
4730 assert (t
->text
[start
] == '_');
4732 /* Now make the token. */
4734 nt
= ffelex_token_new_ ();
4735 nt
->type
= FFELEX_typeUNDERSCORE
;
4737 ffewhere_set_from_track (&nt
->where_line
, &nt
->where_col
, t
->where_line
,
4738 t
->where_col
, t
->wheretrack
, start
);
4743 /* ffelex_token_use -- Return another instance of a token
4746 t = ffelex_token_use(t);
4748 In a sense, the new token is a copy of the old, though it might be the
4749 same with just a new use count.
4751 We use the use count method (easy). */
4754 ffelex_token_use (ffelexToken t
)
4757 assert ("_token_use: null token" == NULL
);