xref: /freebsd/contrib/tcsh/gethost.c (revision 87569f75a91f298c52a71823c04d41cf53c88889)
1 /* $Header: /src/pub/tcsh/gethost.c,v 1.10 2005/01/05 16:06:13 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("$Id: gethost.c,v 1.10 2005/01/05 16:06:13 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 __P((char *));
93 static char *gettoken __P((char **, char  *));
94 
95 int main __P((int, char *[]));
96 
97 /* findtoken():
98  *	Return the token number of the given token
99  */
100 static int
101 findtoken(ptr)
102     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(pptr, token)
122     char **pptr;
123     char  *token;
124 {
125     char *ptr = *pptr;
126     char *tok = token;
127 
128     for (; *ptr && ISSPACE(*ptr); ptr++)
129 	continue;
130 
131     for (; *ptr && *ptr != ':'; *tok++ = *ptr++)
132 	continue;
133 
134     if (*ptr == ':')
135 	ptr++;
136     else
137 	tok--;
138 
139     for (tok--; tok >= token && *tok && ISSPACE(*tok); tok--)
140 	continue;
141 
142     *++tok = '\0';
143 
144     *pptr = ptr;
145     return token;
146 }
147 
148 
149 int
150 main(argc, argv)
151     int argc;
152     char *argv[];
153 {
154     char line[INBUFSIZE];
155     char *pname;
156     const char *fname = "stdin";
157     char *ptr, *tok;
158     char defs[INBUFSIZE];
159     char stmt[INBUFSIZE];
160     FILE *fp = stdin;
161     int lineno = 0;
162     int inprocess = 0;
163     int token, state;
164     int errs = 0;
165 
166     if ((pname = strrchr(argv[0], '/')) == NULL)
167 	pname = argv[0];
168     else
169 	pname++;
170 
171     if (argc > 2) {
172 	(void) fprintf(stderr, "Usage: %s [<filename>]\n", pname);
173 	return 1;
174     }
175 
176     if (argc == 2)
177 	if ((fp = fopen(fname = argv[1], "r")) == NULL) {
178 	    (void) fprintf(stderr, "%s: Cannot open `%s'\n", pname, fname);
179 	    return 1;
180 	}
181 
182     state = S_DISCARD;
183 
184     while ((ptr = fgets(line, sizeof(line), fp)) != NULL) {
185 	lineno++;
186 	switch (token = findtoken(gettoken(&ptr, defs))) {
187 	case T_NEWCODE:
188 	    state = S_CODE;
189 	    break;
190 
191 	case T_ENDCODE:
192 	    state = S_DISCARD;
193 	    break;
194 
195 	case T_COMMENT:
196 	    state = S_COMMENT;
197 	    break;
198 
199 	case T_NEWDEF:
200 	    state = S_KEYWORD;
201 	    break;
202 
203 	case T_ENDDEF:
204 	    state = S_DISCARD;
205 	    break;
206 
207 	case T_VENDOR:
208 	    state = S_KEYWORD;
209 	    break;
210 
211 	case T_HOSTTYPE:
212 	    state = S_KEYWORD;
213 	    break;
214 
215 	case T_MACHTYPE:
216 	    state = S_KEYWORD;
217 	    break;
218 
219 	case T_OSTYPE:
220 	    state = S_KEYWORD;
221 	    break;
222 
223 	case T_MACRO:
224 	    if (gettoken(&ptr, defs) == NULL) {
225 		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro name\n",
226 			       pname, fname, lineno);
227 		break;
228 	    }
229 	    if (gettoken(&ptr, stmt) == NULL) {
230 		(void) fprintf(stderr, "%s: \"%s\", %d: Missing macro body\n",
231 			       pname, fname, lineno);
232 		break;
233 	    }
234 	    (void) fprintf(stdout, "\n#if %s\n# define %s\n#endif\n\n", stmt,
235 			   defs);
236 	    break;
237 
238 	case T_NONE:
239 	    if (state != S_CODE && defs && *defs != '\0') {
240 		(void) fprintf(stderr, "%s: \"%s\", %d: Discarded\n",
241 			       pname, fname, lineno);
242 		if (++errs == 30) {
243 		    (void) fprintf(stderr, "%s: Too many errors\n", pname);
244 		    return 1;
245 		}
246 		break;
247 	    }
248 	    (void) fprintf(stdout, "%s", line);
249 	    break;
250 
251 	default:
252 	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected token\n",
253 			   pname, fname, lineno);
254 	    return 1;
255 	}
256 
257 	switch (state) {
258 	case S_DISCARD:
259 	    if (inprocess) {
260 		inprocess = 0;
261 		(void) fprintf(stdout, "#endif\n");
262 	    }
263 	    break;
264 
265 	case S_KEYWORD:
266 	    tok = gettoken(&ptr, defs);
267 	    if (token == T_NEWDEF) {
268 		if (inprocess) {
269 		    (void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
270 				   pname, fname, lineno);
271 		    return 1;
272 		}
273 		if (tok == NULL) {
274 		    (void) fprintf(stderr, "%s: \"%s\", %d: No defs\n",
275 				   pname, fname, lineno);
276 		    return 1;
277 		}
278 		(void) fprintf(stdout, "\n\n");
279 #ifdef LINEDIRECTIVE
280 		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
281 #endif /* LINEDIRECTIVE */
282 		(void) fprintf(stdout, "#if %s\n", defs);
283 		inprocess = 1;
284 	    }
285 	    else {
286 		if (tok && *tok)
287 		    (void) fprintf(stdout, "# if (%s) && !defined(_%s_)\n",
288 				   defs, keyword[token]);
289 		else
290 		    (void) fprintf(stdout, "# if !defined(_%s_)\n",
291 				   keyword[token]);
292 
293 		if (gettoken(&ptr, stmt) == NULL) {
294 		    (void) fprintf(stderr, "%s: \"%s\", %d: No statement\n",
295 				   pname, fname, lineno);
296 		    return 1;
297 		}
298 		(void) fprintf(stdout, "# define _%s_\n", keyword[token]);
299 		(void) fprintf(stdout, "    %s = %s;\n", keyword[token], stmt);
300 		(void) fprintf(stdout, "# endif\n");
301 	    }
302 	    break;
303 
304 	case S_COMMENT:
305 	    if (gettoken(&ptr, defs))
306 		(void) fprintf(stdout, "    /* %s */\n", defs);
307 	    break;
308 
309 	case S_CODE:
310 	    if (token == T_NEWCODE) {
311 #ifdef LINEDIRECTIVE
312 		(void) fprintf(stdout, "# %d \"%s\"\n", lineno + 1, fname);
313 #endif /* LINEDIRECTIVE */
314 	    }
315 	    break;
316 
317 	default:
318 	    (void) fprintf(stderr, "%s: \"%s\", %d: Unexpected state\n",
319 			   pname, fname, lineno);
320 	    return 1;
321 	}
322     }
323 
324     if (inprocess) {
325 	(void) fprintf(stderr, "%s: \"%s\", %d: Missing enddef\n",
326 		       pname, fname, lineno);
327 	return 1;
328     }
329 
330     if (fp != stdin)
331 	(void) fclose(fp);
332 
333     return 0;
334 }
335