xref: /freebsd/contrib/tcsh/gethost.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /* $Header: /src/pub/tcsh/gethost.c,v 1.7 1997/10/28 22:34:19 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. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 #include "sh.h"
38 
39 RCSID("$Id: gethost.c,v 1.7 1997/10/28 22:34:19 christos Exp $")
40 
41 #ifdef SCO
42 # define perror __perror
43 # define rename __rename
44 # define getopt __getopt
45 # define system __system
46 #endif
47 #include <stdio.h>
48 #ifdef SCO
49 # undef perror
50 # undef rename
51 # undef getopt
52 # undef system
53 #endif
54 
55 #include <ctype.h>
56 
57 /* Some people don't bother to declare these */
58 #if defined(SUNOS4) || defined(ibm032)
59 extern int fprintf();
60 extern int fclose();
61 #endif /* SUNOS4 || ibm032 */
62 
63 #define ISSPACE(p)	(isspace((unsigned char) (p)) && (p) != '\n')
64 
65 /*
66  * We cannot do that, because some compilers like #line and others
67  * like # <lineno>
68  * #define LINEDIRECTIVE
69  */
70 
71 static const char *keyword[] =
72 {
73     "vendor",
74 #define T_VENDOR	0
75     "hosttype",
76 #define T_HOSTTYPE	1
77     "machtype",
78 #define T_MACHTYPE	2
79     "ostype",
80 #define T_OSTYPE	3
81     "newdef",
82 #define T_NEWDEF	4
83     "enddef",
84 #define T_ENDDEF	5
85     "newcode",
86 #define T_NEWCODE	6
87     "endcode",
88 #define T_ENDCODE	7
89     "comment",
90 #define T_COMMENT	8
91     "macro",
92 #define T_MACRO		9
93     NULL
94 #define T_NONE		10
95 };
96 
97 #define S_DISCARD	0
98 #define S_COMMENT	1
99 #define S_CODE		2
100 #define S_KEYWORD	3
101 
102 static int findtoken __P((char *));
103 static char *gettoken __P((char **, char  *));
104 
105 int main __P((int, char *[]));
106 
107 /* findtoken():
108  *	Return the token number of the given token
109  */
110 static int
111 findtoken(ptr)
112     char *ptr;
113 {
114     int i;
115 
116     if (ptr == NULL || *ptr == '\0')
117 	return T_NONE;
118 
119     for (i = 0; keyword[i] != NULL; i++)
120 	if (strcmp(keyword[i], ptr) == 0)
121 	    return i;
122 
123     return T_NONE;
124 }
125 
126 
127 /* gettoken():
128  *	Get : delimited token and remove leading/trailing blanks/newlines
129  */
130 static char *
131 gettoken(pptr, token)
132     char **pptr;
133     char  *token;
134 {
135     char *ptr = *pptr;
136     char *tok = token;
137 
138     for (; *ptr && ISSPACE(*ptr); ptr++)
139 	continue;
140 
141     for (; *ptr && *ptr != ':'; *tok++ = *ptr++)
142 	continue;
143 
144     if (*ptr == ':')
145 	ptr++;
146     else
147 	tok--;
148 
149     for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--)
150 	continue;
151 
152     *++tok = '\0';
153 
154     *pptr = ptr;
155     return token;
156 }
157 
158 
159 int
160 main(argc, argv)
161     int argc;
162     char *argv[];
163 {
164     char line[INBUFSIZE];
165     char *pname;
166     char *fname = "stdin";
167     char *ptr, *tok;
168     char defs[INBUFSIZE];
169     char stmt[INBUFSIZE];
170     FILE *fp = stdin;
171     int lineno = 0;
172     int inprocess = 0;
173     int token, state;
174     int errs = 0;
175 
176     if ((pname = strrchr(argv[0], '/')) == NULL)
177 	pname = argv[0];
178     else
179 	pname++;
180 
181     if (argc > 2) {
182 	(void) fprintf(stderr, "Usage: %s [<filename>]\n", pname);
183 	return 1;
184     }
185 
186     if (argc == 2)
187 	if ((fp = fopen(fname = argv[1], "r")) == NULL) {
188 	    (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname);
189 	    return 1;
190 	}
191 
192     state = S_DISCARD;
193 
194     while ((ptr = fgets(line, sizeof(line), fp)) != NULL) {
195 	lineno++;
196 	switch (token = findtoken(gettoken(&ptr, defs))) {
197 	case T_NEWCODE:
198 	    state = S_CODE;
199 	    break;
200 
201 	case T_ENDCODE:
202 	    state = S_DISCARD;
203 	    break;
204 
205 	case T_COMMENT:
206 	    state = S_COMMENT;
207 	    break;
208 
209 	case T_NEWDEF:
210 	    state = S_KEYWORD;
211 	    break;
212 
213 	case T_ENDDEF:
214 	    state = S_DISCARD;
215 	    break;
216 
217 	case T_VENDOR:
218 	    state = S_KEYWORD;
219 	    break;
220 
221 	case T_HOSTTYPE:
222 	    state = S_KEYWORD;
223 	    break;
224 
225 	case T_MACHTYPE:
226 	    state = S_KEYWORD;
227 	    break;
228 
229 	case T_OSTYPE:
230 	    state = S_KEYWORD;
231 	    break;
232 
233 	case T_MACRO:
234 	    if (gettoken(&ptr, defs) == NULL) {
235 		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n",
236 			       pname, fname, lineno);
237 		break;
238 	    }
239 	    if (gettoken(&ptr, stmt) == NULL) {
240 		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n",
241 			       pname, fname, lineno);
242 		break;
243 	    }
244 	    (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt,
245 			   defs);
246 	    break;
247 
248 	case T_NONE:
249 	    if (state != S_CODE && defs && *defs != '\0') {
250 		(void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n",
251 			       pname, fname, lineno);
252 		if (++errs == 30) {
253 		    (void) fprintf(stderr, "%s: Too many errors\n", pname);
254 		    return 1;
255 		}
256 		break;
257 	    }
258 	    (void) fprintf(stdout, "%s", line);
259 	    break;
260 
261 	default:
262 	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n",
263 			   pname, fname, lineno);
264 	    return 1;
265 	}
266 
267 	switch (state) {
268 	case S_DISCARD:
269 	    if (inprocess) {
270 		inprocess = 0;
271 		(void) fprintf(stdout, "#endif\n");
272 	    }
273 	    break;
274 
275 	case S_KEYWORD:
276 	    tok = gettoken(&ptr, defs);
277 	    if (token == T_NEWDEF) {
278 		if (inprocess) {
279 		    (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
280 				   pname, fname, lineno);
281 		    return 1;
282 		}
283 		if (tok == NULL) {
284 		    (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n",
285 				   pname, fname, lineno);
286 		    return 1;
287 		}
288 		(void) fprintf(stdout, "\n\n");
289 #ifdef LINEDIRECTIVE
290 		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
291 #endif /* LINEDIRECTIVE */
292 		(void) fprintf(stdout, "#if %s\n", defs);
293 		inprocess = 1;
294 	    }
295 	    else {
296 		if (tok && *tok)
297 		    (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n",
298 				   defs, keyword[token]);
299 		else
300 		    (void) fprintf(stdout, "# if !defined(_%s_)\n",
301 				   keyword[token]);
302 
303 		if (gettoken(&ptr, stmt) == NULL) {
304 		    (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n",
305 				   pname, fname, lineno);
306 		    return 1;
307 		}
308 		(void) fprintf(stdout, "# define _%s_\n", keyword[token]);
309 		(void) fprintf(stdout, "    %s = %s;\n", keyword[token], stmt);
310 		(void) fprintf(stdout, "# endif\n");
311 	    }
312 	    break;
313 
314 	case S_COMMENT:
315 	    if (gettoken(&ptr, defs))
316 		(void) fprintf(stdout, "    /* %s */\n", defs);
317 	    break;
318 
319 	case S_CODE:
320 	    if (token == T_NEWCODE) {
321 #ifdef LINEDIRECTIVE
322 		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
323 #endif /* LINEDIRECTIVE */
324 	    }
325 	    break;
326 
327 	default:
328 	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n",
329 			   pname, fname, lineno);
330 	    return 1;
331 	}
332     }
333 
334     if (inprocess) {
335 	(void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
336 		       pname, fname, lineno);
337 	return 1;
338     }
339 
340     if (fp != stdin)
341 	(void) fclose(fp);
342 
343     return 0;
344 }
345