13 #include "keyword_list.h"
14 /*------------------------------------------------------------------------------------------------*/
15 #include "namespace/globals.h"
16 #include "namespace/input.h"
17 #include "namespace/input.c"
18 #include "namespace/keyword.h"
19 #include "namespace/getline.h"
20 #include "namespace/options.h"
21 #include "namespace/keyword.h"
22 #include "namespace/keyword_list.h"
23 /*------------------------------------------------------------------------------------------------*/
25 /*{{{ pretty_input_file_name */
26 /* returns a pretty representation of the input file name, for error and warning messages */
27 static u8
*pretty_input_file_name(void)
31 fn
= options
->input_file_name
;
35 return "(standard input)";
37 /*{{{ is_define_declaration */
39 * Tests if the given line contains a "%define DECL ARG" declaration. If yes, it sets *ARGP to the
40 * argument, and returns true. Otherwise, it returns false.
42 static bool is_define_declaration(u8
*line
, u8
*line_end
, u32 lineno
, u8
*decl
, u8
**argp
)
56 if (!(line
< line_end
))
63 if (!(line
< line_end
&& (*line
== ' ' || *line
== '\t')))
68 if (line
>= line_end
|| !(*line
== ' ' || *line
== '\t'))
77 if (!(line
< line_end
))
79 if (!(*line
== *d
|| (*d
== '-' && *line
== '_')))
85 && ((*line
>= 'A' && *line
<= 'Z')
86 || (*line
>= 'a' && *line
<= 'z')
87 || *line
== '-' || *line
== '_'))
91 if (!(line
< line_end
&& (*line
== ' ' || *line
== '\t'))) {
92 fprintf (stderr
, "%s:%u: missing argument in %%define %s ARG declaration.\n", pretty_input_file_name(), lineno
, decl
);
97 if (line
>= line_end
|| !(*line
== ' ' || *line
== '\t'))
100 /* The next word is the argument */
101 arg
= calloc(line_end
- line
+ 1, sizeof(u8
));
104 if (line
>= line_end
|| (*line
== ' ' || *line
== '\t' || *line
== '\n'))
109 /* skip whitespace */
111 if (line
>= line_end
|| !(*line
== ' ' || *line
== '\t'))
115 /* expect end of line */
116 if (line
< line_end
&& *line
!= '\n') {
117 fprintf(stderr
, "%s:%u: junk after declaration\n", pretty_input_file_name(), lineno
);
123 /*{{{ is_declaration */
124 /* returns true if the given line contains a "%DECL" declaration */
125 static bool is_declaration(u8
*line
, u8
*line_end
, u32 lineno
, u8
*decl
)
135 if (!(line
< line_end
))
137 if (!(*line
== *d
|| (*d
== '-' && *line
== '_')))
143 && ((*line
>= 'A' && *line
<= 'Z')
144 || (*line
>= 'a' && *line
<= 'z')
145 || *line
== '-' || *line
== '_'))
147 /* OK, found DECL. */
148 /* skip whitespace */
150 if (line
>= line_end
|| !(*line
== ' ' || *line
== '\t'))
154 /* expect end of line */
155 if (line
< line_end
&& *line
!= '\n') {
156 fprintf(stderr
, "%s:%u: junk after declaration\n", pretty_input_file_name(), lineno
);
161 /*{{{ is_declaration_with_arg */
163 * Tests if the given line contains a "%DECL=ARG" declaration. If yes, it sets *ARGP to the
164 * argument, and returns true. Otherwise, it returns false
166 static bool is_declaration_with_arg(u8
*line
, u8
*line_end
, u32 lineno
, u8
*decl
, u8
**argp
)
179 if (!(line
< line_end
))
181 if (!(*line
== *d
|| (*d
== '-' && *line
== '_')))
187 && ((*line
>= 'A' && *line
<= 'Z')
188 || (*line
>= 'a' && *line
<= 'z')
189 || *line
== '-' || *line
== '_'))
193 if (!(line
< line_end
&& *line
== '=')) {
194 fprintf(stderr
, "%s:%u: missing argument in %%%s=ARG declaration.\n", pretty_input_file_name(), lineno
, decl
);
198 /* the next word is the argument */
199 arg
= calloc(line_end
- line
+ 1, sizeof(u8
));
202 if (line
>= line_end
|| (*line
== ' ' || *line
== '\t' || *line
== '\n'))
207 /* skip whitespace */
209 if (line
>= line_end
|| !(*line
== ' ' || *line
== '\t'))
213 /* expect end of line */
214 if (line
< line_end
&& *line
!= '\n') {
215 fprintf(stderr
, "%s:%u: junk after declaration\n", pretty_input_file_name(), lineno
);
221 /*}}} local -- END */
223 static struct Input
*input_new(FILE *stream
)
227 t
= calloc(1, sizeof(*t
));
232 static void input_del(struct Input
*t
)
234 free(t
->return_type
);
236 free(t
->struct_decl
);
239 /*{{{ input_read_input */
240 static void input_read(struct Input
*t
)
243 The input file has the following structure:
249 Since the DECLARATIONS and the ADDITIONAL_CODE sections are optional,
250 we have to read the entire file in the case there is only one %%
251 separator line, in order to determine whether the structure is
259 When the option -t is given or when the first section contains
260 declaration lines starting with %, we go for the first interpretation,
261 otherwise for the second interpretation. }}}*/
268 u8
*declarations_end
;
275 input_length
= get_delim(&input
, &input_size
, EOF
, t
->stream
);
276 if (input_length
< 0) {
277 if (ferror(t
->stream
))
278 fprintf(stderr
, "%s: error while reading input file\n", pretty_input_file_name());
280 fprintf(stderr
, "%s: The input file is empty!\n", pretty_input_file_name());
284 * Convert CR/LF line terminators (Windows) to LF line terminators (Unix). GCC 3.3 and
285 * newer support CR/LF line terminators in C sources on Unix, so we do the same.
286 * The so-called "text mode" in stdio on Windows translates CR/LF to \n automatically, but
287 * here we also need this conversion on Unix. As a side effect, on Windows we also parse
288 * CR/CR/LF into a single \n, but this is not a problem
296 p_end
= input
+ input_length
;
297 /* converting the initial segment without CRs is a no-op */
299 if (p
>= p_end
|| *p
== '\r')
303 /* then start the conversion for real */
308 if (p
[0] == '\r' && p
+ 1 < p_end
&& p
[1] == '\n')
312 input_length
= (s32
)(q
- input
);
315 * We use input_end as a limit, in order to cope with NUL bytes in the input. But note that
316 * one trailing NUL byte has been added after input_end, for convenience
318 input_end
= input
+ input_length
;
319 /* break up the input into the three sections */
322 u32 separator_lineno
[2];
324 bool has_declarations
;
328 separator_lineno
[0] = 0;
329 separator_lineno
[1] = 0;
340 if (p
[0] == '%' && p
[1] == '%') {
341 separator
[separators
] = p
;
342 separator_lineno
[separators
] = lineno
;
348 p
= (u8
*)memchr(p
, '\n', input_end
- p
);
355 if (separators
== 1) {
357 has_declarations
= true;
361 has_declarations
= false;
364 if (p
>= separator
[0])
367 has_declarations
= true;
370 p
= (u8
*)memchr(p
, '\n',
379 has_declarations
= (separators
> 0);
380 if (has_declarations
) {
384 declarations
= input
;
385 declarations_end
= separator
[0];
386 /* give a warning if the separator line is nonempty */
387 nonempty_line
= false;
388 p
= declarations_end
+ 2;
396 if (!(*p
== ' ' || *p
== '\t'))
397 nonempty_line
= true;
401 fprintf(stderr
, "%s:%u: warning: junk after %%%% is ignored\n", pretty_input_file_name(), separator_lineno
[0]);
403 keywords_lineno
= separator_lineno
[0] + 1;
406 declarations_end
= 0;
410 if (separators
> (has_declarations
? 1 : 0)) {
411 keywords_end
= separator
[separators
- 1];
412 t
->verbatim_code
= separator
[separators
- 1] + 2;
413 t
->verbatim_code_end
= input_end
;
414 t
->verbatim_code_lineno
= separator_lineno
[separators
- 1];
416 keywords_end
= input_end
;
417 t
->verbatim_code
= 0;
418 t
->verbatim_code_end
= 0;
419 t
->verbatim_code_lineno
= 0;
422 /* parse the declarations section */
423 t
->verbatim_declarations
= 0;
424 t
->verbatim_declarations_end
= 0;
425 t
->verbatim_declarations_lineno
= 0;
427 t
->struct_decl_lineno
= 0;
433 u32
*struct_decl_linenos
;
434 u32 struct_decl_linecount
;
439 struct_decl_linenos
= NULL
;
440 struct_decl_linecount
= 0;
446 if (line
>= declarations_end
)
448 line_end
= (u8
*)memchr(line
, '\n', declarations_end
- line
);
452 line_end
= declarations_end
;
455 if (line
[1] == '{') {
457 if (t
->verbatim_declarations
!= 0) {
458 fprintf(stderr
, "%s:%u:\n%s:%u:only one %%{...%%} section is allowed\n", pretty_input_file_name(), t
->verbatim_declarations_lineno
, pretty_input_file_name(), lineno
);
461 t
->verbatim_declarations
= line
+ 2;
462 t
->verbatim_declarations_lineno
= lineno
;
463 } else if (line
[1] == '}') {
467 if (t
->verbatim_declarations
== 0) {
468 fprintf(stderr
, "%s:%u: %%} outside of %%{...%%} section\n", pretty_input_file_name(), lineno
);
471 if (t
->verbatim_declarations_end
!= 0) {
472 fprintf(stderr
, "%s:%u: %%{...%%} section already closed\n", pretty_input_file_name(), lineno
);
475 t
->verbatim_declarations_end
= line
;
476 /* give a warning if the rest of the line is nonempty */
477 nonempty_line
= false;
486 if (!(*q
== ' ' || *q
== '\t'))
487 nonempty_line
= true;
491 fprintf(stderr
, "%s:%u: warning: junk after %%} is ignored\n", pretty_input_file_name(), lineno
);
492 } else if (t
->verbatim_declarations
!= 0
493 && t
->verbatim_declarations_end
== 0) {
494 fprintf (stderr
, "%s:%u: warning: %% directives are ignored" " inside the %%{...%%} section\n", pretty_input_file_name(), lineno
);
498 #define OPT_SET(x) options->option_word |= OPTS_##x
499 if (is_declaration_with_arg(line
, line_end
, lineno
, "delimiters", &arg
))
500 opts_set_delimiters(options
, arg
);
503 if (is_declaration(line
, line_end
, lineno
, "struct-type"))
507 if (is_declaration(line
, line_end
, lineno
, "ignore-case"))
511 if (is_declaration_with_arg(line
, line_end
, lineno
, "language", &arg
))
512 opts_set_language(options
, arg
);
515 if (is_define_declaration(line
, line_end
, lineno
, "slot-name", &arg
))
516 opts_set_slot_name(options
, arg
);
519 if (is_define_declaration(line
, line_end
, lineno
, "initializer-suffix", &arg
))
520 opts_set_initializer_suffix(options
, arg
);
523 if (is_define_declaration(line
, line_end
, lineno
, "hash-function-name", &arg
))
524 opts_set_hash_name(options
, arg
);
527 if (is_define_declaration(line
, line_end
, lineno
, "lookup-function-name", &arg
))
528 opts_set_function_name(options
, arg
);
531 if (is_define_declaration(line
, line_end
, lineno
, "class-name", &arg
))
532 opts_set_class_name(options
, arg
);
535 if (is_declaration(line
, line_end
, lineno
, "7bit"))
539 if (is_declaration(line
, line_end
, lineno
, "compare-lengths"))
543 if (is_declaration (line
, line_end
, lineno
, "compare-strncmp"))
547 if (is_declaration(line
, line_end
, lineno
, "readonly-tables"))
551 if (is_declaration(line
, line_end
, lineno
, "enum"))
555 if (is_declaration(line
, line_end
, lineno
, "includes"))
559 if (is_declaration(line
, line_end
, lineno
, "global-table"))
563 if (is_declaration(line
, line_end
, lineno
, "pic"))
567 if (is_define_declaration(line
, line_end
, lineno
, "string-pool-name", &arg
))
568 opts_set_stringpool_name(options
, arg
);
571 if (is_declaration(line
, line_end
, lineno
, "null-strings"))
572 OPT_SET(NULLSTRINGS
);
575 if (is_define_declaration(line
, line_end
, lineno
, "constants-prefix", &arg
))
576 opts_set_constants_prefix(options
, arg
);
579 if (is_define_declaration(line
, line_end
, lineno
, "word-array-name", &arg
))
580 opts_set_wordlist_name(options
, arg
);
583 if (is_define_declaration(line
, line_end
, lineno
, "length-table-name", &arg
))
584 opts_set_lengthtable_name(options
, arg
);
587 if (is_declaration_with_arg(line
, line_end
, lineno
, "switch", &arg
)) {
588 opts_set_total_switches(options
, atoi(arg
));
589 if (options
->total_switches
<= 0) {
590 fprintf (stderr
, "%s:%u: number of switches %s must be a positive number\n", pretty_input_file_name(), lineno
, arg
);
596 if (is_declaration(line
, line_end
, lineno
, "omit-struct-type"))
599 fprintf (stderr
, "%s:%u: unrecognized %% directive\n", pretty_input_file_name(), lineno
);
604 } else if (!(t
->verbatim_declarations
!= 0
605 && t
->verbatim_declarations_end
== 0)) {
606 /* append the line to struct_decl */
611 u32
*new_struct_decl_linenos
;
613 old_len
= (struct_decl
? strlen(struct_decl
) : 0);
614 line_len
= line_end
- line
;
615 new_len
= old_len
+ line_len
+ 1;
616 new_struct_decl
= calloc(new_len
, sizeof(u8
));
618 memcpy(new_struct_decl
, struct_decl
, old_len
);
619 memcpy(new_struct_decl
+ old_len
, line
, line_len
);
620 new_struct_decl
[old_len
+ line_len
] = '\0';
621 if (struct_decl
!= 0)
623 struct_decl
= new_struct_decl
;
624 /* append the lineno to struct_decl_linenos */
625 new_struct_decl_linenos
= calloc(struct_decl_linecount
+ 1,
627 if (struct_decl_linecount
> 0)
628 memcpy(new_struct_decl_linenos
, struct_decl_linenos
,
629 struct_decl_linecount
* sizeof(u32
));
630 new_struct_decl_linenos
[struct_decl_linecount
] = lineno
;
631 if (struct_decl_linenos
)
632 free(struct_decl_linenos
);
633 struct_decl_linenos
= new_struct_decl_linenos
;
634 /* increment struct_decl_linecount */
635 ++struct_decl_linecount
;
640 if (t
->verbatim_declarations
!= 0 && t
->verbatim_declarations_end
== 0) {
641 fprintf(stderr
, "%s:%u: unterminated %%{ section\n", pretty_input_file_name(), t
->verbatim_declarations_lineno
);
644 /* determine _struct_decl, _return_type, _struct_tag */
647 u32 struct_tag_length
;
651 if (struct_decl
!= 0) {
652 /* drop leading whitespace and comments */
658 l
= struct_decl_linenos
;
660 if (p
[0] == ' ' || p
[0] == '\t') {
671 /* skip over ANSI C style comment */
688 /* skip over ISO C99 or C++ style comment */
705 if (p
!= struct_decl
) {
710 new_struct_decl
= calloc(len
+ 1, sizeof(u8
));
711 memcpy(new_struct_decl
, p
, len
+ 1);
713 struct_decl
= new_struct_decl
;
715 t
->struct_decl_lineno
= *l
;
717 /* drop trailing whitespace */
718 p
= struct_decl
+ strlen(struct_decl
);
720 if (p
<= struct_decl
)
722 if (p
[-1] == '\n' || p
[-1] == ' ' || p
[-1] == '\t')
728 if (struct_decl
== 0 || struct_decl
[0] == '\0') {
729 fprintf (stderr
, "%s: missing struct declaration for option --struct-type\n", pretty_input_file_name());
733 /* ensure trailing semicolon */
736 old_len
= strlen(struct_decl
);
737 if (struct_decl
[old_len
- 1] != ';') {
740 new_struct_decl
= calloc(old_len
+ 2, sizeof(u8
));
741 memcpy(new_struct_decl
, struct_decl
, old_len
);
742 new_struct_decl
[old_len
] = ';';
743 new_struct_decl
[old_len
+ 1] = '\0';
745 struct_decl
= new_struct_decl
;
748 /* set _struct_decl to the entire declaration */
749 t
->struct_decl
= struct_decl
;
750 /* set _struct_tag to the naked "struct something" */
753 if (*p
== 0 || *p
== '{' || *p
== ';' || *p
== '\n')
758 if (p
<= struct_decl
)
760 if (p
[-1] == '\n' || p
[-1] == ' ' || p
[-1] == '\t')
765 struct_tag_length
= p
- struct_decl
;
766 struct_tag
= calloc(struct_tag_length
+ 1, sizeof(u8
));
767 memcpy(struct_tag
, struct_decl
, struct_tag_length
);
768 struct_tag
[struct_tag_length
] = '\0';
769 t
->struct_tag
= struct_tag
;
771 * The return type of the lookup function is "struct something *". No
772 * "const" here, because if !option[CONST], some user code might want to
773 * modify the structure.
775 return_type
= calloc(struct_tag_length
+ 3, sizeof(u8
));
776 memcpy(return_type
, struct_decl
, struct_tag_length
);
777 return_type
[struct_tag_length
] = ' ';
778 return_type
[struct_tag_length
+ 1] = '*';
779 return_type
[struct_tag_length
+ 2] = '\0';
780 t
->return_type
= return_type
;
782 if (struct_decl_linenos
!= 0)
783 free(struct_decl_linenos
);
785 /* parse the keywords section */
787 struct Keyword_List
**list_tail
;
790 bool charset_dependent
;
793 list_tail
= &t
->head
;
794 delimiters
= options
->delimiters
;
795 lineno
= keywords_lineno
;
796 charset_dependent
= false;
801 if (line
>= keywords_end
)
803 line_end
= memchr(line
, '\n', keywords_end
- line
);
807 line_end
= keywords_end
;
810 else if (line
[0] == '%') {
811 fprintf(stderr
, "%s:%u: declarations are not allowed in the keywords section.\nTo declare a keyword starting with %%, enclose it in double-quotes.\n", pretty_input_file_name(), lineno
);
814 /* an input line carrying a keyword */
818 struct Keyword
*new_kw
;
820 if (line
[0] == '"') {
821 /* parse a string in ANSI C syntax */
825 kp
= calloc(line_end
- line
, sizeof(u8
));
831 if (lp
== line_end
) {
832 fprintf(stderr
, "%s:%u: unterminated string\n", pretty_input_file_name(), lineno
);
839 case '0': case '1': case '2': case '3':
840 case '4': case '5': case '6': case '7':{
847 if (count
>= 3 || *lp
== '0' || *lp
> '7')
849 code
= (code
<< 3) + (*lp
- '0');
853 if (code
> UCHAR_MAX
)
854 fprintf(stderr
, "%s:%u: octal escape out of range\n", pretty_input_file_name(), lineno
);
865 if (!(*lp
>= '0' && *lp
<= '9') || !(*lp
>= 'A' && *lp
<= 'F') || !(*lp
>= 'a' && *lp
<= 'f'))
868 + (*lp
>= 'A' && *lp
<= 'F'
870 *lp
>= 'a' && *lp
<= 'f'
877 fprintf(stderr
, "%s:%u: hexadecimal escape without any hex digits\n", pretty_input_file_name(), lineno
);
878 if (code
> UCHAR_MAX
)
879 fprintf(stderr
, "%s:%u: hexadecimal escape out of range\n", pretty_input_file_name(), lineno
);
882 case '\\': case '\'': case '"':
885 charset_dependent
= true;
890 charset_dependent
= true;
895 charset_dependent
= true;
900 charset_dependent
= true;
905 charset_dependent
= true;
910 charset_dependent
= true;
915 charset_dependent
= true;
920 charset_dependent
= true;
923 fprintf(stderr
, "%s:%u: invalid escape sequence in string\n", pretty_input_file_name(), lineno
);
931 charset_dependent
= true;
936 if (lp
< line_end
&& *lp
!= '\n') {
937 if (strchr(delimiters
, *lp
) == 0) {
938 fprintf(stderr
, "%s:%u: string not followed by delimiter\n", pretty_input_file_name(), lineno
);
943 keyword_length
= kp
- keyword
;
947 line_rest
= calloc(line_end
- lp
+ 1, sizeof(u8
));
948 memcpy(line_rest
, lp
, line_end
- lp
);
949 line_rest
[line_end
- lp
- (line_end
> lp
&& line_end
[-1] == '\n' ? 1 : 0)] = '\0';
954 /* Not a string. Look for the delimiter. */
959 if (!(lp
< line_end
&& *lp
!= '\n')) {
961 keyword_length
= lp
- line
;
965 if (strchr(delimiters
, *lp
) != 0) {
967 keyword_length
= lp
- line
;
969 if ((cgperf_options
->option_word
& OPTS_TYPE
) != 0) {
972 line_rest
= calloc(line_end
- lp
+ 1, sizeof(u8
));
973 memcpy(line_rest
, lp
, line_end
- lp
);
974 line_rest
[line_end
- lp
- (line_end
> lp
&& line_end
[-1] == '\n' ? 1 : 0)] = '\0';
982 if (keyword_length
> 0)
983 charset_dependent
= true;
985 /* allocate Keyword and add it to the list */
986 new_kw
= kw_new(keyword
, keyword_length
, rest
, lineno
);
987 *list_tail
= kwl_new(new_kw
);
988 list_tail
= &(*list_tail
)->next
;
995 fprintf (stderr
, "%s: No keywords in input file!\n", pretty_input_file_name());
998 t
->charset_dependent
= charset_dependent
;
1000 /* to be freed in the destructor */
1002 t
->input_end
= input_end
;
1004 /*------------------------------------------------------------------------------------------------*/
1006 #include "namespace/globals.h"
1007 #include "namespace/input.h"
1008 #include "namespace/input.c"
1009 #include "namespace/keyword.h"
1010 #include "namespace/getline.h"
1011 #include "namespace/options.h"
1012 #include "namespace/keyword.h"
1013 #include "namespace/keyword_list.h"
1015 /*------------------------------------------------------------------------------------------------*/