chiark / gitweb /
This commit was manufactured by cvs2svn to create branch 'straylight'.
[ssr] / StraySrc / Utilities / c / chdrgen
1 /*
2  * chdrgen.c
3  *
4  * Generate csapph headers
5  *
6  * © 1995-1998 Straylight
7  */
8
9 /*----- Licensing note ----------------------------------------------------*
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2, or (at your option)
14  * any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program.  If not, write to the Free Software Foundation,
23  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <time.h>
32
33
34 #if defined(__riscos)
35   #include "kernel.h"
36   #define lasterr (_kernel_last_oserror()->errmess)
37 #else
38   #define lasterr (strerror(errno))
39 #endif
40
41 static char buf[256];
42
43 static int xtoi(const char *p)
44 {
45   int base=10;
46   int flags=0;
47   int a=0;
48   unsigned t;
49   char ch;
50   int b10=0;
51
52   for (;;)
53   {
54     ch=*p++;
55     switch (ch)
56     {
57       case '&':
58       case '%':
59         if (flags & 0x3f) goto end;
60         if (ch=='&') base=16; else base=2;
61         flags|=(1<<5);
62         break;
63
64       case '_':
65         if ((flags & 0x30) || !(flags & (1<<2))) goto end;
66         base=b10;
67         flags=(flags & ~0xA) | (1<<5);
68         a=0;
69         break;
70
71       case '-':
72       case '+':
73         if (flags & 0x7f) goto end;
74         flags|=(1<<6);
75         if (ch=='-') flags|=(1<<7);
76         break;
77
78       default:
79         t=ch-'A';
80         if (t>=26) t=ch-'a';
81         if (t<26) flags|=(1<<0);
82         else
83         {
84           t=ch-'0';
85           if (t>=10) goto end;
86         }
87         if (t<10)
88         {
89           b10=(b10*10)+t;
90           flags|=(1<<2);
91         }
92         else
93           flags|=(1<<4);
94         if (!(flags&(1<<3)))
95         {
96           if (t<base)
97           {
98             a=(a*base)+t;
99             flags|=(1<<1);
100           }
101           else
102             flags|=(1<<3);
103         }
104         break;
105     }
106   }
107
108 end:
109   if (flags & (1<<7)) a=-a;
110   return (a);
111 }
112
113 static void dogen(FILE *in,FILE *out,char *inn,char *outn)
114 {
115   char *p,*q,*r,*s;
116   int ch;
117   time_t t;
118   unsigned int var = 0;
119   int macro=0;
120   int type=0;
121   int i;
122   char *footer="";
123   int flags=2;
124
125   time(&t);
126   strftime(buf,256,"%d %B %Y",localtime(&t));
127
128   p=outn; q=p;
129   while (*p)
130   {
131     if (*p=='.') q=p+1;
132     p++;
133   }
134
135   p=inn; r=p;
136   while (*p)
137   {
138     if (*p=='.') r=p+1;
139     p++;
140   }
141
142   fprintf(out,
143           "/*\n"
144           " * %s.h\n"
145           " *\n"
146           " * [Generated from %s, %s]\n"
147           " */\n"
148           "\n"
149           "#if !defined(__CC_NORCROFT) || !defined(__arm)\n"
150           "#  error You must use the Norcroft ARM Compiler for Sapphire "
151                                         "programs\n"
152           "endif\n"
153           "\n"
154           "#pragma include_only_once\n"
155           "#pragma force_top_level\n"
156           "\n"
157           "#ifndef __%s_h\n"
158           "#define __%s_h\n"
159           "\n"
160           "#ifndef __sapphire_h\n"
161           "#  include \"sapphire.h\"\n"
162           "#endif\n"
163           "\n",
164           q,r,buf,q,q);
165
166   do
167   {
168     p=buf;
169     while (ch=getc(in),ch!=EOF && ch!='\n')
170       *p++=ch;
171     *p++=0;
172     p=buf;
173     while (!isspace(*p) && *p)
174       p++;
175     s=p;
176     while (isspace(*p) && *p)
177       p++;
178     q=p;
179     while (!isspace(*q) && *q)
180       q++;
181     r=q;
182     while (isspace(*r) && *r)
183       r++;
184     if (*buf!=';') *q=*s=0;
185
186     if (!strcmp(p,"MACRO"))
187       macro=1;
188     else if (!strcmp(p,"MEND"))
189       macro=0;
190     else if (macro)
191       /* ... */;
192     else if (*buf==';')
193     {
194       if (flags & 2)
195         continue;
196       else if (type!=4)
197         { fputs(footer,out); type=4; footer=" */\n\n"; flags=0; }
198       else
199         flags=1;
200       switch (buf[1])
201       {
202         case '-':
203           fputs("/*",out);
204           i=3;
205           p=buf+1;
206           while (*p=='-') { putc(*p++,out); i++; }
207           while (*p!='-') { putc(*p++,out); i++; }
208           while (i<76) { putc('-',out); i++; }
209           ch=getc(in);
210           fputs(ch==';' ? "*\n" : "*/\n",out);
211           ungetc(ch,in);
212           if (ch!=';') footer="\n";
213           break;
214         case '+':
215           /* A BAS directive.  Yawn. */
216           type=0; footer="";
217           break;
218         case ' ':
219           if (buf[2]=='-')
220           {
221             fputs(flags & 1 ? " *" : "/*",out);
222             fputs(buf+1,out);
223             ch=getc(in);
224             fputs(ch==';' ? " *\n" : " */\n",out);
225             ungetc(ch,in);
226             if (ch!=';') footer="\n";
227             break;
228           }
229         default:
230           fputs(flags & 1 ? " *" : "/*",out);
231           fputs(buf+1,out);
232           putc('\n',out);
233           break;
234       }
235     }
236     else if (r==buf)
237     {
238       if (type!=0) { fputs(footer,out); type=0; footer=""; }
239       flags=0;
240     }
241     else if (!strcmp(p,"IMPORT"))
242     {
243       if (type!=1) { fputs(footer,out); type=1; footer="\n"; }
244       fprintf(out,"extern routine %s;\n",r);
245     }
246     else if (!strcmp(p,"EQU"))
247     {
248       if (type!=2) { fputs(footer,out); type=2; footer="\n"; }
249       fprintf(out,"#define %s (",buf);
250       i=0;
251       while (*r)
252       {
253         switch (*r)
254         {
255           case '&': while (i--) putc(' ',out); fputs("0x",out); i=0; break;
256           case ' ': case 9: i++; break;
257           case ';': goto end;
258           default:  while (i--) putc(' ',out); putc(*r,out); i=0; break;
259         }
260         r++;
261       }
262     end:
263       fputs(")\n",out);
264     }
265     else if (!strcmp(p,"^"))
266     {
267       var=xtoi(r);
268       type=0;
269     }
270     else if (!strcmp(p,"#"))
271     {
272       if (type!=3) { fputs(footer,out); type=3; footer="\n"; }
273       if (*buf) fprintf(out,"#define %s %i\n",buf,var);
274       var+=xtoi(r);
275     }
276   }
277   while (!feof(in));
278
279   if (type!=0) putc('\n',out);
280   fputs("#endif\n",out);
281 }
282
283 int main(int argc,char *argv[])
284 {
285   FILE *in,*out;
286   if (argc!=3)
287   {
288     fprintf(stderr,"Usage: chdrgen <asm-header> <c-header>\n");
289     exit (1);
290   }
291   if (in=fopen(argv[1],"r"),!in) goto tidy_0;
292   if (out=fopen(argv[2],"w"),!out) goto tidy_1;
293   dogen(in,out,argv[1],argv[2]);
294   fclose(out);
295   fclose(in);
296   return (0);
297
298 tidy_1:
299   fclose(in);
300 tidy_0:
301   fprintf(stderr,"%s\n",lasterr);
302   exit(1);
303 }