]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
f083c6c3 A |
6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
7 | * | |
8 | * This file contains Original Code and/or Modifications of Original Code | |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14c7c974 A |
14 | * |
15 | * The Original Code and all software distributed under the License are | |
f083c6c3 | 16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
14c7c974 A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
f083c6c3 A |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
14c7c974 A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* | |
26 | * Copyright 1993 NeXT Computer, Inc. | |
27 | * All rights reserved. | |
28 | */ | |
29 | ||
30 | /* | |
31 | * Standalone Interface Generator | |
32 | * | |
33 | * Input file format: a series of lines of the form: | |
34 | * | |
35 | * #<text> | |
36 | * or | |
37 | * <function declaration> <arg list> ; | |
38 | * | |
39 | * e.g.: | |
40 | * void *malloc(int len) len; | |
41 | * | |
42 | * Lines starting with '#' are passed through unchanged. | |
43 | * Lines starting with '/' are ignored. | |
44 | * | |
45 | * | |
46 | */ | |
47 | ||
48 | #import <stdio.h> | |
49 | #import <ctype.h> | |
50 | #import <string.h> | |
51 | #import <stdlib.h> | |
52 | #import <sys/param.h> | |
53 | ||
54 | #define MAXLINE 65535 | |
55 | typedef enum {NO=0, YES=1} BOOL; | |
56 | #define strdup(str) ((char *)strcpy(malloc(strlen(str)+1),str)) | |
57 | extern int getopt(); | |
58 | ||
59 | enum { | |
60 | none, | |
61 | external, | |
62 | internal, | |
63 | table, | |
64 | defs | |
65 | } which; | |
66 | char *osuffix[] = { | |
67 | "none", | |
68 | "_external.h", | |
69 | "_internal.h", | |
70 | "_table.c", | |
71 | "_defs.h" | |
72 | }; | |
73 | ||
74 | FILE *ofile; | |
75 | int lineNumber, outputNumber; | |
76 | char *moduleName; | |
77 | char *moduleNameCaps; | |
78 | ||
79 | char *stringToLower(char *string) | |
80 | { | |
81 | char *new = strdup(string); | |
82 | char *p = new; | |
83 | ||
84 | while (*p) | |
85 | *p = tolower(*p++); | |
86 | return new; | |
87 | } | |
88 | ||
89 | char *stringToUpper(char *string) | |
90 | { | |
91 | char *new = strdup(string); | |
92 | char *p = new; | |
93 | ||
94 | while (*p) | |
95 | *p = toupper(*p++); | |
96 | return new; | |
97 | } | |
98 | ||
99 | inline BOOL | |
100 | isIdentifier(char c) | |
101 | { | |
102 | if (isalnum(c) || c == '_') | |
103 | return YES; | |
104 | else | |
105 | return NO; | |
106 | } | |
107 | ||
108 | void | |
109 | outputLine(char *decl, char *function, char *args, char *arglist) | |
110 | { | |
111 | if (which == table) { | |
112 | static int struct_started; | |
113 | if (struct_started == 0) { | |
114 | fprintf(ofile, "unsigned long (*%s_functions[])() = {\n", | |
115 | moduleName); | |
116 | struct_started = 1; | |
117 | } | |
118 | fprintf(ofile, "(unsigned long (*)())_%s,\t\t/* %d */\n", function, outputNumber); | |
119 | } | |
120 | ||
121 | if (which == defs) { | |
122 | fprintf(ofile, "#define %s _%s\n",function,function); | |
123 | } | |
124 | ||
125 | if (which == internal) { | |
126 | fprintf(ofile, "extern %s _%s(%s);\n", decl, function, args); | |
127 | } | |
128 | ||
129 | if (which == external) { | |
130 | fprintf(ofile, "#define %s_%s_FN %d\n", | |
131 | moduleNameCaps, function, outputNumber); | |
132 | fprintf(ofile, | |
133 | "static inline %s %s ( %s ) {\n", decl, function, args); | |
134 | fprintf(ofile, | |
135 | "\treturn (%s)(*%s_FN[%d])(%s);\n", | |
136 | decl, moduleNameCaps, outputNumber, arglist); | |
137 | fprintf(ofile, "}\n"); | |
138 | } | |
139 | outputNumber++; | |
140 | } | |
141 | ||
142 | void | |
143 | parseLine(char *line) | |
144 | { | |
145 | char *paren, *parenEnd; | |
146 | char *ident, *identEnd; | |
147 | char *arglist, *arglistEnd; | |
148 | char *function; | |
149 | ||
150 | paren = strchr(line, '('); | |
151 | if (paren == NULL) | |
152 | goto syntax_error; | |
153 | for (identEnd = paren - 1; !isIdentifier(*identEnd); identEnd--) | |
154 | continue; | |
155 | for (ident = identEnd; isIdentifier(*ident); ident--) | |
156 | continue; | |
157 | ident++; | |
158 | *++identEnd = '\0'; | |
159 | paren++; | |
160 | parenEnd = strchr(paren, ')'); | |
161 | if (parenEnd == NULL) | |
162 | goto syntax_error; | |
163 | *parenEnd = '\0'; | |
164 | ||
165 | arglist = parenEnd + 1; | |
166 | while (isspace(*arglist)) | |
167 | arglist++; | |
168 | arglistEnd = strchr(arglist, ';'); | |
169 | if (arglistEnd == NULL) | |
170 | goto syntax_error; | |
171 | *arglistEnd = '\0'; | |
172 | ||
173 | function = strdup(ident); | |
174 | *ident = '\0'; | |
175 | outputLine(line, function, paren, arglist); | |
176 | free(function); | |
177 | return; | |
178 | ||
179 | syntax_error: | |
180 | fprintf(stderr, "Syntax error at line %d\n",lineNumber); | |
181 | return; | |
182 | } | |
183 | ||
184 | int | |
185 | getLineThru(FILE *file, char *linebuf, char stop, int len) | |
186 | { | |
187 | char *p = linebuf; | |
188 | int c, gotten; | |
189 | ||
190 | gotten = 0; | |
191 | while (((c = fgetc(file)) != EOF) && len) { | |
192 | *p++ = c; | |
193 | len--; | |
194 | gotten++; | |
195 | if (c == '\n') lineNumber++; | |
196 | if (c == stop) | |
197 | break; | |
198 | } | |
199 | *p = '\0'; | |
200 | return gotten; | |
201 | } | |
202 | ||
203 | int | |
204 | peekf(FILE *file) | |
205 | { | |
206 | int c = fgetc(file); | |
207 | ungetc(c, file); | |
208 | return c; | |
209 | } | |
210 | ||
211 | void | |
212 | skipWhitespace(FILE *file) | |
213 | { | |
214 | int c; | |
215 | ||
216 | while ((c = fgetc(file)) != EOF && isspace(c)) | |
217 | if (c == '\n') ++lineNumber; | |
218 | ungetc(c, file); | |
219 | } | |
220 | ||
221 | void | |
222 | parseFile(FILE *file) | |
223 | { | |
224 | char *line, c; | |
225 | int len, lineNumber; | |
226 | ||
227 | line = malloc(MAXLINE+1); | |
228 | lineNumber = 1; | |
229 | ||
230 | skipWhitespace(file); | |
231 | ||
232 | while (!feof(file)) { | |
233 | c = peekf(file); | |
234 | if (c == '#' || c == '/') { | |
235 | len = getLineThru(file, line, '\n', MAXLINE); | |
236 | if (c == '#') | |
237 | fprintf(ofile, line); | |
238 | } else { | |
239 | len = getLineThru(file, line, ';', MAXLINE); | |
240 | parseLine(line); | |
241 | } | |
242 | skipWhitespace(file); | |
243 | } | |
244 | free(line); | |
245 | } | |
246 | ||
247 | int | |
248 | main(int argc, char **argv) | |
249 | { | |
250 | extern char *optarg; | |
251 | extern int optind; | |
252 | FILE *file; | |
253 | int c, errflag = 0; | |
254 | char ofilename[MAXPATHLEN]; | |
255 | char *ifile, *odir = "."; | |
256 | ||
257 | while ((c = getopt(argc, argv, "d:n:")) != EOF) | |
258 | switch (c) { | |
259 | case 'd': | |
260 | odir = optarg; | |
261 | break; | |
262 | case 'n': | |
263 | moduleName = optarg; | |
264 | moduleNameCaps = stringToUpper(moduleName); | |
265 | break; | |
266 | default: | |
267 | errflag++; | |
268 | break; | |
269 | } | |
270 | ||
271 | ofile = stdout; | |
272 | if ((ifile = argv[optind]) != NULL) { | |
273 | file = fopen(argv[optind], "r"); | |
274 | if (file == NULL) { | |
275 | perror("open"); | |
276 | exit(1); | |
277 | } | |
278 | } else { | |
279 | fprintf(stderr,"No input file specified\n"); | |
280 | exit(2); | |
281 | } | |
282 | ||
283 | if (moduleName == NULL) { | |
284 | char *newName, *dot; | |
285 | int len; | |
286 | newName = strchr(ifile, '/'); | |
287 | if (newName == NULL) | |
288 | newName = ifile; | |
289 | dot = strchr(newName, '.'); | |
290 | if (dot == NULL) | |
291 | dot = &newName[strlen(newName)]; | |
292 | len = dot - newName; | |
293 | moduleName = (char *)malloc(len + 1); | |
294 | strncpy(moduleName, newName, len); | |
295 | moduleName[len] = '\0'; | |
296 | moduleNameCaps = stringToUpper(moduleName); | |
297 | } | |
298 | ||
299 | for (which = external; which <= defs; which++) { | |
300 | rewind(file); | |
301 | lineNumber = 1; | |
302 | outputNumber = 0; | |
303 | sprintf(ofilename, "%s/%s%s", odir, moduleName, osuffix[which]); | |
304 | ofile = fopen((const char *)ofilename, "w"); | |
305 | if (ofile == NULL) { | |
306 | fprintf(stderr,"error opening output file %s\n",ofilename); | |
307 | exit(3); | |
308 | } | |
309 | ||
310 | if (which == table) { | |
311 | fprintf(ofile, "#define %s_TABLE 1\n", moduleNameCaps); | |
312 | fprintf(ofile, "#import \"%s_internal.h\"\n",moduleName); | |
313 | } | |
314 | ||
315 | if (which == internal) { | |
316 | fprintf(ofile, "#define %s_INTERNAL 1\n", moduleNameCaps); | |
317 | } | |
318 | ||
319 | if (which == defs) { | |
320 | fprintf(ofile, "#define %s_DEFS 1\n", moduleNameCaps); | |
321 | } | |
322 | ||
323 | if (which == external) { | |
324 | fprintf(ofile, "#import \"memory.h\"\n"); | |
325 | fprintf(ofile, "#define %s_EXTERNAL 1\n", moduleNameCaps); | |
326 | fprintf(ofile, | |
327 | "#define %s_FN (*(unsigned long (***)())%s_TABLE_POINTER)\n\n", | |
328 | moduleNameCaps, moduleNameCaps); | |
329 | } | |
330 | parseFile(file); | |
331 | ||
332 | if (which == table) { | |
333 | fprintf(ofile, "};\n\n"); | |
334 | } | |
335 | } | |
336 | return 0; | |
337 | } |