xref: /dragonfly/contrib/tcsh-6/gethost.c (revision 279dd846)
1 /* $Header: /p/tcsh/cvsroot/tcsh/gethost.c,v 1.15 2012/01/15 17:14:54 christos Exp $ */
2 /*
3  * gethost.c: Create version file from prototype
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include "sh.h"
34 
35 RCSID("$tcsh: gethost.c,v 1.15 2012/01/15 17:14:54 christos Exp $")
36 
37 #ifdef SCO
38 # define perror __perror
39 # define rename __rename
40 # define getopt __getopt
41 # define system __system
42 #endif
43 #include <stdio.h>
44 #ifdef SCO
45 # undef perror
46 # undef rename
47 # undef getopt
48 # undef system
49 #endif
50 
51 #include <ctype.h>
52 
53 #define ISSPACE(p)	(isspace((unsigned char) (p)) && (p) != '\n')
54 
55 /*
56  * We cannot do that, because some compilers like #line and others
57  * like # <lineno>
58  * #define LINEDIRECTIVE
59  */
60 
61 static const char *keyword[] =
62 {
63     "vendor",
64 #define T_VENDOR	0
65     "hosttype",
66 #define T_HOSTTYPE	1
67     "machtype",
68 #define T_MACHTYPE	2
69     "ostype",
70 #define T_OSTYPE	3
71     "newdef",
72 #define T_NEWDEF	4
73     "enddef",
74 #define T_ENDDEF	5
75     "newcode",
76 #define T_NEWCODE	6
77     "endcode",
78 #define T_ENDCODE	7
79     "comment",
80 #define T_COMMENT	8
81     "macro",
82 #define T_MACRO		9
83     NULL
84 #define T_NONE		10
85 };
86 
87 #define S_DISCARD	0
88 #define S_COMMENT	1
89 #define S_CODE		2
90 #define S_KEYWORD	3
91 
92 static int findtoken (char *);
93 static char *gettoken (char **, char  *);
94 static char *pname;
95 
96 int main (int, char *[]);
97 
98 /* findtoken():
99  *	Return the token number of the given token
100  */
101 static int
102 findtoken(char *ptr)
103 {
104     int i;
105 
106     if (ptr == NULL || *ptr == '\0')
107 	return T_NONE;
108 
109     for (i = 0; keyword[i] != NULL; i++)
110 	if (strcmp(keyword[i], ptr) == 0)
111 	    return i;
112 
113     return T_NONE;
114 }
115 
116 
117 /* gettoken():
118  *	Get : delimited token and remove leading/trailing blanks/newlines
119  */
120 static char *
121 gettoken(char **pptr, char *token)
122 {
123     char *ptr = *pptr;
124     char *tok = token;
125 
126     for (; *ptr && ISSPACE(*ptr); ptr++)
127 	continue;
128 
129     for (; *ptr && *ptr != ':'; *tok++ = *ptr++)
130 	continue;
131 
132     if (*ptr == ':')
133 	ptr++;
134     else
135 	tok--;
136 
137     for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--)
138 	continue;
139 
140     *++tok = '\0';
141 
142     *pptr = ptr;
143     return token;
144 }
145 
146 static char *
147 cat(const char *a, const char *b, size_t len)
148 {
149 	size_t l;
150 	char *r;
151 
152 	if (len == 0)
153 		len = strlen(b);
154 	l = strlen(a) + len + 1;
155 	if ((r = malloc(l)) == NULL)
156 		abort();
157 	snprintf(r, l, "%s%.*s", a, (int)len, b);
158 	return r;
159 }
160 
161 static const char *
162 explode(const char *defs)
163 {
164 	static const char def[] = "defined("; /* ) */
165 	static char *buf;
166 	size_t len;
167 	const char *ptr, *bptr, *eptr = NULL, *name;
168 
169 	if (strstr(defs, "#machine(" /* ) */))
170 		return defs;
171 
172 	free(buf);
173 	buf = strdup("("); /* ) */
174 	for (ptr = defs; (bptr = strstr(ptr, def)) != NULL; ptr = eptr + 1) {
175 		if (ptr != bptr)
176 			buf = cat(buf, ptr, bptr - ptr);
177 		if ((eptr = strchr(ptr + sizeof(def) - 1, ')')) == NULL) {
178 			(void) fprintf(stderr, "%s: missing close paren `%s'\n",
179 			    pname, defs);
180 			return defs;
181 		}
182 		buf = cat(buf, bptr, eptr - bptr + 1);
183 		name = bptr + sizeof(def) - 1;
184 		len = eptr - name;
185 		if (len < 1) {
186 			(void) fprintf(stderr, "%s: empty define `%s'\n",
187 			    pname, defs);
188 			return defs;
189 		}
190 		if (*name != '_') {
191 			char *undername = malloc(len + 10);
192 			buf = cat(buf, " || defined(", 0);
193 			snprintf(undername, len + 10, "__%.*s__)", (int)len,
194 			    name);
195 			buf = cat(buf, undername, len + 5);
196 			buf = cat(buf, " || defined(", 0);
197 			snprintf(undername, len + 10, "__%.*s)", (int)len,
198 			    name);
199 			buf = cat(buf, undername, len + 3);
200 		}
201 	}
202 	if (!eptr) {
203 	    (void) fprintf(stderr, "%s: invalid input `%s'\n", pname, defs);
204 	    return defs;
205         }
206 	buf = cat(buf, eptr + 1, 0);
207 	buf = cat(buf, ")", 0);
208 	return buf;
209 }
210 
211 
212 int
213 main(int argc, char *argv[])
214 {
215     char line[INBUFSIZE];
216     const char *fname = "stdin";
217     char *ptr, *tok;
218     char defs[INBUFSIZE];
219     char stmt[INBUFSIZE];
220     FILE *fp = stdin;
221     int lineno = 0;
222     int inprocess = 0;
223     int token, state;
224     int errs = 0;
225 
226     if ((pname = strrchr(argv[0], '/')) == NULL)
227 	pname = argv[0];
228     else
229 	pname++;
230 
231     if (argc > 2) {
232 	(void) fprintf(stderr, "Usage: %s [<filename>]\n", pname);
233 	return 1;
234     }
235 
236     if (argc == 2)
237 	if ((fp = fopen(fname = argv[1], "r")) == NULL) {
238 	    (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname);
239 	    return 1;
240 	}
241 
242     state = S_DISCARD;
243 
244     while ((ptr = fgets(line, sizeof(line), fp)) != NULL) {
245 	lineno++;
246 	switch (token = findtoken(gettoken(&ptr, defs))) {
247 	case T_NEWCODE:
248 	    state = S_CODE;
249 	    break;
250 
251 	case T_ENDCODE:
252 	    state = S_DISCARD;
253 	    break;
254 
255 	case T_COMMENT:
256 	    state = S_COMMENT;
257 	    break;
258 
259 	case T_NEWDEF:
260 	    state = S_KEYWORD;
261 	    break;
262 
263 	case T_ENDDEF:
264 	    state = S_DISCARD;
265 	    break;
266 
267 	case T_VENDOR:
268 	    state = S_KEYWORD;
269 	    break;
270 
271 	case T_HOSTTYPE:
272 	    state = S_KEYWORD;
273 	    break;
274 
275 	case T_MACHTYPE:
276 	    state = S_KEYWORD;
277 	    break;
278 
279 	case T_OSTYPE:
280 	    state = S_KEYWORD;
281 	    break;
282 
283 	case T_MACRO:
284 	    if (gettoken(&ptr, defs) == NULL) {
285 		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n",
286 			       pname, fname, lineno);
287 		break;
288 	    }
289 	    if (gettoken(&ptr, stmt) == NULL) {
290 		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n",
291 			       pname, fname, lineno);
292 		break;
293 	    }
294 	    (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt,
295 			   defs);
296 	    break;
297 
298 	case T_NONE:
299 	    if (state != S_CODE && *defs != '\0') {
300 		(void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n",
301 			       pname, fname, lineno);
302 		if (++errs == 30) {
303 		    (void) fprintf(stderr, "%s: Too many errors\n", pname);
304 		    return 1;
305 		}
306 		break;
307 	    }
308 	    (void) fprintf(stdout, "%s", line);
309 	    break;
310 
311 	default:
312 	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n",
313 			   pname, fname, lineno);
314 	    return 1;
315 	}
316 
317 	switch (state) {
318 	case S_DISCARD:
319 	    if (inprocess) {
320 		inprocess = 0;
321 		(void) fprintf(stdout, "#endif\n");
322 	    }
323 	    break;
324 
325 	case S_KEYWORD:
326 	    tok = gettoken(&ptr, defs);
327 	    if (token == T_NEWDEF) {
328 		if (inprocess) {
329 		    (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
330 				   pname, fname, lineno);
331 		    return 1;
332 		}
333 		if (tok == NULL) {
334 		    (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n",
335 				   pname, fname, lineno);
336 		    return 1;
337 		}
338 		(void) fprintf(stdout, "\n\n");
339 #ifdef LINEDIRECTIVE
340 		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
341 #endif /* LINEDIRECTIVE */
342 		(void) fprintf(stdout, "#if %s\n", defs);
343 		inprocess = 1;
344 	    }
345 	    else {
346 		if (tok && *tok)
347 		    (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n",
348 				   explode(defs), keyword[token]);
349 		else
350 		    (void) fprintf(stdout, "# if !defined(_%s_)\n",
351 				   keyword[token]);
352 
353 		if (gettoken(&ptr, stmt) == NULL) {
354 		    (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n",
355 				   pname, fname, lineno);
356 		    return 1;
357 		}
358 		(void) fprintf(stdout, "# define _%s_\n", keyword[token]);
359 		(void) fprintf(stdout, "    %s = %s;\n", keyword[token], stmt);
360 		(void) fprintf(stdout, "# endif\n");
361 	    }
362 	    break;
363 
364 	case S_COMMENT:
365 	    if (gettoken(&ptr, defs))
366 		(void) fprintf(stdout, "    /* %s */\n", defs);
367 	    break;
368 
369 	case S_CODE:
370 	    if (token == T_NEWCODE) {
371 #ifdef LINEDIRECTIVE
372 		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
373 #endif /* LINEDIRECTIVE */
374 	    }
375 	    break;
376 
377 	default:
378 	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n",
379 			   pname, fname, lineno);
380 	    return 1;
381 	}
382     }
383 
384     if (inprocess) {
385 	(void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
386 		       pname, fname, lineno);
387 	return 1;
388     }
389 
390     if (fp != stdin)
391 	(void) fclose(fp);
392 
393     return 0;
394 }
395