Initial revision
[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 }