Mercurial > hg > xemacs-beta
diff lib-src/make-po.c @ 70:131b0175ea99 r20-0b30
Import from CVS: tag r20-0b30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:02:59 +0200 |
parents | |
children | 576fb035e263 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib-src/make-po.c Mon Aug 13 09:02:59 2007 +0200 @@ -0,0 +1,301 @@ +/* Generate .po file from doc-string file. + + Scan specified doc-string file, creating .po format messages for processing + with msgfmt. The results go to standard output or to a file specified + with -a or -o (-a to append, -o to start from nothing). + + Kludge to make up for shortcoming in make-docfile and Snarf-documentation: + If arg before input filename is -p, we are scanning an add-on + package, which requires slightly different processing. +*/ + +#include <stdio.h> +#include <stdlib.h> + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#endif + +/* #define BUFSIZE 8192 */ +#define BUFSIZE 16384 +#define NEWSTRING 31 /* Character signalling start of new doc string */ +#define LINEEND "\\n" +#define ENDSTRING "\"\n" +#define LINEBEGIN " \"" +#define LINEBREAK ENDSTRING LINEBEGIN + +/* some brain-dead headers define this ... */ +#undef FALSE +#undef TRUE +enum boolean { FALSE, TRUE }; + + +/***********************/ +/* buffer pseudo-class */ +/***********************/ + +typedef struct _buffer +{ + size_t index; /* current position in buf[] */ + size_t size; /* size of buf */ + char *buf; +} buffer_struct; + +#define BUF_NULL {0, 0, NULL} + +int buf_init (buffer_struct *buffer, size_t size); +void buf_free (buffer_struct *buffer); +void buf_clear (buffer_struct *buffer); +int buf_putc (buffer_struct *buffer, int c); +int buf_print (buffer_struct *buffer, const char *s); + + +/********************/ +/* global variables */ +/********************/ + +FILE *infile = NULL; +FILE *outfile = NULL; +buffer_struct buf = BUF_NULL; + + +void scan_file (enum boolean package); +void initialize (void); +void clean_exit (int status); +void buf_putc_safe (int c); +void buf_print_safe (const char *s); +void terminate_string (void); + +main (int argc, char *argv[]) +{ + register int i; + enum boolean package = FALSE; /* TRUE if scanning add-on package */ + + initialize (); + + outfile = stdout; + + /* If first two args are -o FILE, output to FILE. */ + i = 1; + if (argc > i + 1 && strcmp (argv[i], "-o") == 0) { + outfile = fopen (argv[++i], "w"); + ++i; + } + /* ...Or if args are -a FILE, append to FILE. */ + if (argc > i + 1 && strcmp (argv[i], "-a") == 0) { + outfile = fopen (argv[++i], "a"); + ++i; + } + if (!outfile) { + fprintf (stderr, "Unable to open output file %s\n", argv[--i]); + return 1; + } + + if (argc > i && !strcmp (argv[i], "-p")) { + package = TRUE; + ++i; + } + + infile = fopen (argv[i], "r"); + if (!infile) { + fprintf (stderr, "Unable to open input file %s\n", argv[i]); + return 1; + } + + scan_file (package); + clean_exit (EXIT_SUCCESS); +} + + +void scan_file (enum boolean package) +{ + register int c; /* Character read in */ + + fprintf (outfile, "###############\n"); + fprintf (outfile, "# DOC strings #\n"); + fprintf (outfile, "###############\n"); + + while (c = getc (infile), !feof (infile)) { + if (c == NEWSTRING) { + /* If a string was being processed, terminate it. */ + if (buf.index > 0) + terminate_string (); + + /* Skip function or variable name. */ + while (c != '\n') + c = getc (infile); + c = getc (infile); + + /* Begin a new string. */ + fprintf (outfile, "msgid \""); + buf_print_safe ("msgstr \""); + } + + if (c == '\n') { + /* Peek at next character. */ + c = getc (infile); + ungetc (c, infile); + + /* For add-on (i.e., non-preloaded) documentation, ignore the last + carriage return of a string. */ + if (!(package && c == NEWSTRING)) { + fprintf (outfile, LINEEND); + buf_print_safe (LINEEND); + } + + /* If not end of string, continue it on the next line. */ + if (c != NEWSTRING) { + fprintf (outfile, LINEBREAK); + buf_print_safe (LINEBREAK); + } + } + else { + + /* If character is \ or ", precede it by a backslash. */ + if (c == '\\' || c == '\"') { + putc ('\\', outfile); + buf_putc_safe ('\\'); + } + + putc (c, outfile); + buf_putc_safe (c); + } + } + terminate_string (); +} + + +/* initialize sets up the global variables. +*/ +void initialize (void) +{ + if (buf_init (&buf, BUFSIZE) != 0) + clean_exit (EXIT_FAILURE); +} + + +/* clean_exit returns any resources and terminates the program. + An error message is printed if status is EXIT_FAILURE. +*/ +void clean_exit (int status) +{ + if (buf.size > 0) + buf_free (&buf); + if (outfile) + fclose (outfile); + if (infile) + fclose (infile); + + if (status == EXIT_FAILURE) + fprintf (stderr, "make-po abnormally terminated\n"); + exit (status); +} + + +/* buf_putc_safe writes the character c on the global buffer buf, + checking to make sure that the operation was successful. +*/ +void buf_putc_safe (int c) +{ + register int status; + + status = buf_putc (&buf, c); + if (status == EOF) + clean_exit (EXIT_FAILURE); +} + + +/* buf_putc_safe writes the string s on the global buffer buf, + checking to make sure that the operation was successful. +*/ +void buf_print_safe (const char *s) +{ + register int status; + + status = buf_print (&buf, s); + if (status < 0) + clean_exit (EXIT_FAILURE); +} + + +/* terminate_string terminates the current doc string and outputs the buffer. +*/ +void terminate_string (void) + { + fprintf (outfile, ENDSTRING); + + /* Make the "translation" different from the original string. */ + buf_print_safe ("_X"); + + buf_print_safe (ENDSTRING); + fprintf (outfile, "%s", buf.buf); + buf_clear (&buf); + } + + +/*********************************/ +/* buffer pseudo-class functions */ +/*********************************/ + +/* buf_init initializes a buffer to the specified size. + It returns non-zero if the attempt fails. +*/ +int buf_init (buffer_struct *buffer, size_t size) +{ + buffer->buf = malloc (size); + if (buffer->buf == NULL) + return 1; + + buffer->size = size; + buf_clear (buffer); + return 0; +} + + +/* buf_free releases the memory allocated for the buffer. +*/ +void buf_free (buffer_struct *buffer) +{ + free (buffer->buf); + buffer->size = 0; +} + + +/* buf_clear resets a buffer to an empty string. +*/ +void buf_clear (buffer_struct *buffer) +{ + buffer->index = 0; + buffer->buf[0] = '\0'; +} + + +/* buf_putc writes the character c on the buffer. + It returns the character written, or EOF for error. +*/ +int buf_putc (buffer_struct *buffer, int c) +{ + if (buffer->index >= buffer->size) + return EOF; + + buffer->buf[buffer->index++] = c; + return c; +} + + +/* buf_print writes the string s on the buffer. + It returns the number of characters written, or negative if an error occurred. +*/ +int buf_print (buffer_struct *buffer, const char *s) +{ + register int len; + + len = strlen (s); + if (buffer->index + len >= buffer->size) + return -1; + + sprintf (&(buffer->buf[buffer->index]), s); + buffer->index += len; + return len; +}