No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / src / x-librep.c
blobafa99fc3bb3918ac765c598ca3365f000e53b81a
1 /* xgettext librep backend.
2 Copyright (C) 2001-2003 Free Software Foundation, Inc.
4 This file was written by Bruno Haible <haible@clisp.cons.org>, 2001.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include <ctype.h>
25 #include <errno.h>
26 #include <stdbool.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #include "message.h"
32 #include "xgettext.h"
33 #include "x-librep.h"
34 #include "error.h"
35 #include "xalloc.h"
36 #include "exit.h"
37 #include "hash.h"
38 #include "gettext.h"
40 #define _(s) gettext(s)
43 /* Summary of librep syntax:
44 - ';' starts a comment until end of line.
45 - Block comments start with '#|' and end with '|#'.
46 - Numbers are constituted of an optional prefix (#b, #B for binary,
47 #o, #O for octal, #d, #D for decimal, #x, #X for hexadecimal,
48 #e, #E for exact, #i, #I for inexact), an optional sign (+ or -), and
49 the digits.
50 - Characters are written as '?' followed by the character, possibly
51 with an escape sequence, for examples '?a', '?\n', '?\177'.
52 - Strings are delimited by double quotes. Backslash introduces an escape
53 sequence. The following are understood: '\n', '\r', '\f', '\t', '\a',
54 '\\', '\^C', '\012' (octal), '\x12' (hexadecimal).
55 - Symbols: can contain meta-characters - whitespace or any from ()[]'";|\' -
56 if preceded by backslash or enclosed in |...|.
57 - Keywords: written as #:SYMBOL.
58 - () delimit lists.
59 - [] delimit vectors.
60 The reader is implemented in librep-0.14/src/lisp.c. */
63 /* ====================== Keyword set customization. ====================== */
65 /* If true extract all strings. */
66 static bool extract_all = false;
68 static hash_table keywords;
69 static bool default_keywords = true;
72 void
73 x_librep_extract_all ()
75 extract_all = true;
79 void
80 x_librep_keyword (const char *name)
82 if (name == NULL)
83 default_keywords = false;
84 else
86 const char *end;
87 int argnum1;
88 int argnum2;
89 const char *colon;
91 if (keywords.table == NULL)
92 init_hash (&keywords, 100);
94 split_keywordspec (name, &end, &argnum1, &argnum2);
96 /* The characters between name and end should form a valid Lisp
97 symbol. */
98 colon = strchr (name, ':');
99 if (colon == NULL || colon >= end)
101 if (argnum1 == 0)
102 argnum1 = 1;
103 insert_entry (&keywords, name, end - name,
104 (void *) (long) (argnum1 + (argnum2 << 10)));
109 /* Finish initializing the keywords hash table.
110 Called after argument processing, before each file is processed. */
111 static void
112 init_keywords ()
114 if (default_keywords)
116 x_librep_keyword ("_");
117 default_keywords = false;
121 void
122 init_flag_table_librep ()
124 xgettext_record_flag ("_:1:pass-librep-format");
125 xgettext_record_flag ("format:2:librep-format");
129 /* ======================== Reading of characters. ======================== */
131 /* Real filename, used in error messages about the input file. */
132 static const char *real_file_name;
134 /* Logical filename and line number, used to label the extracted messages. */
135 static char *logical_file_name;
136 static int line_number;
138 /* The input file stream. */
139 static FILE *fp;
142 /* Fetch the next character from the input file. */
143 static int
144 do_getc ()
146 int c = getc (fp);
148 if (c == EOF)
150 if (ferror (fp))
151 error (EXIT_FAILURE, errno, _("\
152 error while reading \"%s\""), real_file_name);
154 else if (c == '\n')
155 line_number++;
157 return c;
160 /* Put back the last fetched character, not EOF. */
161 static void
162 do_ungetc (int c)
164 if (c == '\n')
165 line_number--;
166 ungetc (c, fp);
170 /* ========================== Reading of tokens. ========================== */
173 /* A token consists of a sequence of characters. */
174 struct token
176 int allocated; /* number of allocated 'token_char's */
177 int charcount; /* number of used 'token_char's */
178 char *chars; /* the token's constituents */
181 /* Initialize a 'struct token'. */
182 static inline void
183 init_token (struct token *tp)
185 tp->allocated = 10;
186 tp->chars = (char *) xmalloc (tp->allocated * sizeof (char));
187 tp->charcount = 0;
190 /* Free the memory pointed to by a 'struct token'. */
191 static inline void
192 free_token (struct token *tp)
194 free (tp->chars);
197 /* Ensure there is enough room in the token for one more character. */
198 static inline void
199 grow_token (struct token *tp)
201 if (tp->charcount == tp->allocated)
203 tp->allocated *= 2;
204 tp->chars = (char *) xrealloc (tp->chars, tp->allocated * sizeof (char));
208 /* Read the next token. If 'first' is given, it points to the first
209 character, which has already been read. Returns true for a symbol,
210 false for a number. */
211 static bool
212 read_token (struct token *tp, const int *first)
214 int c;
215 /* Variables for speculative number parsing: */
216 int radix = -1;
217 int nfirst = 0;
218 bool exact = true;
219 bool rational = false;
220 bool exponent = false;
221 bool had_sign = false;
222 bool expecting_prefix = false;
224 init_token (tp);
226 if (first)
227 c = *first;
228 else
229 c = do_getc ();
231 for (;; c = do_getc ())
233 switch (c)
235 case EOF:
236 goto done;
238 case ' ': case '\t': case '\n': case '\f': case '\r':
239 case '(': case ')': case '[': case ']':
240 case '\'': case '"': case ';': case ',': case '`':
241 goto done;
243 case '\\':
244 radix = 0;
245 c = do_getc ();
246 if (c == EOF)
247 /* Invalid, but be tolerant. */
248 break;
249 grow_token (tp);
250 tp->chars[tp->charcount++] = c;
251 break;
253 case '|':
254 radix = 0;
255 for (;;)
257 c = do_getc ();
258 if (c == EOF || c == '|')
259 break;
260 grow_token (tp);
261 tp->chars[tp->charcount++] = c;
263 break;
265 default:
266 if (radix != 0)
268 if (expecting_prefix)
270 switch (c)
272 case 'B': case 'b':
273 radix = 2;
274 break;
275 case 'O': case 'o':
276 radix = 8;
277 break;
278 case 'D': case 'd':
279 radix = 10;
280 break;
281 case 'X': case 'x':
282 radix = 16;
283 break;
284 case 'E': case 'e':
285 case 'I': case 'i':
286 break;
287 default:
288 radix = 0;
289 break;
291 expecting_prefix = false;
292 nfirst = tp->charcount + 1;
294 else if (tp->charcount == nfirst
295 && (c == '+' || c == '-' || c == '#'))
297 if (c == '#')
299 if (had_sign)
300 radix = 0;
301 else
302 expecting_prefix = true;
304 else
305 had_sign = true;
306 nfirst = tp->charcount + 1;
308 else
310 switch (radix)
312 case -1:
313 if (c == '.')
315 radix = 10;
316 exact = false;
318 else if (!(c >= '0' && c <= '9'))
319 radix = 0;
320 else if (c == '0')
321 radix = 1;
322 else
323 radix = 10;
324 break;
326 case 1:
327 switch (c)
329 case 'X': case 'x':
330 radix = 16;
331 nfirst = tp->charcount + 1;
332 break;
333 case '0': case '1': case '2': case '3': case '4':
334 case '5': case '6': case '7':
335 radix = 8;
336 nfirst = tp->charcount;
337 break;
338 case '.': case 'E': case 'e':
339 radix = 10;
340 exact = false;
341 break;
342 case '/':
343 radix = 10;
344 rational = true;
345 break;
346 default:
347 radix = 0;
348 break;
350 break;
352 default:
353 switch (c)
355 case '.':
356 if (exact && radix == 10 && !rational)
357 exact = false;
358 else
359 radix = 0;
360 break;
361 case '/':
362 if (exact && !rational)
363 rational = true;
364 else
365 radix = 0;
366 break;
367 case 'E': case 'e':
368 if (radix == 10)
370 if (!rational && !exponent)
372 exponent = true;
373 exact = false;
375 else
376 radix = 0;
377 break;
379 /*FALLTHROUGH*/
380 default:
381 if (exponent && (c == '+' || c == '-'))
382 break;
383 if ((radix <= 10
384 && !(c >= '0' && c <= '0' + radix - 1))
385 || (radix == 16 && !isxdigit (c)))
386 radix = 0;
387 break;
389 break;
393 else
395 if (c == '#')
396 goto done;
398 grow_token (tp);
399 tp->chars[tp->charcount++] = c;
402 done:
403 if (c != EOF)
404 do_ungetc (c);
405 if (radix > 0 && nfirst < tp->charcount)
406 return false; /* number */
407 else
408 return true; /* symbol */
412 /* ========================= Accumulating comments ========================= */
415 static char *buffer;
416 static size_t bufmax;
417 static size_t buflen;
419 static inline void
420 comment_start ()
422 buflen = 0;
425 static inline void
426 comment_add (int c)
428 if (buflen >= bufmax)
430 bufmax = 2 * bufmax + 10;
431 buffer = xrealloc (buffer, bufmax);
433 buffer[buflen++] = c;
436 static inline void
437 comment_line_end (size_t chars_to_remove)
439 buflen -= chars_to_remove;
440 while (buflen >= 1
441 && (buffer[buflen - 1] == ' ' || buffer[buflen - 1] == '\t'))
442 --buflen;
443 if (chars_to_remove == 0 && buflen >= bufmax)
445 bufmax = 2 * bufmax + 10;
446 buffer = xrealloc (buffer, bufmax);
448 buffer[buflen] = '\0';
449 xgettext_comment_add (buffer);
453 /* These are for tracking whether comments count as immediately before
454 keyword. */
455 static int last_comment_line;
456 static int last_non_comment_line;
459 /* ========================= Accumulating messages ========================= */
462 static message_list_ty *mlp;
465 /* ============== Reading of objects. See CLHS 2 "Syntax". ============== */
468 /* We are only interested in symbols (e.g. GETTEXT or NGETTEXT) and strings.
469 Other objects need not to be represented precisely. */
470 enum object_type
472 t_symbol, /* symbol */
473 t_string, /* string */
474 t_other, /* other kind of real object */
475 t_dot, /* '.' pseudo object */
476 t_close, /* ')' or ']' pseudo object */
477 t_eof /* EOF marker */
480 struct object
482 enum object_type type;
483 struct token *token; /* for t_symbol and t_string */
484 int line_number_at_start; /* for t_string */
487 /* Free the memory pointed to by a 'struct object'. */
488 static inline void
489 free_object (struct object *op)
491 if (op->type == t_symbol || op->type == t_string)
493 free_token (op->token);
494 free (op->token);
498 /* Convert a t_symbol/t_string token to a char*. */
499 static char *
500 string_of_object (const struct object *op)
502 char *str;
503 int n;
505 if (!(op->type == t_symbol || op->type == t_string))
506 abort ();
507 n = op->token->charcount;
508 str = (char *) xmalloc (n + 1);
509 memcpy (str, op->token->chars, n);
510 str[n] = '\0';
511 return str;
514 /* Context lookup table. */
515 static flag_context_list_table_ty *flag_context_list_table;
517 /* Returns the character represented by an escape sequence. */
518 static int
519 do_getc_escaped (int c)
521 switch (c)
523 case 'n':
524 return '\n';
525 case 'r':
526 return '\r';
527 case 'f':
528 return '\f';
529 case 't':
530 return '\t';
531 case 'v':
532 return '\v';
533 case 'a':
534 return '\a';
535 case '^':
536 c = do_getc ();
537 if (c == EOF)
538 return EOF;
539 return c & 0x1f;
540 case '0': case '1': case '2': case '3': case '4':
541 case '5': case '6': case '7':
543 int n = c - '0';
545 c = do_getc ();
546 if (c != EOF)
548 if (c >= '0' && c <= '7')
550 n = (n << 3) + (c - '0');
551 c = do_getc ();
552 if (c != EOF)
554 if (c >= '0' && c <= '7')
555 n = (n << 3) + (c - '0');
556 else
557 do_ungetc (c);
560 else
561 do_ungetc (c);
563 return (unsigned char) n;
565 case 'x':
567 int n = 0;
569 for (;;)
571 c = do_getc ();
572 if (c == EOF)
573 break;
574 else if (c >= '0' && c <= '9')
575 n = (n << 4) + (c - '0');
576 else if (c >= 'A' && c <= 'F')
577 n = (n << 4) + (c - 'A' + 10);
578 else if (c >= 'a' && c <= 'f')
579 n = (n << 4) + (c - 'a' + 10);
580 else
582 do_ungetc (c);
583 break;
586 return (unsigned char) n;
588 default:
589 return c;
593 /* Read the next object. */
594 static void
595 read_object (struct object *op, flag_context_ty outer_context)
597 for (;;)
599 int c;
601 c = do_getc ();
603 switch (c)
605 case EOF:
606 op->type = t_eof;
607 return;
609 case '\n':
610 /* Comments assumed to be grouped with a message must immediately
611 precede it, with no non-whitespace token on a line between
612 both. */
613 if (last_non_comment_line > last_comment_line)
614 xgettext_comment_reset ();
615 continue;
617 case ' ': case '\t': case '\f': case '\r':
618 continue;
620 case '(':
622 int arg = 0; /* Current argument number. */
623 flag_context_list_iterator_ty context_iter;
624 int argnum1 = 0; /* First string position. */
625 int argnum2 = 0; /* Plural string position. */
626 message_ty *plural_mp = NULL; /* Remember the msgid. */
628 for (;; arg++)
630 struct object inner;
631 flag_context_ty inner_context;
633 if (arg == 0)
634 inner_context = null_context;
635 else
636 inner_context =
637 inherited_context (outer_context,
638 flag_context_list_iterator_advance (
639 &context_iter));
641 read_object (&inner, inner_context);
643 /* Recognize end of list. */
644 if (inner.type == t_close)
646 op->type = t_other;
647 /* Don't bother converting "()" to "NIL". */
648 last_non_comment_line = line_number;
649 return;
652 /* Dots are not allowed in every position.
653 But be tolerant. */
655 /* EOF inside list is illegal. But be tolerant. */
656 if (inner.type == t_eof)
657 break;
659 if (arg == 0)
661 /* This is the function position. */
662 if (inner.type == t_symbol)
664 char *symbol_name = string_of_object (&inner);
665 void *keyword_value;
667 if (find_entry (&keywords,
668 symbol_name, strlen (symbol_name),
669 &keyword_value)
670 == 0)
672 argnum1 = (int) (long) keyword_value & ((1 << 10) - 1);
673 argnum2 = (int) (long) keyword_value >> 10;
676 context_iter =
677 flag_context_list_iterator (
678 flag_context_list_table_lookup (
679 flag_context_list_table,
680 symbol_name, strlen (symbol_name)));
682 free (symbol_name);
684 else
685 context_iter = null_context_list_iterator;
687 else
689 /* These are the argument positions.
690 Extract a string if we have reached the right
691 argument position. */
692 if (arg == argnum1)
694 if (inner.type == t_string)
696 lex_pos_ty pos;
697 message_ty *mp;
699 pos.file_name = logical_file_name;
700 pos.line_number = inner.line_number_at_start;
701 mp = remember_a_message (mlp, string_of_object (&inner),
702 inner_context, &pos);
703 if (argnum2 > 0)
704 plural_mp = mp;
707 else if (arg == argnum2)
709 if (inner.type == t_string && plural_mp != NULL)
711 lex_pos_ty pos;
713 pos.file_name = logical_file_name;
714 pos.line_number = inner.line_number_at_start;
715 remember_a_message_plural (plural_mp, string_of_object (&inner),
716 inner_context, &pos);
721 free_object (&inner);
724 op->type = t_other;
725 last_non_comment_line = line_number;
726 return;
728 case '[':
730 for (;;)
732 struct object inner;
734 read_object (&inner, null_context);
736 /* Recognize end of vector. */
737 if (inner.type == t_close)
739 op->type = t_other;
740 last_non_comment_line = line_number;
741 return;
744 /* Dots are not allowed. But be tolerant. */
746 /* EOF inside vector is illegal. But be tolerant. */
747 if (inner.type == t_eof)
748 break;
750 free_object (&inner);
753 op->type = t_other;
754 last_non_comment_line = line_number;
755 return;
757 case ')': case ']':
758 /* Tell the caller about the end of list or vector.
759 Unmatched closing parenthesis is illegal. But be tolerant. */
760 op->type = t_close;
761 last_non_comment_line = line_number;
762 return;
764 case ',':
766 int c = do_getc ();
767 /* The ,@ handling inside lists is wrong anyway, because
768 ,@form expands to an unknown number of elements. */
769 if (c != EOF && c != '@')
770 do_ungetc (c);
772 /*FALLTHROUGH*/
773 case '\'':
774 case '`':
776 struct object inner;
778 read_object (&inner, null_context);
780 /* Dots and EOF are not allowed here. But be tolerant. */
782 free_object (&inner);
784 op->type = t_other;
785 last_non_comment_line = line_number;
786 return;
789 case ';':
791 bool all_semicolons = true;
793 last_comment_line = line_number;
794 comment_start ();
795 for (;;)
797 int c = do_getc ();
798 if (c == EOF || c == '\n' || c == '\f' || c == '\r')
799 break;
800 if (c != ';')
801 all_semicolons = false;
802 if (!all_semicolons)
804 /* We skip all leading white space, but not EOLs. */
805 if (!(buflen == 0 && (c == ' ' || c == '\t')))
806 comment_add (c);
809 comment_line_end (0);
810 continue;
813 case '"':
815 op->token = (struct token *) xmalloc (sizeof (struct token));
816 init_token (op->token);
817 op->line_number_at_start = line_number;
818 for (;;)
820 int c = do_getc ();
821 if (c == EOF)
822 /* Invalid input. Be tolerant, no error message. */
823 break;
824 if (c == '"')
825 break;
826 if (c == '\\')
828 c = do_getc ();
829 if (c == EOF)
830 /* Invalid input. Be tolerant, no error message. */
831 break;
832 if (c == '\n')
833 /* Ignore escaped newline. */
835 else
837 c = do_getc_escaped (c);
838 if (c == EOF)
839 /* Invalid input. Be tolerant, no error message. */
840 break;
841 grow_token (op->token);
842 op->token->chars[op->token->charcount++] = c;
845 else
847 grow_token (op->token);
848 op->token->chars[op->token->charcount++] = c;
851 op->type = t_string;
853 if (extract_all)
855 lex_pos_ty pos;
857 pos.file_name = logical_file_name;
858 pos.line_number = op->line_number_at_start;
859 remember_a_message (mlp, string_of_object (op),
860 null_context, &pos);
862 last_non_comment_line = line_number;
863 return;
866 case '?':
867 c = do_getc ();
868 if (c == EOF)
869 /* Invalid input. Be tolerant, no error message. */
871 else if (c == '\\')
873 c = do_getc ();
874 if (c == EOF)
875 /* Invalid input. Be tolerant, no error message. */
877 else
879 c = do_getc_escaped (c);
880 if (c == EOF)
881 /* Invalid input. Be tolerant, no error message. */
885 op->type = t_other;
886 last_non_comment_line = line_number;
887 return;
889 case '#':
890 /* Dispatch macro handling. */
891 c = do_getc ();
892 if (c == EOF)
893 /* Invalid input. Be tolerant, no error message. */
895 op->type = t_other;
896 return;
899 switch (c)
901 case '!':
902 if (ftell (fp) == 2)
903 /* Skip comment until !# */
905 c = do_getc ();
906 for (;;)
908 if (c == EOF)
909 break;
910 if (c == '!')
912 c = do_getc ();
913 if (c == EOF || c == '#')
914 break;
916 else
917 c = do_getc ();
919 if (c == EOF)
921 /* EOF not allowed here. But be tolerant. */
922 op->type = t_eof;
923 return;
925 continue;
927 /*FALLTHROUGH*/
928 case '\'':
929 case ':':
931 struct object inner;
932 read_object (&inner, null_context);
933 /* Dots and EOF are not allowed here.
934 But be tolerant. */
935 free_object (&inner);
936 op->type = t_other;
937 last_non_comment_line = line_number;
938 return;
941 case '[':
942 case '(':
944 struct object inner;
945 do_ungetc (c);
946 read_object (&inner, null_context);
947 /* Dots and EOF are not allowed here.
948 But be tolerant. */
949 free_object (&inner);
950 op->type = t_other;
951 last_non_comment_line = line_number;
952 return;
955 case '|':
957 int depth = 0;
959 comment_start ();
960 c = do_getc ();
961 for (;;)
963 if (c == EOF)
964 break;
965 if (c == '|')
967 c = do_getc ();
968 if (c == EOF)
969 break;
970 if (c == '#')
972 if (depth == 0)
974 comment_line_end (0);
975 break;
977 depth--;
978 comment_add ('|');
979 comment_add ('#');
980 c = do_getc ();
982 else
983 comment_add ('|');
985 else if (c == '#')
987 c = do_getc ();
988 if (c == EOF)
989 break;
990 comment_add ('#');
991 if (c == '|')
993 depth++;
994 comment_add ('|');
995 c = do_getc ();
998 else
1000 /* We skip all leading white space. */
1001 if (!(buflen == 0 && (c == ' ' || c == '\t')))
1002 comment_add (c);
1003 if (c == '\n')
1005 comment_line_end (1);
1006 comment_start ();
1008 c = do_getc ();
1011 if (c == EOF)
1013 /* EOF not allowed here. But be tolerant. */
1014 op->type = t_eof;
1015 return;
1017 last_comment_line = line_number;
1018 continue;
1021 case '\\':
1023 struct token token;
1024 int first = '\\';
1025 read_token (&token, &first);
1026 free_token (&token);
1027 op->type = t_other;
1028 last_non_comment_line = line_number;
1029 return;
1032 case 'T': case 't':
1033 case 'F': case 'f':
1034 op->type = t_other;
1035 last_non_comment_line = line_number;
1036 return;
1038 case 'B': case 'b':
1039 case 'O': case 'o':
1040 case 'D': case 'd':
1041 case 'X': case 'x':
1042 case 'E': case 'e':
1043 case 'I': case 'i':
1045 struct token token;
1046 do_ungetc (c);
1047 c = '#';
1048 read_token (&token, &c);
1049 free_token (&token);
1050 op->type = t_other;
1051 last_non_comment_line = line_number;
1052 return;
1055 default:
1056 /* Invalid input. Be tolerant, no error message. */
1057 op->type = t_other;
1058 last_non_comment_line = line_number;
1059 return;
1062 /*NOTREACHED*/
1063 abort ();
1065 default:
1066 /* Read a token. */
1068 bool symbol;
1070 op->token = (struct token *) xmalloc (sizeof (struct token));
1071 symbol = read_token (op->token, &c);
1072 if (op->token->charcount == 1 && op->token->chars[0] == '.')
1074 free_token (op->token);
1075 free (op->token);
1076 op->type = t_dot;
1077 last_non_comment_line = line_number;
1078 return;
1080 if (!symbol)
1082 free_token (op->token);
1083 free (op->token);
1084 op->type = t_other;
1085 last_non_comment_line = line_number;
1086 return;
1088 /* Distinguish between "foo" and "foo#bar". */
1089 c = do_getc ();
1090 if (c == '#')
1092 struct token second_token;
1094 free_token (op->token);
1095 free (op->token);
1096 read_token (&second_token, NULL);
1097 free_token (&second_token);
1098 op->type = t_other;
1099 last_non_comment_line = line_number;
1100 return;
1102 else
1104 if (c != EOF)
1105 do_ungetc (c);
1106 op->type = t_symbol;
1107 last_non_comment_line = line_number;
1108 return;
1116 void
1117 extract_librep (FILE *f,
1118 const char *real_filename, const char *logical_filename,
1119 flag_context_list_table_ty *flag_table,
1120 msgdomain_list_ty *mdlp)
1122 mlp = mdlp->item[0]->messages;
1124 fp = f;
1125 real_file_name = real_filename;
1126 logical_file_name = xstrdup (logical_filename);
1127 line_number = 1;
1129 last_comment_line = -1;
1130 last_non_comment_line = -1;
1132 flag_context_list_table = flag_table;
1134 init_keywords ();
1136 /* Eat tokens until eof is seen. When read_object returns
1137 due to an unbalanced closing parenthesis, just restart it. */
1140 struct object toplevel_object;
1142 read_object (&toplevel_object, null_context);
1144 if (toplevel_object.type == t_eof)
1145 break;
1147 free_object (&toplevel_object);
1149 while (!feof (fp));
1151 /* Close scanner. */
1152 fp = NULL;
1153 real_file_name = NULL;
1154 logical_file_name = NULL;
1155 line_number = 0;