Initial revision
[ssr] / StraySrc / SDLS / cdll / c / readdef
1 /*
2 * readdef.c
3 *
4 * Read DLL Binder definition files
5 *
6 * © 1994-1998 Straylight
7 */
8
9 /*----- Licensing note ----------------------------------------------------*
10 *
11 * This file is part of Straylight's Dynamic Linking System (SDLS)
12 *
13 * SDLS is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * SDLS is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with SDLS. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "hashtable.h"
34 #include "error.h"
35 #include "readdef.h"
36 #include "swiv.h"
37 #include "swis.h"
38
39 #define CHUNKSIZE 40
40
41 static char *readdef_token=0;
42
43 static void addChar(char **buffer,int *length,int *size,char c)
44 {
45 char *p;
46 if (*length==*size)
47 {
48 if (p=realloc(*buffer,*size+CHUNKSIZE),!p)
49 error(NOMEM);
50 *buffer=p;
51 (*size)+=CHUNKSIZE;
52 }
53 (*buffer)[(*length)++]=c;
54 }
55
56 #define add(c) addChar(&readdef_token,&len,&size,(c))
57
58 int cistrcmp(const char *s1,const char *s2)
59 {
60 char c1;
61 char c2;
62 while (*s1 || *s2)
63 {
64 c1=tolower(*(s1++));
65 c2=tolower(*(s2++));
66 if (c1!=c2)
67 return (c1-c2);
68 }
69 return (0);
70 }
71
72 enum
73 {
74 _xxx,
75 _IDENT,
76 _STRING,
77 _BRA,
78 _KET,
79 _EQUAL,
80 _CONST,
81 _EOF
82 };
83
84 static char readdef__ungot[2];
85 static int readdef__ungotc=0;
86
87 #define GET(fp) (readdef__ungotc ? \
88 readdef__ungot[--readdef__ungotc] : \
89 getc(fp))
90
91 #define UNGET(c) ((void)((c)==EOF ? \
92 EOF : \
93 (readdef__ungot[readdef__ungotc++]=(c))))
94
95 static int readdef__getToken(FILE *fp)
96 {
97 int ch;
98 int type=_xxx;
99 int qu;
100 int len=0;
101 int size=0;
102
103 if (readdef_token)
104 free(readdef_token);
105 readdef_token=0;
106
107 while (!type)
108 {
109 /* --- Skip whitespace --- */
110 while (isspace(ch=GET(fp)))
111 /* blank */;
112
113 switch (ch)
114 {
115 case ';':
116 case '|':
117 case '#':
118 while (ch=GET(fp),ch!='\n' && ch!=EOF)
119 /* blank */;
120 break;
121 case '/':
122 switch (ch=GET(fp))
123 {
124 case '*':
125 while (ch=GET(fp),ch!='*' ||
126 (ch=GET(fp),UNGET(ch),ch!='/'))
127 /* blank */;
128 (void)GET(fp);
129 break;
130 case '/':
131 while (ch=GET(fp),ch!='\n' && ch!=EOF)
132 /* blank */;
133 break;
134 default:
135 UNGET(ch);
136 add('/');
137 break;
138 }
139 break;
140 case '{':
141 type=_BRA;
142 break;
143 case '}':
144 type=_KET;
145 break;
146 case '=':
147 type=_EQUAL;
148 break;
149 case EOF:
150 type=_EOF;
151 break;
152 case '\'':
153 case '\"':
154 qu=ch;
155 while (ch=GET(fp),1)
156 {
157 if (ch==qu)
158 {
159 ch=GET(fp);
160 if (ch!=qu)
161 {
162 UNGET(ch);
163 break;
164 }
165 }
166 if (ch==EOF)
167 {
168 error(QBFEOF,qu);
169 break;
170 }
171 else if (ch=='\n')
172 {
173 error(QBFNL,qu);
174 break;
175 }
176 add(ch);
177 }
178 add(0);
179 type=_STRING;
180 break;
181 default:
182 add(ch);
183 while (ch=GET(fp),ch!=EOF && !isspace(ch))
184 add(ch);
185 add(0);
186 UNGET(ch);
187 type=_IDENT;
188 break;
189 }
190 }
191 return (type);
192 }
193
194 static char *readdef__tokAsString(int type)
195 {
196 switch (type)
197 {
198 case _EOF:
199 return ("<EOF>");
200 case _BRA:
201 return ("{");
202 case _KET:
203 return ("}");
204 case _EQUAL:
205 return ("=");
206 case _CONST:
207 return ("<integer>");
208 case _STRING:
209 return ("<string literal>");
210 case _IDENT:
211 return (readdef_token);
212 }
213 return (0);
214 }
215
216 static int readdef__getOrderedTable(FILE *fp,hashtable h)
217 {
218 int done=0;
219 int tok;
220 char *name;
221 unsigned int ord;
222
223 switch (tok=readdef__getToken(fp))
224 {
225 case _BRA:
226 break;
227 default:
228 error(JUNKNOBRA,readdef__tokAsString(tok));
229 return (1);
230 break;
231 }
232
233 tok=readdef__getToken(fp);
234 while (!done)
235 {
236 switch (tok)
237 {
238 case _IDENT:
239 name=readdef_token;
240 readdef_token=0;
241 tok=readdef__getToken(fp);
242 ord=0xFFFFFFFF;
243 if (tok==_EQUAL)
244 {
245 tok=readdef__getToken(fp);
246 if (tok==_IDENT)
247 {
248 sscanf(readdef_token,"%i",&ord);
249 tok=readdef__getToken(fp);
250 }
251 }
252 if (!hash_addWithOrd(h,name,ord))
253 {
254 error(NOMEM);
255 return (1);
256 }
257 free(name);
258 break;
259 case _KET:
260 done=1;
261 break;
262 default:
263 error(JUNKNOKET,readdef__tokAsString(tok));
264 return (1);
265 }
266 }
267 return (0);
268 }
269
270 static int readdef__getTable(FILE *fp,hashtable h)
271 {
272 int done=0;
273 int tok;
274
275 switch (tok=readdef__getToken(fp))
276 {
277 case _BRA:
278 break;
279 default:
280 error(JUNKNOBRA,readdef__tokAsString(tok));
281 return (1);
282 break;
283 }
284
285 while (!done)
286 {
287 switch (tok=readdef__getToken(fp))
288 {
289 case _IDENT:
290 if (!hash_add(h,readdef_token))
291 {
292 error(NOMEM);
293 return (1);
294 }
295 break;
296 case _KET:
297 done=1;
298 break;
299 default:
300 error(JUNKNOKET,readdef__tokAsString(tok));
301 return (1);
302 }
303 }
304 return (0);
305 }
306
307 static int readdef__getVersion(FILE *fp,int *v)
308 {
309 int tok;
310 int minor;
311 int major;
312 char *dot;
313
314 switch (tok=readdef__getToken(fp))
315 {
316 case _IDENT:
317 dot=strchr(readdef_token,'.');
318 if (!dot)
319 {
320 sscanf(readdef_token,"%i",&major);
321 *v=major*100;
322 }
323 else
324 {
325 *dot=0;
326 major=atoi(readdef_token);
327 switch (strlen(dot+1))
328 {
329 case 0:
330 *v=major*100;
331 break;
332 case 1:
333 minor=atoi(dot+1);
334 *v=major*100+minor*10;
335 break;
336 case 2:
337 minor=atoi(dot+1);
338 *v=major*100+minor;
339 break;
340 default:
341 error(BADVER,readdef__tokAsString(tok));
342 return (1);
343 }
344 }
345 break;
346 default:
347 error(JUNKNOVER,readdef__tokAsString(tok));
348 return (1);
349 }
350 return (0);
351 }
352
353 static int readdef__getName(FILE *fp,char *name)
354 {
355 int tok;
356
357 switch (tok=readdef__getToken(fp))
358 {
359 case _IDENT:
360 case _STRING:
361 strcpy(name,readdef_token);
362 break;
363 default:
364 error(JUNKNONAME,readdef__tokAsString(tok));
365 return (1);
366 }
367 return (0);
368 }
369
370 static int readdef__getCopyright(FILE *fp,char *name)
371 {
372 int tok;
373 char timeBuff[5];
374
375 switch (tok=readdef__getToken(fp))
376 {
377 case _STRING:
378 timeBuff[0]=3;
379 _swi(OS_Word,_inr(0,1),14,timeBuff);
380 _swi(OS_ConvertDateAndTime,_inr(0,3),timeBuff,name,256,readdef_token);
381 break;
382 default:
383 error(JUNKNOCRIGHT,readdef__tokAsString(tok));
384 return (1);
385 }
386 return (0);
387 }
388
389 static int readdef__getItem(FILE *fp,readdef_info *info)
390 {
391 int tok;
392
393 switch (tok=readdef__getToken(fp))
394 {
395 case _EOF:
396 return (-1);
397 break;
398 case _IDENT:
399 break;
400 default:
401 error(JUNKNOITEM,readdef__tokAsString(tok));
402 return (1);
403 }
404
405 if (!cistrcmp(readdef_token,"exports"))
406 return (readdef__getOrderedTable(fp,info->sym));
407 else if (!cistrcmp(readdef_token,"extentry"))
408 return (readdef__getTable(fp,info->vsym));
409 else if (!cistrcmp(readdef_token,"objects"))
410 return (readdef__getTable(fp,info->obj));
411 else if (!cistrcmp(readdef_token,"version"))
412 return (readdef__getVersion(fp,&info->version));
413 else if (!cistrcmp(readdef_token,"name"))
414 return (readdef__getName(fp,info->name));
415 else if (!cistrcmp(readdef_token,"author"))
416 return (readdef__getCopyright(fp,info->copyright));
417 else if (!cistrcmp(readdef_token,"NonAPCS"))
418 {
419 info->flags|=rdFlag_shortEntry;
420 return (0);
421 }
422 else if (!cistrcmp(readdef_token,"OmitNames"))
423 {
424 info->flags|=rdFlag_noNames;
425 return (0);
426 }
427 else
428 {
429 error(BADITEM,readdef_token);
430 return (1);
431 }
432 }
433
434 int readdef(char *file,readdef_info *info)
435 {
436 FILE *fp=fopen(file,"r");
437
438 if (!fp)
439 {
440 error(NOOPENIN,file);
441 return(1);
442 }
443
444 info->version=-1;
445 *info->name=0;
446 *info->copyright=0;
447 info->errored=0;
448 info->flags=0;
449
450 while (readdef__getItem(fp,info)!=-1)
451 /* blank */;
452 fclose(fp);
453
454 return (0);
455 }