diff options
Diffstat (limited to 'debian/gettext-kde/gettext-kde-0.10.35/src/po-lex.c')
-rw-r--r-- | debian/gettext-kde/gettext-kde-0.10.35/src/po-lex.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/debian/gettext-kde/gettext-kde-0.10.35/src/po-lex.c b/debian/gettext-kde/gettext-kde-0.10.35/src/po-lex.c new file mode 100644 index 00000000..0d614308 --- /dev/null +++ b/debian/gettext-kde/gettext-kde-0.10.35/src/po-lex.c @@ -0,0 +1,545 @@ +/* GNU gettext - internationalization aids + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + This file was written by Peter Miller <[email protected]> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> + +#include <libintl.h> +#define _(str) gettext(str) + +#if HAVE_VPRINTF || HAVE_DOPRNT +# if __STDC__ +# include <stdarg.h> +# define VA_START(args, lastarg) va_start(args, lastarg) +# else +# include <varargs.h> +# define VA_START(args, lastarg) va_start(args) +# endif +#else +# define va_alist a1, a2, a3, a4, a5, a6, a7, a8 +# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8; +#endif + +#include "po-lex.h" +#include "po-gram.h" +#include "system.h" +#include "error.h" +#include "po-gram.gen.h" + + +static FILE *fp; +lex_pos_ty gram_pos; +size_t gram_max_allowed_errors = 20; +static int pass_comments = 0; +static int pass_obsolete_entries = 0; + + +/* Prototypes for local functions. */ +static int lex_getc PARAMS ((void)); +static void lex_ungetc PARAMS ((int __ch)); +static int keyword_p PARAMS ((char *__s)); +static int control_sequence PARAMS ((void)); + + +void +lex_open (fname) + const char *fname; +{ + fp = open_po_file (fname, &gram_pos.file_name); + if (!fp) + error (EXIT_FAILURE, errno, + _("error while opening \"%s\" for reading"), fname); + + gram_pos.line_number = 1; +} + + +void +lex_close () +{ + if (error_message_count > 0) + error (EXIT_FAILURE, 0, _("found %d fatal errors"), error_message_count); + + if (fp != stdin) + fclose (fp); + fp = NULL; + gram_pos.file_name = 0; + gram_pos.line_number = 0; + error_message_count = 0; +} + + +/* CAUTION: If you change this function, you must also make identical + changes to the macro of the same name in src/po-lex.h */ + +#if !__STDC__ || !defined __GNUC__ || __GNUC__ == 1 +/* VARARGS1 */ +void +# if defined VA_START && __STDC__ +po_gram_error (const char *fmt, ...) +# else +po_gram_error (fmt, va_alist) + const char *fmt; + va_dcl +# endif +{ +# ifdef VA_START + va_list ap; + char *buffer; + + VA_START (ap, fmt); + + vasprintf (&buffer, fmt, ap); + va_end (ap); + error_at_line (0, 0, gram_pos.file_name, gram_pos.line_number, "%s", buffer); +# else + error_at_line (0, 0, gram_pos.file_name, gram_pos.line_number, fmt, + a1, a2, a3, a4, a5, a6, a7, a8); +# endif + + /* Some messages need more than one line. Continuation lines are + indicated by using "..." at the start of the string. We don't + increment the error counter for these continuation lines. */ + if (*fmt == '.') + --error_message_count; + else if (error_message_count >= gram_max_allowed_errors) + error (EXIT_FAILURE, 0, _("too many errors, aborting")); +} + + +/* CAUTION: If you change this function, you must also make identical + changes to the macro of the same name in src/po-lex.h */ + +/* VARARGS2 */ +void +# if defined VA_START && __STDC__ +gram_error_at_line (const lex_pos_ty *pp, const char *fmt, ...) +# else +gram_error_at_line (pp, fmt, va_alist) + const lex_pos_ty *pp; + const char *fmt; + va_dcl +# endif +{ +# ifdef VA_START + va_list ap; + char *buffer; + + VA_START (ap, fmt); + + vasprintf (&buffer, fmt, ap); + va_end (ap); + error_at_line (0, 0, pp->file_name, pp->line_number, "%s", buffer); +# else + error_at_line (0, 0, pp->file_name, pp->line_number, fmt, + a1, a2, a3, a4, a5, a6, a7, a8); +# endif + + /* Some messages need more than one line, or more than one location. + Continuation lines are indicated by using "..." at the start of the + string. We don't increment the error counter for these + continuation lines. */ + if (*fmt == '.') + --error_message_count; + else if (error_message_count >= gram_max_allowed_errors) + error (EXIT_FAILURE, 0, _("too many errors, aborting")); +} +#endif + + +static int +lex_getc () +{ + int c; + + for (;;) + { + c = getc (fp); + switch (c) + { + case EOF: + if (ferror (fp)) + error (EXIT_FAILURE, errno, _("error while reading \"%s\""), + gram_pos.file_name); + return EOF; + + case '\n': + ++gram_pos.line_number; + return '\n'; + + case '\\': + c = getc (fp); + if (c != '\n') + { + if (c != EOF) + ungetc (c, fp); + return '\\'; + } + ++gram_pos.line_number; + break; + + default: + return c; + } + } +} + + +static void +lex_ungetc (c) + int c; +{ + switch (c) + { + case EOF: + break; + + case '\n': + --gram_pos.line_number; + /* FALLTHROUGH */ + + default: + ungetc (c, fp); + break; + } +} + + +static int +keyword_p (s) + char *s; +{ + if (!strcmp (s, "domain")) + return DOMAIN; + if (!strcmp (s, "msgid")) + return MSGID; + if (!strcmp (s, "msgstr")) + return MSGSTR; + po_gram_error (_("keyword \"%s\" unknown"), s); + return NAME; +} + + +static int +control_sequence () +{ + int c; + int val; + int max; + + c = lex_getc (); + switch (c) + { + case 'n': + return '\n'; + + case 't': + return '\t'; + + case 'b': + return '\b'; + + case 'r': + return '\r'; + + case 'f': + return '\f'; + + case '\\': + case '"': + return c; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + val = 0; + for (max = 0; max < 3; ++max) + { + /* Warning: not portable, can't depend on '0'..'7' ordering. */ + val = val * 8 + c - '0'; + c = lex_getc (); + switch (c) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + continue; + + default: + break; + } + break; + } + lex_ungetc (c); + return val; + + case 'x': case 'X': + c = lex_getc (); + if (c == EOF || !isxdigit (c)) + break; + + val = 0; + for (;;) + { + val *= 16; + if (isdigit (c)) + /* Warning: not portable, can't depend on '0'..'9' ordering */ + val += c - '0'; + else if (isupper (c)) + /* Warning: not portable, can't depend on 'A'..'F' ordering */ + val += c - 'A' + 10; + else + /* Warning: not portable, can't depend on 'a'..'f' ordering */ + val += c - 'a' + 10; + + c = lex_getc (); + switch (c) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + continue; + + default: + break; + } + break; + } + return val; + } + po_gram_error (_("illegal control sequence")); + return ' '; +} + + +int +po_gram_lex () +{ + static char *buf; + static size_t bufmax; + int c; + size_t bufpos; + + for (;;) + { + c = lex_getc (); + switch (c) + { + case EOF: + /* Yacc want this for end of file. */ + return 0; + + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': + break; + + case '#': + /* Accumulate comments into a buffer. If we have been asked + to pass comments, generate a COMMENT token, otherwise + discard it. */ + c = lex_getc (); + if (c == '~' && pass_obsolete_entries) + /* A special comment beginning with #~ is found. This + is the format for obsolete entries and if we are + asked to return them is entries not as comments be + simply stop processing the comment here. The + following characters are expected to be well formed. */ + break; + + if (pass_comments) + { + bufpos = 0; + while (1) + { + if (bufpos >= bufmax) + { + bufmax += 100; + buf = xrealloc (buf, bufmax); + } + if (c == EOF || c == '\n') + break; + + buf[bufpos++] = c; + c = lex_getc (); + } + buf[bufpos] = 0; + + po_gram_lval.string = buf; + return COMMENT; + } + else + /* We do this in separate loop because collecting large + comments while they get not passed to the upper layers + is not very effective. */ + while (c != EOF && c != '\n') + c = lex_getc (); + break; + + case '"': + bufpos = 0; + while (1) + { + if (bufpos >= bufmax) + { + bufmax += 100; + buf = xrealloc (buf, bufmax); + } + c = lex_getc (); + if (c == '\n') + { + po_gram_error (_("end-of-line within string")); + break; + } + if (c == EOF) + { + po_gram_error (_("end-of-file within string")); + break; + } + if (c == '"') + break; + + if (c == '\\') + c = control_sequence (); + + buf[bufpos++] = c; + } + buf[bufpos] = 0; + + po_gram_lval.string = xstrdup (buf); + return STRING; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '_': case '$': + bufpos = 0; + for (;;) + { + if (bufpos + 1 >= bufmax) + { + bufmax += 100; + buf = xrealloc (buf, bufmax); + } + buf[bufpos++] = c; + c = lex_getc (); + switch (c) + { + default: + break; + case 'a': case 'b': case 'c': case 'd': + case 'e': case 'f': case 'g': case 'h': + case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': + case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': + case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': + case 'E': case 'F': case 'G': case 'H': + case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': case 'P': + case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': + case 'Y': case 'Z': + case '_': case '$': + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + continue; + } + break; + } + lex_ungetc (c); + + buf[bufpos] = 0; + + c = keyword_p (buf); + if (c == NAME) + po_gram_lval.string = xstrdup (buf); + return c; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + /* I know, we don't need numbers, yet. */ + bufpos = 0; + for (;;) + { + if (bufpos + 1 >= bufmax) + { + bufmax += 100; + buf = xrealloc (buf, bufmax + 1); + } + buf[bufpos++] = c; + c = lex_getc (); + switch (c) + { + default: + break; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + continue; + } + break; + } + lex_ungetc (c); + + buf[bufpos] = 0; + + po_gram_lval.number = atol (buf); + return NUMBER; + + default: + /* This will cause a syntax error. */ + return JUNK; + } + } +} + + +void +po_lex_pass_comments (flag) + int flag; +{ + pass_comments = (flag != 0); +} + + +void +po_lex_pass_obsolete_entries (flag) + int flag; +{ + pass_obsolete_entries = (flag != 0); +} |