1/* makemsg.c - aeb - 940605 */
2/*
3 * Read a file input with lines
4 *	LABEL "text"
5 * and either output two files:
6 * a file msgout.c with content      char *msg[] = { "text", ... };
7 * and a file msgout.h with content  #define LABEL 1
8 * or output a single file:
9 * a message catalog with lines      1 "text"
10 *
11 * The former two are used during compilation of the main program
12 * and give default (English) messages. The latter output file is
13 * input for gencat, and used in non-English locales.
14 *
15 * Call:
16 *	makemsg input msgout.h msgout.c
17 * or
18 *	makemsg -c input message_catalog
19 */
20#include <stdio.h>
21#include <unistd.h>
22#ifdef __QNX__
23#include <unix.h>
24#endif
25extern char *index(const char *, int);
26extern char *rindex(const char *, int);
27
28#define BUFSIZE 4096
29
30#define whitespace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
31
32static void
33usage(void){
34    fprintf (stderr, "call is: makemsg input msgout.h msgout.c\n");
35    fprintf (stderr, "or:  makemsg -c input catalog\n");
36    exit (1);
37}
38
39int
40main(int argc, char **argv) {
41    FILE *fin, *foh, *foc;
42    char *s, *t;
43    char *infile, *outcfile, *outhfile;
44    char buf[BUFSIZE];
45    int defct = 0;
46    int makecat = 0;
47
48#define getbuf	if (fgets (buf, sizeof(buf), fin) == NULL) {\
49		    fprintf (stderr, "makemsg: unexpected end of input\n");\
50		    fprintf (stderr, "[output file(s) removed]\n");\
51		    unlink (outcfile);\
52		    if (!makecat) unlink (outhfile);\
53		    exit (1);\
54		}
55
56    if (argc != 4)
57      usage ();
58
59    outhfile = 0; foh = 0;	/* just to keep gcc happy */
60
61    if (!strcmp(argv[1], "-c")) {
62	makecat = 1;
63	infile = argv[2];
64	outcfile = argv[3];
65    } else {
66	infile = argv[1];
67	outhfile = argv[2];
68	outcfile = argv[3];
69    }
70
71    fin = fopen (infile, "r");
72    if (!fin) {
73	perror (infile);
74	fprintf (stderr, "makemsg: cannot open input file %s\n", infile);
75	usage ();
76    }
77
78    /* help people not to confuse the order of these args */
79    if (!makecat) {
80	s = rindex(outhfile, '.');
81	if (!s || s[1] != 'h') {
82	    fprintf (stderr, "defines output file should have name ending in .h\n");
83	    usage ();
84	}
85	s = rindex(outcfile, '.');
86	if (!s || s[1] != 'c') {
87	    fprintf (stderr, "string output file should have name ending in .c\n");
88	    usage ();
89	}
90    }
91
92    if (!makecat) {
93	foh = fopen (outhfile, "w");
94	if (!foh) {
95	    perror (argv[1]);
96	    fprintf (stderr, "makemsg: cannot open output file %s\n", outhfile);
97	    usage ();
98	}
99    }
100    foc = fopen (outcfile, "w");
101    if (!foc) {
102	perror (argv[2]);
103	fprintf (stderr, "makemsg: cannot open output file %s\n", outcfile);
104	usage ();
105    }
106
107    if (makecat)
108      fputs ("$quote \"\n$set 1\n", foc);
109    else
110      fputs ("char *msg[] = {\n  \"\",\n", foc);
111
112    while (fgets (buf, sizeof(buf), fin) != NULL) {
113	char ss;
114
115	/* skip leading blanks and blank lines */
116	s = buf;
117	while (whitespace(*s))
118	  s++;
119	if (*s == 0)
120	  continue;
121
122	/* extract label part */
123	t = s;
124	while (*s && !whitespace(*s))
125	  s++;
126	ss = *s;
127	*s = 0;
128	if (makecat) {
129	    /* the format here used to be "%d  ", but that breaks
130	       glibc-2.1.2 gencat */
131	    fprintf (foc, "%d ", ++defct); /* gencat cannot handle %2d */
132	} else {
133	    fprintf (foh, "#define %s %d\n", t, ++defct);
134	    fprintf (foc, "/* %2d */  ", defct);
135	}
136	*s = ss;
137
138	/* skip blanks and newlines until string found */
139	while (whitespace(*s) || *s == 0) {
140	    if (*s == 0) {
141		getbuf;
142		s = buf;
143	    } else
144	      s++;
145	}
146
147	/* output string - it may extend over several lines */
148	while ((t = index(s, '\n')) == NULL || (t > buf && t[-1] == '\\')) {
149	    fputs (s, foc);
150	    getbuf;
151	    s = buf;
152	}
153	*t = 0;
154	fputs (s, foc);
155	if (makecat)
156	  fputs ("\n", foc);
157	else
158	  fputs (",\n", foc);
159    }
160
161    if (!makecat) {
162	fputs ("};\n", foc);
163	fprintf (foh, "\n#define MAXMSG %d\n", defct);
164    }
165
166    if (!makecat) {
167	fclose (foh);
168    }
169
170    fclose (foc);
171    fclose (fin);
172
173    return 0;
174}
175