xref: /titanic_52/usr/src/cmd/exstr/exstr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
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.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.2	*/
27 
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <sys/types.h>
31 #include <signal.h>
32 #include <setjmp.h>
33 #include <string.h>
34 
35 /* external functions */
36 
37 extern	char 	*malloc();
38 extern	int	getopt();
39 extern	void	exit();
40 extern	int	atoi();
41 extern	int	_filbuf();
42 extern	char	*optarg;
43 extern	int	optind, opterr;
44 
45 /* static functions */
46 
47 static	void	extract();
48 static	void	replace();
49 static	void	yankstr();
50 static	void	badformat();
51 static	void	prstr();
52 static	int	getachar();
53 static  void	usage();
54 
55 /* static variables */
56 
57 static	int	eflg;		/* find strings in source file(s) */
58 static	int	dflg;           /* use replaced string a second argument */
59 static  int	rflg;		/* replace strings by function calls */
60 static  int	errflg;         /* syntax error on command line */
61 static  char	*Fname;		/* name of source file */
62 static  int	Lineno;		/* line number in source file */
63 static	int	Posno;		/* character position within line */
64 static  int	flag;           /* sets when newline is encountered */
65 static  jmp_buf	to_eof;
66 
67 
68 main(argc, argv)
69 int	argc;
70 char	*argv[];
71 {
72 	int	ch;
73 
74 	while ((ch = getopt(argc, argv, "erd")) != -1)
75 		switch(ch) {
76 		    case 'e':
77 			if (rflg)
78 				errflg++;
79 			else
80 				eflg++;
81 			continue;
82 		    case 'r':
83 			if (eflg)
84 				errflg++;
85 			else
86 				rflg++;
87 			continue;
88 		    case 'd':
89 			if (eflg)
90 				errflg++;
91 			else
92 				dflg++;
93 			continue;
94 		    default:
95 			errflg++;
96 		}
97 	if (optind ==  argc || errflg)
98 		usage();
99 	if (!rflg)
100 		for(;optind<argc;optind++)
101 			extract(argv[optind]);
102 	else  {
103 		if (optind+1 != argc)
104 			usage();
105 		replace(argv[optind]);
106 	}
107 	exit(0);
108 }
109 
110 static	void
111 extract(name)
112 char	*name;
113 {
114 	if (freopen(name,"r",stdin) == NULL) {
115 		(void)fprintf(stderr,"exstr: ERROR: couldn't open file '%s'\n",name);
116 		exit(1);
117 	}
118 	Fname = name;
119 	flag = 1;
120 	Lineno = 0;
121 
122 	if (setjmp(to_eof) != 0)
123 		return;
124 
125 	for (;;) {
126 		char ch;
127 
128 		ch = getachar();
129 
130 		switch (ch) {
131 		case '#':
132 			if (Posno != 0)
133 				continue;
134 			do {
135 				ch = getachar();
136 			} while (isspace(ch));
137 			if (ch == 'd')
138 				continue;
139 			while (getachar() != '\n');
140 			break;
141 		case '"':
142 			yankstr();
143 			break;
144 		case '\'':
145 			while ((ch = getachar()) != '\'')
146 				if (ch == '\\')
147 					ch = getachar();
148 			break;
149 
150 		case '/':
151 			ch = getachar();
152 			if (ch == '*') {
153 				int level = 0;
154 				while(level != 2) {
155 					ch = getachar();
156 					if (level == 0 && ch == '*')
157 						level++;
158 					else if (level == 1 && ch == '/')
159 						level++;
160 					else
161 						level = 0;
162 				}
163 			}
164 			break;
165 		}
166 	}
167 }
168 
169 static	void
170 yankstr()
171 {
172 	char cc;
173 	char dbuf[BUFSIZ];
174 	register char *dp = dbuf;
175 	int saved_posno;
176 	int saved_lineno;
177 
178 	saved_posno = Posno;
179 	saved_lineno = Lineno;
180 	while ((cc = getachar()) != '"') {
181 		if(cc == '\\') {
182 			*dp++ = cc;
183 			cc = getachar();
184 		}
185 		if (cc == '\n') {
186 			dp--;
187 			continue;
188 		}
189 		*dp++ = cc;
190 	}
191 	*dp = 0;
192 	prstr(dbuf,saved_lineno,saved_posno);
193 }
194 
195 static	void
196 prstr(cp, lineno, posno)
197 register char *cp;
198 {
199 	if (eflg)
200 		(void)fprintf(stdout, "%s:%d:%d:::%s\n", Fname, lineno, posno, cp);
201 	else
202 		(void)fprintf(stdout, "%s:%s\n", Fname, cp);
203 
204 }
205 
206 static	void
207 usage()
208 {
209 	(void)fprintf(stderr, "usage: exstr [-e] files\n");
210 	(void)fprintf(stderr, "or   : exstr -r [-d] file\n");
211 	exit(1);
212 }
213 
214 static	int
215 getachar()
216 {
217 	int cc;
218 
219 	cc = getchar();
220 	if (flag) {
221 		Lineno++;
222 		Posno = 0;
223 		flag = 0;
224 	} else
225 		Posno++;
226 	if (cc == EOF)
227 		longjmp(to_eof, 1);
228 	if (cc == '\n')
229 		flag = 1;
230 	return(cc);
231 }
232 
233 
234 static void
235 replace(name)
236 char	*name;
237 {
238 	char	linebuf[BUFSIZ];	/* buffer to read lines from source file */
239 	char	*cp;
240 	int	curlineno;		/* line number in strings file */
241 	int	curposno;		/* character position in string file */
242 	int	savelineno = 0;
243 	int	curmsgno;		/* message number in strings file */
244 	int	wrong_msg;		/* invalid message number */
245 	int	cont_str = 0;		/* string continues in the next line */
246 	char	*repstr;
247 	char	repbuf[BUFSIZ], *repbufp;
248 	char	curline[BUFSIZ];
249 	char	outbuf[BUFSIZ];
250 	char	*inp;			/* keeps track of character position within input file */
251 	char	*outp;			/* keeps track of character position within output buffer */
252 	char	*msgfile;
253 	FILE	*fi;			/* input source file pointer */
254 
255 	inp = linebuf;
256 	outp = outbuf;
257 	linebuf[0] = '\0';
258 	/* open input C source file */
259 	if ((fi = fopen(name,"r")) == (FILE *)NULL) {
260 		(void)fprintf(stderr,"exstr: ERROR: couldn't open file '%s'\n",name);
261 		exit(1);
262 	}
263 	Fname = name;
264 
265 	(void)fprintf(stdout, "extern char *gettxt();\n");
266 
267 	/* process file containing the list of strings */
268 	while (fgets(repbuf,sizeof repbuf, stdin) != (char *)NULL) {
269 
270 		wrong_msg = 0;
271 
272 		/* save a copy of the current line */
273 		(void)strcpy(curline, repbuf);
274 
275 		/* take apart the input string */
276 		repbufp = strchr(repbuf,':');
277 		if (repbufp == (char *)NULL)
278 			badformat(curline);
279 		*repbufp++ = '\0';
280 		/* verify that string belongs to the input C source file */
281 		if (strcmp(repbuf, name) != NULL)
282 			continue;
283 		repstr = strchr(repbufp,':');
284 		if (repstr == (char *)NULL)
285 			badformat(curline);
286 		*repstr++ = '\0';
287 		curlineno = atoi(repbufp);
288 		if (curlineno < savelineno) {
289 			(void)fprintf(stderr, "exstr: ERROR: stdin: line out of order\n");
290 			(void)fprintf(stderr, "%s", curline);
291 			exit(1);
292 		}
293 		savelineno = curlineno;
294 		repbufp = repstr;
295 		repstr = strchr(repbufp,':');
296 		if (repstr == (char *)NULL)
297 			badformat(curline);
298 		repstr[strlen(repstr) - 1 ] = '\0';
299 		*repstr++ = '\0';
300 		curposno = atoi(repbufp);
301 		repbufp = repstr;
302 		repstr = strchr(repbufp,':');
303 		if (repstr == (char *)NULL)
304 			badformat(curline);
305 		*repstr++ = '\0';
306 		msgfile = repbufp;
307 		if ( strlen(msgfile) > (size_t) 14 || *msgfile == '\0' ){
308 			(void)fprintf(stderr, "exstr: ERROR: stdin: invalid message file name '%s'\n", msgfile);
309 			(void)fprintf(stderr, "%s", curline);
310 			exit(1);
311 		}
312 		repbufp = repstr;
313 		repstr = strchr(repbufp,':');
314 		if (repstr == (char *)NULL)
315 			badformat(curline);
316 		*repstr++ = '\0';
317 		cp = repbufp;
318 		while(*cp)
319 			if(!isdigit(*cp++)) {
320 				wrong_msg++;
321 				break;
322 			}
323 		if ( *repbufp == '\0' || wrong_msg ) {
324 			(void)fprintf(stderr, "exstr: ERROR: stdin: invalid message number '%s'\n", repbufp);
325 			(void)fprintf(stderr, "%s", curline);
326 			exit(1);
327 			}
328 		curmsgno = atoi(repbufp);
329 
330 		/* move up to this line */
331 		while (Lineno != curlineno ) {
332 			if (outp != outbuf) {
333 				while(*inp != '\0')
334 					*outp++ = *inp++;
335 				*outp = '\0';
336 				(void)fputs(outbuf,stdout);
337 			} else if (*linebuf != '\0')
338 				(void)fputs(linebuf,stdout);
339 			outp = outbuf;
340 			inp = linebuf;
341 			if (fgets(linebuf, sizeof linebuf, fi) == (char *)NULL) {
342 				(void)fprintf(stderr, "read error\n");
343 				exit(1);
344 			}
345 			Lineno++;
346 			Posno = 0;
347 		}
348 		if (Posno > curposno) {
349 			(void)fprintf(stderr, "Bad input record line number %d\n",Lineno);
350 			exit(1);
351 		}
352 		while (Posno != curposno) {
353 			*outp++ = *inp++;
354 			Posno++;
355 		}
356 		if (*inp != '"') {
357 			fprintf(stderr, "exstr: ERROR: cannot replace string '%s' in line (%d) of file (%s)\n", repstr, Lineno, Fname);
358 			exit(1);
359 		}
360 		/* check if string continues in next line */
361 		while (inp[strlen(inp)-2] == '\\' && inp[strlen(inp)-1] == '\n') {
362 			if (fgets(linebuf,sizeof linebuf, fi) == (char *)NULL) {
363 				fprintf(stderr, "exstr: ERROR: read error in file (%s)\n", Fname);
364 				exit(1);
365 			}
366 			cont_str++;
367 			Lineno++;
368 		}
369 		if (cont_str) {
370 			cp = linebuf;
371 			while (*cp != '\0' && *cp++ != '"') ;
372 			if (*cp == '\0') {
373 				fprintf(stderr, "exstr: ERROR: cannot replace string '%s' in line (%d) of file (%s)\n", repstr, Lineno, Fname);
374 				exit(1);
375 			}
376 			inp = cp;
377 			Posno = cp - linebuf;
378 		}
379 		if (dflg)
380 			outp += sprintf(outp,"gettxt(\"%s:%d\", \"%s\")",msgfile, curmsgno, repstr);
381 		else
382 			outp += sprintf(outp,"gettxt(\"%s:%d\", \"\")",msgfile,curmsgno);
383 		if (!cont_str) {
384 			inp += strlen(repstr)+2;
385 			Posno += strlen(repstr)+2;
386 		}
387 		else
388 			cont_str = 0;
389 	}
390 	if (outp != outbuf) {
391 		while(*inp != '\0')
392 			*outp++ = *inp++;
393 		*outp = '\0';
394 		(void)fputs(outbuf,stdout);
395 	}
396 	while(fgets(linebuf,sizeof linebuf, fi) != (char *)NULL)
397 		(void)fputs(linebuf, stdout);
398 
399 }
400 
401 static	void
402 badformat(line)
403 char  	*line;
404 {
405 	(void)fprintf(stderr, "exstr: ERROR: stdin: Badly formatted replacement string\n%s", line);
406 	exit(1);
407 }
408