1 /* xgettext sh backend.
2 Copyright (C) 2003, 2005-2009 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
39 #define _(s) gettext(s)
41 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
44 /* The sh syntax is defined in POSIX:2001, see
45 http://www.opengroup.org/onlinepubs/007904975/utilities/xcu_chap02.html
47 - Input is broken into words, which are then subject to
48 - tilde expansion ~...
49 - command substitution `...`
50 - variable substitution $var
51 - arithmetic substitution $((...))
52 - field splitting at whitespace (IFS)
53 - wildcard pattern expansion *?
55 - Strings are enclosed in "..."; command substitution, variable
56 substitution and arithmetic substitution are performed here as well.
57 - '...' is a string without substitutions.
58 - The list of resulting words is split into commands by semicolon and
60 - '#' at the beginning of a word introduces a comment until end of line.
61 The parser is implemented in bash-2.05b/parse.y. */
64 /* ====================== Keyword set customization. ====================== */
66 /* If true extract all strings. */
67 static bool extract_all = false;
69 static hash_table keywords;
70 static bool default_keywords = true;
81 x_sh_keyword (const char *name)
84 default_keywords = false;
88 struct callshape shape;
91 if (keywords.table == NULL)
92 hash_init (&keywords, 100);
94 split_keywordspec (name, &end, &shape);
96 /* The characters between name and end should form a valid C identifier.
97 A colon means an invalid parse in split_keywordspec(). */
98 colon = strchr (name, ':');
99 if (colon == NULL || colon >= end)
100 insert_keyword_callshape (&keywords, name, end - name, &shape);
104 /* Finish initializing the keywords hash table.
105 Called after argument processing, before each file is processed. */
109 if (default_keywords)
111 /* When adding new keywords here, also update the documentation in
113 x_sh_keyword ("gettext");
114 x_sh_keyword ("ngettext:1,2");
115 x_sh_keyword ("eval_gettext");
116 x_sh_keyword ("eval_ngettext:1,2");
117 default_keywords = false;
122 init_flag_table_sh ()
124 xgettext_record_flag ("gettext:1:pass-sh-format");
125 xgettext_record_flag ("ngettext:1:pass-sh-format");
126 xgettext_record_flag ("ngettext:2:pass-sh-format");
127 xgettext_record_flag ("eval_gettext:1:sh-format");
128 xgettext_record_flag ("eval_ngettext:1:sh-format");
129 xgettext_record_flag ("eval_ngettext:2:sh-format");
133 /* ======================== Reading of characters. ======================== */
135 /* Real filename, used in error messages about the input file. */
136 static const char *real_file_name;
138 /* Logical filename and line number, used to label the extracted messages. */
139 static char *logical_file_name;
140 static int line_number;
142 /* The input file stream. */
146 /* Fetch the next character from the input file. */
155 error (EXIT_FAILURE, errno, _("\
156 error while reading \"%s\""), real_file_name);
164 /* Put back the last fetched character, not EOF. */
174 /* Remove backslash followed by newline from the input stream. */
176 static int phase1_pushback[1];
177 static int phase1_pushback_length;
184 if (phase1_pushback_length)
186 c = phase1_pushback[--phase1_pushback_length];
206 /* Supports only one pushback character. */
208 phase1_ungetc (int c)
220 if (phase1_pushback_length == SIZEOF (phase1_pushback))
222 phase1_pushback[phase1_pushback_length++] = c;
228 /* ========================== Reading of tokens. ========================== */
231 /* A token consists of a sequence of characters. */
234 int allocated; /* number of allocated 'token_char's */
235 int charcount; /* number of used 'token_char's */
236 char *chars; /* the token's constituents */
239 /* Initialize a 'struct token'. */
241 init_token (struct token *tp)
244 tp->chars = XNMALLOC (tp->allocated, char);
248 /* Free the memory pointed to by a 'struct token'. */
250 free_token (struct token *tp)
255 /* Ensure there is enough room in the token for one more character. */
257 grow_token (struct token *tp)
259 if (tp->charcount == tp->allocated)
262 tp->chars = (char *) xrealloc (tp->chars, tp->allocated * sizeof (char));
266 /* Convert a struct token * to a char*. */
268 string_of_token (const struct token *tp)
274 str = XNMALLOC (n + 1, char);
275 memcpy (str, tp->chars, n);
281 /* ========================= Accumulating messages ========================= */
284 static message_list_ty *mlp;
287 /* ========================= Accumulating comments ========================= */
291 static size_t bufmax;
292 static size_t buflen;
303 if (buflen >= bufmax)
305 bufmax = 2 * bufmax + 10;
306 buffer = xrealloc (buffer, bufmax);
308 buffer[buflen++] = c;
315 && (buffer[buflen - 1] == ' ' || buffer[buflen - 1] == '\t'))
317 if (buflen >= bufmax)
319 bufmax = 2 * bufmax + 10;
320 buffer = xrealloc (buffer, bufmax);
322 buffer[buflen] = '\0';
323 savable_comment_add (buffer);
327 /* These are for tracking whether comments count as immediately before
329 static int last_comment_line;
330 static int last_non_comment_line;
333 /* ========================= Debackslashification ========================== */
335 /* This state tracks the effect of backquotes, double-quotes and single-quotes
336 on the parsing of backslashes. We make a single pass through the input
337 file, keeping the state up to date. This is much faster than accumulating
338 strings and processing them with explicit debackslashification, like the
341 /* The number of nested `...` or "`...`" constructs. Assumed to be <= 32. */
342 static unsigned int nested_backquotes;
344 /* A bit mask indicating which of the currently open `...` or "`...`"
345 constructs is with double-quotes: "`...`".
346 A bit value of 1 stands for "`...`", a bit value of 0 stands for `...`.
347 Bit position 0 designates the outermost backquotes nesting,
348 bit position 1 the second-outermost backquotes nesting,
350 bit position (nested_backquotes-1) the innermost backquotes nesting. */
351 static unsigned int open_doublequotes_mask;
353 /* A bit indicating whether a double-quote is currently open inside the
354 innermost backquotes nesting. */
355 static bool open_doublequote;
357 /* A bit indicating whether a single-quote is currently open inside the
358 innermost backquotes nesting. */
359 static bool open_singlequote;
361 /* The expected terminator of the currently open single-quote.
362 Usually '\'', but can be '"' for i18n-quotes. */
363 static char open_singlequote_terminator;
366 /* Functions to update the state. */
369 saw_opening_backquote ()
371 if (open_singlequote)
373 if (open_doublequote)
374 open_doublequotes_mask |= (unsigned int) 1 << nested_backquotes;
376 open_doublequote = false;
380 saw_closing_backquote ()
383 open_doublequote = (open_doublequotes_mask >> nested_backquotes) & 1;
384 open_doublequotes_mask &= ((unsigned int) 1 << nested_backquotes) - 1;
385 open_singlequote = false; /* just for safety */
389 saw_opening_doublequote ()
391 if (open_singlequote || open_doublequote)
393 open_doublequote = true;
397 saw_closing_doublequote ()
399 if (open_singlequote || !open_doublequote)
401 open_doublequote = false;
405 saw_opening_singlequote ()
407 if (open_doublequote || open_singlequote)
409 open_singlequote = true;
410 open_singlequote_terminator = '\'';
414 saw_closing_singlequote ()
416 if (open_doublequote || !open_singlequote)
418 open_singlequote = false;
422 /* ========================== Reading of commands ========================== */
424 /* We are only interested in constant strings. Other words need not to be
425 represented precisely. */
428 t_string, /* constant string */
429 t_other, /* other string */
430 t_separator, /* command separator: semicolon or newline */
431 t_redirect, /* redirection: one of < > >| << <<- >> <> <& >& */
432 t_backquote, /* closing '`' pseudo word */
433 t_paren, /* closing ')' pseudo word */
434 t_eof /* EOF marker */
440 struct token *token; /* for t_string */
441 int line_number_at_start; /* for t_string */
444 /* Free the memory pointed to by a 'struct word'. */
446 free_word (struct word *wp)
448 if (wp->type == t_string)
450 free_token (wp->token);
455 /* Convert a t_string token to a char*. */
457 string_of_word (const struct word *wp)
462 if (!(wp->type == t_string))
464 n = wp->token->charcount;
465 str = XNMALLOC (n + 1, char);
466 memcpy (str, wp->token->chars, n);
472 /* Whitespace recognition. */
475 is_whitespace (int c)
477 return (c == ' ' || c == '\t' || c == '\n');
480 /* Operator character recognition. */
483 is_operator_start (int c)
485 return (c == '|' || c == '&' || c == ';' || c == '<' || c == '>'
486 || c == '(' || c == ')');
490 /* Denotation of a quoted character.
491 The distinction between quoted and unquoted character is important only for
492 the special, whitespace and operator characters; it is irrelevant for
493 alphanumeric characters, '\\' and many others. */
494 #define QUOTED(c) (UCHAR_MAX + 1 + (c))
495 /* Values in the 'unsigned char' range are implicitly unquoted. Among these,
496 the following are important:
497 '"' opening or closing double quote
498 '\'' opening or closing single quote
499 '$' the unknown result of a dollar expansion
500 '`' does not occur - replaced with OPENING_BACKQUOTE or
503 #define OPENING_BACKQUOTE (2 * (UCHAR_MAX + 1) + '`')
504 #define CLOSING_BACKQUOTE (3 * (UCHAR_MAX + 1) + '`')
506 /* 2 characters of pushback are supported.
507 2 characters of pushback occur only when the first is an 'x'; in all
508 other cases only one character of pushback is needed. */
509 static int phase2_pushback[2];
510 static int phase2_pushback_length;
512 /* Return the next character, with backslashes removed.
513 The result is QUOTED(c) for some unsigned char c, if the next character
514 is escaped sufficiently often to make it a regular constituent character,
515 or simply an 'unsigned char' if it has its special meaning (of special,
516 whitespace or operator charcter), or OPENING_BACKQUOTE, CLOSING_BACKQUOTE,
518 It's the caller's responsibility to update the state. */
524 if (phase2_pushback_length)
526 c = phase2_pushback[--phase2_pushback_length];
536 return ((open_doublequote
537 || (open_singlequote && open_singlequote_terminator != c))
540 if (open_singlequote)
542 if (c == open_singlequote_terminator)
547 if (c == '"' || c == '$')
550 return (nested_backquotes > 0 ? CLOSING_BACKQUOTE : OPENING_BACKQUOTE);
554 /* Number of debackslahificication passes that are active at the
556 unsigned int debackslahify =
557 nested_backquotes + (open_singlequote ? 0 : 1);
558 /* Normal number of backslashes that yield a single backslash in the
560 unsigned int expected_count =
561 (unsigned int) 1 << debackslahify;
562 /* Number of backslashes found. */
565 for (count = 1; count < expected_count; count++)
571 if (count == expected_count)
574 /* The count of backslashes is > 0 and < expected_count, therefore the
575 result depends on c, the first character after the backslashes.
576 Note: The formulas below don't necessarily have a logic; they were
577 empirically determined such that 1. the xgettext-30 test succeeds,
578 2. the behaviour for count == 0 would correspond to the one without
582 if (!open_singlequote && count > (expected_count >> 1))
588 return ((open_doublequote
589 || (open_singlequote && open_singlequote_terminator != c))
595 /* Each debackslahificication pass converts \\ to \ and \" to ";
596 passes corresponding to `...` drop a lone " whereas passes
597 corresponding to "`...`" leave it alone. Therefore, the
598 minimum number of backslashes needed to get one double-quote
599 in the end is open_doublequotes_mask + 1. */
600 if (open_singlequote)
602 if (count > open_doublequotes_mask)
608 return (open_singlequote_terminator != c ? QUOTED (c) : c);
612 if (count > open_doublequotes_mask)
615 /* Some of the count values <= open_doublequotes_mask are
616 actually invalid here, but we assume a syntactically
617 correct input file anyway. */
623 /* FIXME: This code looks fishy. */
624 if (count == expected_count - 1)
627 /* Some of the count values < expected_count - 1 are
628 actually invalid here, but we assume a syntactically
629 correct input file anyway. */
630 if (nested_backquotes > 0 && !open_singlequote
631 && count >= (expected_count >> 2))
632 return OPENING_BACKQUOTE;
634 return CLOSING_BACKQUOTE;
638 if (open_singlequote)
640 if (count >= (expected_count >> 1))
647 /* When not followed by a quoting character or backslash or dollar,
648 a backslash survives a debackslahificication pass unmodified.
649 Therefore each debackslahificication pass performs a
650 count := (count + 1) >> 1
651 operation. Therefore the minimum number of backslashes needed
652 to get one backslash in the end is (expected_count >> 1) + 1. */
653 if (open_doublequote || open_singlequote)
665 if (count > (expected_count >> 1))
678 return (open_singlequote || open_doublequote ? QUOTED (c) : c);
681 /* Supports 2 characters of pushback. */
683 phase2_ungetc (int c)
695 if (phase2_pushback_length == SIZEOF (phase2_pushback))
697 phase2_pushback[phase2_pushback_length++] = c;
703 /* Context lookup table. */
704 static flag_context_list_table_ty *flag_context_list_table;
707 /* Forward declaration of local functions. */
708 static enum word_type read_command_list (int looking_for,
709 flag_context_ty outer_context);
713 /* Read the next word.
714 'looking_for' denotes a parse terminator, either CLOSING_BACKQUOTE, ')'
717 read_word (struct word *wp, int looking_for, flag_context_ty context)
720 bool all_unquoted_digits;
727 /* Skip a comment up to end of line. */
728 last_comment_line = line_number;
733 if (c == EOF || c == '\n')
735 /* We skip all leading white space, but not EOLs. */
736 if (!(buflen == 0 && (c == ' ' || c == '\t')))
743 /* Comments assumed to be grouped with a message must immediately
744 precede it, with no non-whitespace token on a line between
746 if (last_non_comment_line > last_comment_line)
747 savable_comment_reset ();
748 wp->type = t_separator;
752 while (is_whitespace (c));
760 if (c == '<' || c == '>')
762 /* Recognize the redirection operators < > >| << <<- >> <> <& >&
763 But <( and >) are handled below, not here. */
764 int c2 = phase2_getc ();
767 if ((c == '<' ? c2 == '<' : c2 == '|') || c2 == '>' || c2 == '&')
769 if (c == '<' && c2 == '<')
771 int c3 = phase2_getc ();
778 wp->type = t_redirect;
785 if (looking_for == CLOSING_BACKQUOTE && c == CLOSING_BACKQUOTE)
787 saw_closing_backquote ();
788 wp->type = t_backquote;
789 last_non_comment_line = line_number;
793 if (looking_for == ')' && c == ')')
796 last_non_comment_line = line_number;
800 if (is_operator_start (c))
802 wp->type = (c == ';' ? t_separator : t_other);
807 wp->token = XMALLOC (struct token);
808 init_token (wp->token);
809 wp->line_number_at_start = line_number;
810 all_unquoted_digits = true;
812 for (;; c = phase2_getc ())
817 if (all_unquoted_digits && (c == '<' || c == '>'))
819 /* Recognize the redirection operators < > >| << <<- >> <> <& >&
820 prefixed with a nonempty sequence of unquoted digits. */
821 int c2 = phase2_getc ();
822 if ((c == '<' ? c2 == '<' : c2 == '|') || c2 == '>' || c2 == '&')
824 if (c == '<' && c2 == '<')
826 int c3 = phase2_getc ();
834 wp->type = t_redirect;
835 free_token (wp->token);
838 last_non_comment_line = line_number;
843 all_unquoted_digits = all_unquoted_digits && (c >= '0' && c <= '9');
849 /* An unquoted dollar indicates we are not inside '...'. */
850 if (open_singlequote)
852 /* After reading a dollar, we know that there is no pushed back
853 character from an earlier lookahead. */
854 if (phase2_pushback_length > 0)
856 /* Therefore we can use phase1 without interfering with phase2.
857 We need to recognize $( outside and inside double-quotes.
858 It would be incorrect to do
860 if (c2 == '(' || c2 == QUOTED ('('))
861 because that would also trigger for $\(. */
865 bool saved_open_doublequote;
870 /* The entire inner command or arithmetic expression is read
871 ignoring possible surrounding double-quotes. */
872 saved_open_doublequote = open_doublequote;
873 open_doublequote = false;
882 /* Arithmetic expression (Bash syntax). Skip until the
883 matching closing parenthesis. */
884 unsigned int depth = 2;
899 /* Command substitution (Bash syntax). */
901 read_command_list (')', context);
904 open_doublequote = saved_open_doublequote;
911 if (c2 == '\'' && !open_singlequote)
913 /* Bash builtin for string with ANSI-C escape sequences. */
914 saw_opening_singlequote ();
922 saw_closing_singlequote ();
938 /* Don't call saw_closing_singlequote ()
969 if ((c >= '0' && c <= '9')
970 || (c >= 'A' && c <= 'F')
971 || (c >= 'a' && c <= 'f'))
975 if (c >= '0' && c <= '9')
977 else if (c >= 'A' && c <= 'F')
979 else if (c >= 'a' && c <= 'f')
985 if ((c >= '0' && c <= '9')
986 || (c >= 'A' && c <= 'F')
987 || (c >= 'a' && c <= 'f'))
989 if (c >= '0' && c <= '9')
990 n = n * 16 + c - '0';
991 else if (c >= 'A' && c <= 'F')
992 n = n * 16 + 10 + c - 'A';
993 else if (c >= 'a' && c <= 'f')
994 n = n * 16 + 10 + c - 'a';
1006 phase2_ungetc ('x');
1011 case '0': case '1': case '2': case '3':
1012 case '4': case '5': case '6': case '7':
1017 if (c >= '0' && c <= '7')
1019 n = n * 8 + c - '0';
1022 if (c >= '0' && c <= '7')
1023 n = n * 8 + c - '0';
1035 if (wp->type == t_string)
1037 grow_token (wp->token);
1038 wp->token->chars[wp->token->charcount++] =
1042 /* The result is a literal string. Don't change wp->type. */
1045 else if (c2 == '"' && !open_doublequote)
1047 /* Bash builtin for internationalized string. */
1049 struct token string;
1051 saw_opening_singlequote ();
1052 open_singlequote_terminator = '"';
1053 pos.file_name = logical_file_name;
1054 pos.line_number = line_number;
1055 init_token (&string);
1063 saw_closing_singlequote ();
1066 grow_token (&string);
1067 string.chars[string.charcount++] = (unsigned char) c;
1069 remember_a_message (mlp, NULL, string_of_token (&string),
1070 context, &pos, NULL, savable_comment);
1071 free_token (&string);
1073 error_with_progname = false;
1074 error (0, 0, _("%s:%lu: warning: the syntax $\"...\" is deprecated due to security reasons; use eval_gettext instead"),
1075 pos.file_name, (unsigned long) pos.line_number);
1076 error_with_progname = true;
1078 /* The result at runtime is not constant. Therefore we
1090 if (!open_singlequote)
1092 /* Handle an opening single quote. */
1093 saw_opening_singlequote ();
1097 /* Handle a closing single quote. */
1098 saw_closing_singlequote ();
1105 if (open_singlequote && open_singlequote_terminator == '"')
1107 /* Handle a closing i18n quote. */
1108 saw_closing_singlequote ();
1110 else if (!open_doublequote)
1112 /* Handle an opening double quote. */
1113 saw_opening_doublequote ();
1117 /* Handle a closing double quote. */
1118 saw_closing_doublequote ();
1123 if (c == OPENING_BACKQUOTE)
1125 /* Handle an opening backquote. */
1126 saw_opening_backquote ();
1128 read_command_list (CLOSING_BACKQUOTE, context);
1133 if (c == CLOSING_BACKQUOTE)
1136 if (c == '<' || c == '>')
1140 /* An unquoted c indicates we are not inside '...' nor "...". */
1141 if (open_singlequote || open_doublequote)
1144 c2 = phase2_getc ();
1147 /* Process substitution (Bash syntax). */
1148 read_command_list (')', context);
1157 if (!open_singlequote && !open_doublequote
1158 && (is_whitespace (c) || is_operator_start (c)))
1161 if (wp->type == t_string)
1163 grow_token (wp->token);
1164 wp->token->chars[wp->token->charcount++] = (unsigned char) c;
1170 if (wp->type != t_string)
1172 free_token (wp->token);
1175 last_non_comment_line = line_number;
1179 /* Read the next command.
1180 'looking_for' denotes a parse terminator, either CLOSING_BACKQUOTE, ')'
1182 Returns the type of the word that terminated the command. */
1183 static enum word_type
1184 read_command (int looking_for, flag_context_ty outer_context)
1186 /* Read the words that make up the command.
1187 Here we completely ignore field splitting at whitespace and wildcard
1188 expansions; i.e. we assume that the source is written in such a way that
1189 every word in the program determines exactly one word in the resulting
1191 But we do not require that the 'gettext'/'ngettext' command is the
1192 first in the command; this is because 1. we want to allow for prefixes
1193 like "$verbose" that may expand to nothing, and 2. it's a big effort
1194 to know where a command starts in a $(for ...) or $(case ...) compound
1196 int arg = 0; /* Current argument number. */
1197 bool arg_of_redirect = false; /* True right after a redirection operator. */
1198 flag_context_list_iterator_ty context_iter;
1199 const struct callshapes *shapes = NULL;
1200 struct arglist_parser *argparser = NULL;
1205 flag_context_ty inner_context;
1208 inner_context = null_context;
1211 inherited_context (outer_context,
1212 flag_context_list_iterator_advance (
1215 read_word (&inner, looking_for, inner_context);
1217 /* Recognize end of command. */
1218 if (inner.type == t_separator
1219 || inner.type == t_backquote || inner.type == t_paren
1220 || inner.type == t_eof)
1222 if (argparser != NULL)
1223 arglist_parser_done (argparser, arg);
1229 if (inner.type == t_string)
1233 pos.file_name = logical_file_name;
1234 pos.line_number = inner.line_number_at_start;
1235 remember_a_message (mlp, NULL, string_of_word (&inner),
1236 inner_context, &pos, NULL, savable_comment);
1240 if (arg_of_redirect)
1242 /* Ignore arguments of redirection operators. */
1243 arg_of_redirect = false;
1245 else if (inner.type == t_redirect)
1247 /* Ignore this word and the following one. */
1248 arg_of_redirect = true;
1252 if (argparser == NULL)
1254 /* This is the function position. */
1256 if (inner.type == t_string)
1258 char *function_name = string_of_word (&inner);
1259 void *keyword_value;
1261 if (hash_find_entry (&keywords,
1262 function_name, strlen (function_name),
1265 shapes = (const struct callshapes *) keyword_value;
1267 argparser = arglist_parser_alloc (mlp, shapes);
1270 flag_context_list_iterator (
1271 flag_context_list_table_lookup (
1272 flag_context_list_table,
1273 function_name, strlen (function_name)));
1275 free (function_name);
1278 context_iter = null_context_list_iterator;
1282 /* These are the argument positions. */
1283 if (inner.type == t_string)
1284 arglist_parser_remember (argparser, arg,
1285 string_of_word (&inner),
1288 inner.line_number_at_start,
1291 if (arglist_parser_decidedp (argparser, arg))
1293 /* Stop looking for arguments of the last function_name. */
1294 /* FIXME: What about context_iter? */
1295 arglist_parser_done (argparser, arg);
1309 /* Read a list of commands.
1310 'looking_for' denotes a parse terminator, either CLOSING_BACKQUOTE, ')'
1312 Returns the type of the word that terminated the command list. */
1313 static enum word_type
1314 read_command_list (int looking_for, flag_context_ty outer_context)
1318 enum word_type terminator;
1320 terminator = read_command (looking_for, outer_context);
1321 if (terminator != t_separator)
1328 extract_sh (FILE *f,
1329 const char *real_filename, const char *logical_filename,
1330 flag_context_list_table_ty *flag_table,
1331 msgdomain_list_ty *mdlp)
1333 mlp = mdlp->item[0]->messages;
1336 real_file_name = real_filename;
1337 logical_file_name = xstrdup (logical_filename);
1340 last_comment_line = -1;
1341 last_non_comment_line = -1;
1343 nested_backquotes = 0;
1344 open_doublequotes_mask = 0;
1345 open_doublequote = false;
1346 open_singlequote = false;
1348 flag_context_list_table = flag_table;
1352 /* Eat tokens until eof is seen. */
1353 read_command_list ('\0', null_context);
1356 real_file_name = NULL;
1357 logical_file_name = NULL;