Mercurial > hg > xemacs-beta
comparison 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 |
comparison
equal
deleted
inserted
replaced
69:804d1389bcd6 | 70:131b0175ea99 |
---|---|
1 /* Generate .po file from doc-string file. | |
2 | |
3 Scan specified doc-string file, creating .po format messages for processing | |
4 with msgfmt. The results go to standard output or to a file specified | |
5 with -a or -o (-a to append, -o to start from nothing). | |
6 | |
7 Kludge to make up for shortcoming in make-docfile and Snarf-documentation: | |
8 If arg before input filename is -p, we are scanning an add-on | |
9 package, which requires slightly different processing. | |
10 */ | |
11 | |
12 #include <stdio.h> | |
13 #include <stdlib.h> | |
14 | |
15 #ifndef EXIT_SUCCESS | |
16 #define EXIT_SUCCESS 0 | |
17 #define EXIT_FAILURE 1 | |
18 #endif | |
19 | |
20 /* #define BUFSIZE 8192 */ | |
21 #define BUFSIZE 16384 | |
22 #define NEWSTRING 31 /* Character signalling start of new doc string */ | |
23 #define LINEEND "\\n" | |
24 #define ENDSTRING "\"\n" | |
25 #define LINEBEGIN " \"" | |
26 #define LINEBREAK ENDSTRING LINEBEGIN | |
27 | |
28 /* some brain-dead headers define this ... */ | |
29 #undef FALSE | |
30 #undef TRUE | |
31 enum boolean { FALSE, TRUE }; | |
32 | |
33 | |
34 /***********************/ | |
35 /* buffer pseudo-class */ | |
36 /***********************/ | |
37 | |
38 typedef struct _buffer | |
39 { | |
40 size_t index; /* current position in buf[] */ | |
41 size_t size; /* size of buf */ | |
42 char *buf; | |
43 } buffer_struct; | |
44 | |
45 #define BUF_NULL {0, 0, NULL} | |
46 | |
47 int buf_init (buffer_struct *buffer, size_t size); | |
48 void buf_free (buffer_struct *buffer); | |
49 void buf_clear (buffer_struct *buffer); | |
50 int buf_putc (buffer_struct *buffer, int c); | |
51 int buf_print (buffer_struct *buffer, const char *s); | |
52 | |
53 | |
54 /********************/ | |
55 /* global variables */ | |
56 /********************/ | |
57 | |
58 FILE *infile = NULL; | |
59 FILE *outfile = NULL; | |
60 buffer_struct buf = BUF_NULL; | |
61 | |
62 | |
63 void scan_file (enum boolean package); | |
64 void initialize (void); | |
65 void clean_exit (int status); | |
66 void buf_putc_safe (int c); | |
67 void buf_print_safe (const char *s); | |
68 void terminate_string (void); | |
69 | |
70 main (int argc, char *argv[]) | |
71 { | |
72 register int i; | |
73 enum boolean package = FALSE; /* TRUE if scanning add-on package */ | |
74 | |
75 initialize (); | |
76 | |
77 outfile = stdout; | |
78 | |
79 /* If first two args are -o FILE, output to FILE. */ | |
80 i = 1; | |
81 if (argc > i + 1 && strcmp (argv[i], "-o") == 0) { | |
82 outfile = fopen (argv[++i], "w"); | |
83 ++i; | |
84 } | |
85 /* ...Or if args are -a FILE, append to FILE. */ | |
86 if (argc > i + 1 && strcmp (argv[i], "-a") == 0) { | |
87 outfile = fopen (argv[++i], "a"); | |
88 ++i; | |
89 } | |
90 if (!outfile) { | |
91 fprintf (stderr, "Unable to open output file %s\n", argv[--i]); | |
92 return 1; | |
93 } | |
94 | |
95 if (argc > i && !strcmp (argv[i], "-p")) { | |
96 package = TRUE; | |
97 ++i; | |
98 } | |
99 | |
100 infile = fopen (argv[i], "r"); | |
101 if (!infile) { | |
102 fprintf (stderr, "Unable to open input file %s\n", argv[i]); | |
103 return 1; | |
104 } | |
105 | |
106 scan_file (package); | |
107 clean_exit (EXIT_SUCCESS); | |
108 } | |
109 | |
110 | |
111 void scan_file (enum boolean package) | |
112 { | |
113 register int c; /* Character read in */ | |
114 | |
115 fprintf (outfile, "###############\n"); | |
116 fprintf (outfile, "# DOC strings #\n"); | |
117 fprintf (outfile, "###############\n"); | |
118 | |
119 while (c = getc (infile), !feof (infile)) { | |
120 if (c == NEWSTRING) { | |
121 /* If a string was being processed, terminate it. */ | |
122 if (buf.index > 0) | |
123 terminate_string (); | |
124 | |
125 /* Skip function or variable name. */ | |
126 while (c != '\n') | |
127 c = getc (infile); | |
128 c = getc (infile); | |
129 | |
130 /* Begin a new string. */ | |
131 fprintf (outfile, "msgid \""); | |
132 buf_print_safe ("msgstr \""); | |
133 } | |
134 | |
135 if (c == '\n') { | |
136 /* Peek at next character. */ | |
137 c = getc (infile); | |
138 ungetc (c, infile); | |
139 | |
140 /* For add-on (i.e., non-preloaded) documentation, ignore the last | |
141 carriage return of a string. */ | |
142 if (!(package && c == NEWSTRING)) { | |
143 fprintf (outfile, LINEEND); | |
144 buf_print_safe (LINEEND); | |
145 } | |
146 | |
147 /* If not end of string, continue it on the next line. */ | |
148 if (c != NEWSTRING) { | |
149 fprintf (outfile, LINEBREAK); | |
150 buf_print_safe (LINEBREAK); | |
151 } | |
152 } | |
153 else { | |
154 | |
155 /* If character is \ or ", precede it by a backslash. */ | |
156 if (c == '\\' || c == '\"') { | |
157 putc ('\\', outfile); | |
158 buf_putc_safe ('\\'); | |
159 } | |
160 | |
161 putc (c, outfile); | |
162 buf_putc_safe (c); | |
163 } | |
164 } | |
165 terminate_string (); | |
166 } | |
167 | |
168 | |
169 /* initialize sets up the global variables. | |
170 */ | |
171 void initialize (void) | |
172 { | |
173 if (buf_init (&buf, BUFSIZE) != 0) | |
174 clean_exit (EXIT_FAILURE); | |
175 } | |
176 | |
177 | |
178 /* clean_exit returns any resources and terminates the program. | |
179 An error message is printed if status is EXIT_FAILURE. | |
180 */ | |
181 void clean_exit (int status) | |
182 { | |
183 if (buf.size > 0) | |
184 buf_free (&buf); | |
185 if (outfile) | |
186 fclose (outfile); | |
187 if (infile) | |
188 fclose (infile); | |
189 | |
190 if (status == EXIT_FAILURE) | |
191 fprintf (stderr, "make-po abnormally terminated\n"); | |
192 exit (status); | |
193 } | |
194 | |
195 | |
196 /* buf_putc_safe writes the character c on the global buffer buf, | |
197 checking to make sure that the operation was successful. | |
198 */ | |
199 void buf_putc_safe (int c) | |
200 { | |
201 register int status; | |
202 | |
203 status = buf_putc (&buf, c); | |
204 if (status == EOF) | |
205 clean_exit (EXIT_FAILURE); | |
206 } | |
207 | |
208 | |
209 /* buf_putc_safe writes the string s on the global buffer buf, | |
210 checking to make sure that the operation was successful. | |
211 */ | |
212 void buf_print_safe (const char *s) | |
213 { | |
214 register int status; | |
215 | |
216 status = buf_print (&buf, s); | |
217 if (status < 0) | |
218 clean_exit (EXIT_FAILURE); | |
219 } | |
220 | |
221 | |
222 /* terminate_string terminates the current doc string and outputs the buffer. | |
223 */ | |
224 void terminate_string (void) | |
225 { | |
226 fprintf (outfile, ENDSTRING); | |
227 | |
228 /* Make the "translation" different from the original string. */ | |
229 buf_print_safe ("_X"); | |
230 | |
231 buf_print_safe (ENDSTRING); | |
232 fprintf (outfile, "%s", buf.buf); | |
233 buf_clear (&buf); | |
234 } | |
235 | |
236 | |
237 /*********************************/ | |
238 /* buffer pseudo-class functions */ | |
239 /*********************************/ | |
240 | |
241 /* buf_init initializes a buffer to the specified size. | |
242 It returns non-zero if the attempt fails. | |
243 */ | |
244 int buf_init (buffer_struct *buffer, size_t size) | |
245 { | |
246 buffer->buf = malloc (size); | |
247 if (buffer->buf == NULL) | |
248 return 1; | |
249 | |
250 buffer->size = size; | |
251 buf_clear (buffer); | |
252 return 0; | |
253 } | |
254 | |
255 | |
256 /* buf_free releases the memory allocated for the buffer. | |
257 */ | |
258 void buf_free (buffer_struct *buffer) | |
259 { | |
260 free (buffer->buf); | |
261 buffer->size = 0; | |
262 } | |
263 | |
264 | |
265 /* buf_clear resets a buffer to an empty string. | |
266 */ | |
267 void buf_clear (buffer_struct *buffer) | |
268 { | |
269 buffer->index = 0; | |
270 buffer->buf[0] = '\0'; | |
271 } | |
272 | |
273 | |
274 /* buf_putc writes the character c on the buffer. | |
275 It returns the character written, or EOF for error. | |
276 */ | |
277 int buf_putc (buffer_struct *buffer, int c) | |
278 { | |
279 if (buffer->index >= buffer->size) | |
280 return EOF; | |
281 | |
282 buffer->buf[buffer->index++] = c; | |
283 return c; | |
284 } | |
285 | |
286 | |
287 /* buf_print writes the string s on the buffer. | |
288 It returns the number of characters written, or negative if an error occurred. | |
289 */ | |
290 int buf_print (buffer_struct *buffer, const char *s) | |
291 { | |
292 register int len; | |
293 | |
294 len = strlen (s); | |
295 if (buffer->index + len >= buffer->size) | |
296 return -1; | |
297 | |
298 sprintf (&(buffer->buf[buffer->index]), s); | |
299 buffer->index += len; | |
300 return len; | |
301 } |