dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / exstr / exstr.c
blobd5cd595a8b999dc4bc36569eb5bb5cb162234814
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <signal.h>
35 #include <setjmp.h>
36 #include <string.h>
38 /* external functions */
40 extern int getopt();
41 extern void exit();
42 extern int atoi();
43 extern int _filbuf();
44 extern char *optarg;
45 extern int optind, opterr;
47 /* static functions */
49 static void extract();
50 static void replace();
51 static void yankstr();
52 static void badformat();
53 static void prstr();
54 static int getachar();
55 static void usage();
57 /* static variables */
59 static int eflg; /* find strings in source file(s) */
60 static int dflg; /* use replaced string a second argument */
61 static int rflg; /* replace strings by function calls */
62 static int errflg; /* syntax error on command line */
63 static char *Fname; /* name of source file */
64 static int Lineno; /* line number in source file */
65 static int Posno; /* character position within line */
66 static int flag; /* sets when newline is encountered */
67 static jmp_buf to_eof;
70 int
71 main(int argc, char *argv[])
73 int ch;
75 while ((ch = getopt(argc, argv, "erd")) != -1)
76 switch (ch) {
77 case 'e':
78 if (rflg)
79 errflg++;
80 else
81 eflg++;
82 continue;
83 case 'r':
84 if (eflg)
85 errflg++;
86 else
87 rflg++;
88 continue;
89 case 'd':
90 if (eflg)
91 errflg++;
92 else
93 dflg++;
94 continue;
95 default:
96 errflg++;
98 if (optind == argc || errflg)
99 usage();
100 if (!rflg)
101 for (; optind < argc; optind++)
102 extract(argv[optind]);
103 else {
104 if (optind+1 != argc)
105 usage();
106 replace(argv[optind]);
108 return (0);
111 static void
112 extract(name)
113 char *name;
115 if (freopen(name, "r", stdin) == NULL) {
116 (void) fprintf(
117 stderr, "exstr: ERROR: couldn't open file '%s'\n", name);
118 exit(1);
120 Fname = name;
121 flag = 1;
122 Lineno = 0;
124 if (setjmp(to_eof) != 0)
125 return;
127 for (;;) {
128 char ch;
130 ch = getachar();
132 switch (ch) {
133 case '#':
134 if (Posno != 0)
135 continue;
136 do {
137 ch = getachar();
138 } while (isspace(ch));
139 if (ch == 'd')
140 continue;
141 while (getachar() != '\n');
142 break;
143 case '"':
144 yankstr();
145 break;
146 case '\'':
147 while ((ch = getachar()) != '\'')
148 if (ch == '\\')
149 ch = getachar();
150 break;
152 case '/':
153 ch = getachar();
154 if (ch == '*') {
155 int level = 0;
156 while (level != 2) {
157 ch = getachar();
158 if (level == 0 && ch == '*')
159 level++;
160 else if (level == 1 && ch == '/')
161 level++;
162 else
163 level = 0;
166 break;
171 static void
172 yankstr()
174 char cc;
175 char dbuf[BUFSIZ];
176 register char *dp = dbuf;
177 int saved_posno;
178 int saved_lineno;
180 saved_posno = Posno;
181 saved_lineno = Lineno;
182 while ((cc = getachar()) != '"') {
183 if (cc == '\\') {
184 *dp++ = cc;
185 cc = getachar();
187 if (cc == '\n') {
188 dp--;
189 continue;
191 *dp++ = cc;
193 *dp = 0;
194 prstr(dbuf, saved_lineno, saved_posno);
197 static void
198 prstr(cp, lineno, posno)
199 register char *cp;
201 if (eflg)
202 (void) fprintf(stdout, "%s:%d:%d:::%s\n", Fname, lineno, posno,
203 cp);
204 else
205 (void) fprintf(stdout, "%s:%s\n", Fname, cp);
209 static void
210 usage()
212 (void) fprintf(stderr, "usage: exstr [-e] files\n");
213 (void) fprintf(stderr, "or : exstr -r [-d] file\n");
214 exit(1);
217 static int
218 getachar()
220 int cc;
222 cc = getchar();
223 if (flag) {
224 Lineno++;
225 Posno = 0;
226 flag = 0;
227 } else
228 Posno++;
229 if (cc == EOF)
230 longjmp(to_eof, 1);
231 if (cc == '\n')
232 flag = 1;
233 return (cc);
237 static void
238 replace(name)
239 char *name;
241 char linebuf[BUFSIZ];
242 char *cp;
243 int curlineno; /* line number in strings file */
244 int curposno; /* character position in string file */
245 int savelineno = 0;
246 int curmsgno; /* message number in strings file */
247 int wrong_msg; /* invalid message number */
248 int cont_str = 0; /* string continues in the next line */
249 char *repstr;
250 char repbuf[BUFSIZ], *repbufp;
251 char curline[BUFSIZ];
252 char outbuf[BUFSIZ];
253 /* keeps track of character position within input file */
254 char *inp;
255 /* keeps track of character position within output buffer */
256 char *outp;
257 char *msgfile;
258 FILE *fi; /* input source file pointer */
260 inp = linebuf;
261 outp = outbuf;
262 linebuf[0] = '\0';
263 /* open input C source file */
264 if ((fi = fopen(name, "r")) == NULL) {
265 (void) fprintf(stderr,
266 "exstr: ERROR: couldn't open file '%s'\n", name);
267 exit(1);
269 Fname = name;
271 (void) fprintf(stdout, "extern char *gettxt();\n");
273 /* process file containing the list of strings */
274 while (fgets(repbuf, sizeof (repbuf), stdin) != NULL) {
276 wrong_msg = 0;
278 /* save a copy of the current line */
279 (void) strcpy(curline, repbuf);
281 /* take apart the input string */
282 repbufp = strchr(repbuf, ':');
283 if (repbufp == NULL)
284 badformat(curline);
285 *repbufp++ = '\0';
286 /* verify that string belongs to the input C source file */
287 if (strcmp(repbuf, name) != 0)
288 continue;
289 repstr = strchr(repbufp, ':');
290 if (repstr == NULL)
291 badformat(curline);
292 *repstr++ = '\0';
293 curlineno = atoi(repbufp);
294 if (curlineno < savelineno) {
295 (void) fprintf(stderr,
296 "exstr: ERROR: stdin: line out of order\n");
297 (void) fprintf(stderr, "%s", curline);
298 exit(1);
300 savelineno = curlineno;
301 repbufp = repstr;
302 repstr = strchr(repbufp, ':');
303 if (repstr == NULL)
304 badformat(curline);
305 repstr[strlen(repstr) - 1 ] = '\0';
306 *repstr++ = '\0';
307 curposno = atoi(repbufp);
308 repbufp = repstr;
309 repstr = strchr(repbufp, ':');
310 if (repstr == NULL)
311 badformat(curline);
312 *repstr++ = '\0';
313 msgfile = repbufp;
314 if (strlen(msgfile) > (size_t)14 || *msgfile == '\0') {
315 (void) fprintf(stderr,
316 "exstr: ERROR: stdin: invalid message file name "
317 "'%s'\n", msgfile);
318 (void) fprintf(stderr, "%s", curline);
319 exit(1);
321 repbufp = repstr;
322 repstr = strchr(repbufp, ':');
323 if (repstr == NULL)
324 badformat(curline);
325 *repstr++ = '\0';
326 cp = repbufp;
327 while (*cp)
328 if (!isdigit(*cp++)) {
329 wrong_msg++;
330 break;
332 if (*repbufp == '\0' || wrong_msg) {
333 (void) fprintf(stderr, "exstr: ERROR: stdin: invalid "
334 "message number '%s'\n", repbufp);
335 (void) fprintf(stderr, "%s", curline);
336 exit(1);
338 curmsgno = atoi(repbufp);
340 /* move up to this line */
341 while (Lineno != curlineno) {
342 if (outp != outbuf) {
343 while (*inp != '\0')
344 *outp++ = *inp++;
345 *outp = '\0';
346 (void) fputs(outbuf, stdout);
347 } else if (*linebuf != '\0')
348 (void) fputs(linebuf, stdout);
349 outp = outbuf;
350 inp = linebuf;
351 if (fgets(linebuf,
352 sizeof (linebuf), fi) == NULL) {
353 (void) fprintf(stderr, "read error\n");
354 exit(1);
356 Lineno++;
357 Posno = 0;
359 if (Posno > curposno) {
360 (void) fprintf(stderr,
361 "Bad input record line number %d\n", Lineno);
362 exit(1);
364 while (Posno != curposno) {
365 *outp++ = *inp++;
366 Posno++;
368 if (*inp != '"') {
369 (void) fprintf(stderr, "exstr: ERROR: cannot replace "
370 "string '%s' in line (%d) of file (%s)\n", repstr,
371 Lineno, Fname);
372 exit(1);
374 /* check if string continues in next line */
375 while (inp[strlen(inp)-2] == '\\' &&
376 inp[strlen(inp)-1] == '\n') {
377 if (fgets(linebuf,
378 sizeof (linebuf), fi) == NULL) {
379 (void) fprintf(stderr, "exstr: ERROR: read "
380 "error in file (%s)\n", Fname);
381 exit(1);
383 cont_str++;
384 Lineno++;
386 if (cont_str) {
387 cp = linebuf;
388 while (*cp != '\0' && *cp++ != '"')
390 if (*cp == '\0') {
391 (void) fprintf(stderr, "exstr: ERROR: cannot "
392 "replace string '%s' in line (%d) of file "
393 "(%s)\n", repstr, Lineno, Fname);
394 exit(1);
396 inp = cp;
397 Posno = cp - linebuf;
399 if (dflg)
400 outp += snprintf(outp, BUFSIZ - (outp - outbuf),
401 "gettxt(\"%s:%d\", \"%s\")", msgfile, curmsgno,
402 repstr);
403 else
404 outp += snprintf(outp, BUFSIZ - (outp - outbuf),
405 "gettxt(\"%s:%d\", \"\")", msgfile, curmsgno);
406 if (!cont_str) {
407 inp += strlen(repstr)+2;
408 Posno += strlen(repstr)+2;
410 else
411 cont_str = 0;
413 if (outp != outbuf) {
414 while (*inp != '\0')
415 *outp++ = *inp++;
416 *outp = '\0';
417 (void) fputs(outbuf, stdout);
419 while (fgets(linebuf, sizeof (linebuf), fi) != NULL)
420 (void) fputs(linebuf, stdout);
422 (void) fclose(fi);
425 static void
426 badformat(line)
427 char *line;
429 (void) fprintf(stderr, "exstr: ERROR: stdin: Badly formatted "
430 "replacement string\n%s", line);
431 exit(1);