chiark / gitweb /
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 }