1 /*
2 ** regextr.c - extract graphics modes and register information
3 ** from C source file
4 **
5 ** This file is part of SVGALIB (C) 1993 by Tommy Frandsen and
6 ** Harm Hanemaayer
7 **
8 ** Copyright (C) 1993 by Hartmut Schirmer
9 **
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 #include "vga.h"
18 #include "libvga.h"
19 #include "driver.h"
20
21 #ifndef FALSE
22 #define FALSE (1==0)
23 #endif
24 #ifndef TRUE
25 #define TRUE (1==1)
26 #endif
27
28 #define WordLen 100
29 typedef char WordStr[WordLen];
30
31 typedef struct ML {
32 WordStr x, y, c;
33 int mnum;
34 int equ;
35 void *regs;
36 struct ML *nxt;
37 } ModeList;
38
39 static void *
Malloc(unsigned long bytes)40 Malloc(unsigned long bytes)
41 {
42 void *res;
43
44 res = (void *) malloc(bytes);
45 if (res == NULL) {
46 fprintf(stderr, "regextr.c: Can't allocate memory\n");
47 exit(1);
48 }
49 return res;
50 }
51
store_equ(ModeList ** root,char * x1,char * y1,char * c1,int mnum,char * x2,char * y2,char * c2)52 static void store_equ(ModeList ** root, char *x1, char *y1, char *c1,
53 int mnum, char *x2, char *y2, char *c2)
54 {
55 ModeList *p;
56
57 p = *root;
58 while (p != NULL) {
59 if (strcmp(p->x, x1) == 0
60 && strcmp(p->y, y1) == 0
61 && strcmp(p->c, c1) == 0) {
62 fprintf(stderr, "regextr.c: Duplicate g%sx%sx%s_regs !\n", x1, y1, c1);
63 exit(1);
64 }
65 p = p->nxt;
66 }
67 p = (ModeList *) Malloc(sizeof(ModeList));
68 strcpy(p->x, x1);
69 strcpy(p->y, y1);
70 strcpy(p->c, c1);
71 p->mnum = mnum;
72 p->equ = TRUE;
73 p->nxt = *root;
74 *root = p;
75 p = (ModeList *) Malloc(sizeof(ModeList));
76 strcpy(p->x, x2);
77 strcpy(p->y, y2);
78 strcpy(p->c, c2);
79 p->mnum = 0;
80 p->equ = FALSE;
81 p->regs = NULL;
82 p->nxt = NULL;
83 (*root)->regs = (void *) p;
84 }
85
check_new_mode(ModeList * p,char * x,char * y,char * c)86 static int check_new_mode(ModeList * p, char *x, char *y, char *c)
87 {
88 while (p != NULL) {
89 if (strcmp(p->x, x) == 0
90 && strcmp(p->y, y) == 0
91 && strcmp(p->c, c) == 0)
92 return FALSE;
93 p = p->nxt;
94 }
95 return TRUE;
96 }
97
store_regs(ModeList ** root,char * x,char * y,char * c,int mnum,const char * r)98 static void store_regs(ModeList ** root, char *x, char *y, char *c, int mnum, const char *r)
99 {
100 ModeList *p;
101
102 if (!check_new_mode(*root, x, y, c)) {
103 fprintf(stderr, "regextr.c: Duplicate g%sx%sx%s_regs !\n", x, y, c);
104 exit(1);
105 }
106 p = (ModeList *) Malloc(sizeof(ModeList));
107 strcpy(p->x, x);
108 strcpy(p->y, y);
109 strcpy(p->c, c);
110 p->mnum = mnum;
111 p->equ = FALSE;
112 p->regs = (void *) r;
113 p->nxt = *root;
114 *root = p;
115 }
116
117
__store_regs(ModeList ** root,int mnum,const char * r)118 static void __store_regs(ModeList ** root, int mnum, const char *r)
119 {
120 WordStr x, y, c;
121
122 sprintf(x, "%d", infotable[mnum].xdim);
123 sprintf(y, "%d", infotable[mnum].ydim);
124 switch (infotable[mnum].colors) {
125 case 1 << 15:
126 strcpy(c, "32K");
127 break;
128 case 1 << 16:
129 strcpy(c, "64K");
130 break;
131 case 1 << 24:
132 strcpy(c, "16M");
133 break;
134 default:
135 sprintf(c, "%d", infotable[mnum].colors);
136 }
137 if (check_new_mode(*root, x, y, c))
138 store_regs(root, x, y, c, mnum, r);
139 }
140
141
142 static char *
mode2name(char * x,char * y,char * c)143 mode2name(char *x, char *y, char *c)
144 {
145 static char mn[WordLen];
146
147 sprintf(mn, "G%sx%sx%s", x, y, c);
148 return mn;
149 }
150
151 /* -------------------------------------- Scanner --- */
get_nextchar(FILE * inp)152 static int get_nextchar(FILE * inp)
153 {
154 int nch;
155
156 nch = fgetc(inp);
157 if (nch == '\\') {
158 int nnch;
159 nnch = fgetc(inp);
160 if (nnch == '\n')
161 return ' ';
162 ungetc(nnch, inp);
163 }
164 if (isspace(nch))
165 return ' ';
166 return nch;
167 }
168
169 static int next_ch = ' ';
170
get_char(FILE * inp)171 static int get_char(FILE * inp)
172 {
173 int ch;
174
175 do {
176 ch = next_ch;
177 do
178 next_ch = get_nextchar(inp);
179 while (ch == ' ' && next_ch == ' ');
180 if (ch != '/' || next_ch != '*')
181 return ch;
182 do {
183 ch = next_ch;
184 next_ch = get_nextchar(inp);
185 }
186 while (ch != EOF && !(ch == '*' && next_ch == '/'));
187 next_ch = get_nextchar(inp);
188 }
189 while (1);
190 }
191
192 static char *
get_word(FILE * inp)193 get_word(FILE * inp)
194 {
195 int ch;
196 static char buf[1000];
197 char *p;
198
199 do
200 ch = get_char(inp);
201 while (ch == ' ');
202 p = buf;
203 switch (ch) {
204 case '[':
205 case ']':
206 case '{':
207 case '}':
208 case ',':
209 case ';':
210 case '=':
211 case '(':
212 case ')':
213 *(p++) = ch;
214 *p = '\0';
215 return buf;
216 case EOF:
217 buf[0] = '\0';
218 return buf;
219 }
220 for (;;) {
221 *(p++) = ch;
222 switch (next_ch) {
223 case EOF:
224 case '[':
225 case ']':
226 case '{':
227 case '}':
228 case ',':
229 case ';':
230 case '=':
231 case '(':
232 case ')':
233 case ' ':
234 *p = '\0';
235 return buf;
236 }
237 ch = get_char(inp);
238 }
239 }
240
241 /* ----------------------------------------------- parser -- */
is_res(char * rp,char * x,char * y,char * c,int * mnum)242 static int is_res(char *rp, char *x, char *y, char *c, int *mnum)
243 {
244 char *p;
245
246 if (*(rp++) != 'g')
247 return FALSE;
248 /* X resolution */
249 p = x;
250 if (!isdigit(*rp))
251 return FALSE;
252 *(p++) = *(rp++);
253 if (!isdigit(*rp))
254 return FALSE;
255 *(p++) = *(rp++);
256 if (!isdigit(*rp))
257 return FALSE;
258 *(p++) = *(rp++);
259 if (isdigit(*rp))
260 *(p++) = *(rp++);
261 if (*(rp++) != 'x')
262 return FALSE;
263 *p = '\0';
264
265 /* Y resolution */
266 p = y;
267 if (!isdigit(*rp))
268 return FALSE;
269 *(p++) = *(rp++);
270 if (!isdigit(*rp))
271 return FALSE;
272 *(p++) = *(rp++);
273 if (!isdigit(*rp))
274 return FALSE;
275 *(p++) = *(rp++);
276 if (isdigit(*rp))
277 *(p++) = *(rp++);
278 if (*(rp++) != 'x')
279 return FALSE;
280 *p = '\0';
281
282 /* colors */
283 p = c;
284 *(p++) = *rp;
285 switch (*(rp++)) {
286 case '1':
287 *(p++) = *rp;
288 if (*(rp++) != '6')
289 return FALSE;
290 if (*rp == 'M')
291 *(p++) = *(rp++);
292 break;
293 case '2':
294 if (*rp == '5' && *(rp + 1) == '6') {
295 *(p++) = *(rp++);
296 *(p++) = *(rp++);
297 }
298 break;
299 case '3':
300 if (*rp != '2')
301 return FALSE;
302 *(p++) = *(rp++);
303 if (*rp != 'k' && *rp != 'K')
304 return FALSE;
305 *(p++) = 'K';
306 ++rp;
307 break;
308 case '6':
309 if (*rp != '4')
310 return FALSE;
311 *(p++) = *(rp++);
312 if (*rp != 'k' && *rp != 'K')
313 return FALSE;
314 *(p++) = 'K';
315 ++rp;
316 break;
317 default:
318 return FALSE;
319 }
320 *p = '\0';
321 *mnum = __svgalib_name2number(mode2name(x, y, c));
322 if (*mnum < 0) {
323 int cols = 0;
324 int xbytes = 0;
325
326 if (strcmp("16M", c) == 0) {
327 cols = 1 << 24;
328 xbytes = atoi(x) * 3;
329 } else if (strcmp("32K", c) == 0) {
330 cols = 1 << 15;
331 xbytes = atoi(x) * 2;
332 } else if (strcmp("64K", c) == 0) {
333 cols = 1 << 16;
334 xbytes = atoi(x) * 2;
335 } else if (strcmp("256", c) == 0) {
336 cols = 256;
337 xbytes = atoi(x);
338 } else if (strcmp("16", c) == 0) {
339 cols = 16;
340 xbytes = atoi(x) / 4;
341 } else
342 return FALSE;
343 *mnum = __svgalib_addmode(atoi(x), atoi(y), cols, xbytes, xbytes / atoi(x));
344 }
345 return (*mnum > TEXT && *mnum != GPLANE16);
346 }
347
read_regs(FILE * inp,unsigned char ** regs)348 static int read_regs(FILE * inp, unsigned char **regs)
349 {
350 unsigned char r[MAX_REGS];
351 char *w;
352 int c;
353 unsigned u;
354
355 if (strcmp("[", get_word(inp)) != 0)
356 return 0;
357 if (strcmp("]", get_word(inp)) != 0)
358 if (strcmp("]", get_word(inp)) != 0)
359 return 0;
360 if (strcmp("=", get_word(inp)) != 0)
361 return 0;
362 if (strcmp("{", get_word(inp)) != 0)
363 return 0;
364
365 c = 0;
366 do {
367 w = get_word(inp);
368 if (strcmp(w, "}") == 0)
369 continue;
370 if (sscanf(w, "%x", &u) == EOF)
371 if (sscanf(w, "%u", &u) == EOF) {
372 fprintf(stderr, "regextr.c: Invalid register value %s\n", w);
373 exit(1);
374 }
375 r[c++] = u;
376 w = get_word(inp);
377 }
378 while (strcmp(",", w) == 0);
379 *regs = (char *) Malloc(c);
380 memcpy(*regs, r, c);
381 return c;
382 }
383
384
__svgalib_readmodes(FILE * inp,ModeTable ** mt,int * dac,unsigned * clocks)385 void __svgalib_readmodes(FILE * inp, ModeTable ** mt, int *dac, unsigned *clocks)
386 {
387 WordStr x1, y1, c1, x2, y2, c2;
388 WordStr w1, w2;
389 int mnum1, mnum2;
390 ModeList *modes = NULL;
391 ModeList *p, *q, *cmp;
392 int regs_count = -1;
393 int change;
394 int mode_cnt, i;
395
396 /* read the register information from file */
397 while (!feof(inp)) {
398 char *wp;
399
400 wp = get_word(inp);
401 if (strcmp(wp, "#define") == 0) {
402 strcpy(w1, get_word(inp));
403 strcpy(w2, get_word(inp));
404 if (clocks != NULL && strcmp(w1, "CLOCK_VALUES") == 0) {
405 unsigned freq;
406
407 if (strcmp(w2, "{") == 0) {
408 do {
409 strcpy(w2, get_word(inp));
410 if (sscanf(w2, "%u", &freq) == EOF)
411 if (sscanf(w2, "%x", &freq) == EOF) {
412 fprintf(stderr, "regextr.c: Invalid clock definition (%s)\n", w2);
413 exit(1);
414 }
415 *(clocks++) = freq;
416 strcpy(w1, get_word(inp));
417 }
418 while (strcmp(",", w1) == 0);
419 clocks = NULL;
420 }
421 } else if (dac != NULL && strcmp(w1, "DAC_TYPE") == 0) {
422 int new_dac;
423
424 if (sscanf(w2, "%d", &new_dac) == EOF)
425 if (sscanf(w2, "%x", &new_dac) == EOF) {
426 fprintf(stderr, "regextr.c: Invalid dac definition (%s)\n", w2);
427 exit(1);
428 }
429 *dac = new_dac;
430 } else if (is_res(w1, x1, y1, c1, &mnum1)) {
431 if (is_res(w2, x2, y2, c2, &mnum2))
432 store_equ(&modes, x1, y1, c1, mnum1, x2, y2, c2);
433 else if (strcmp(w2, "DISABLE_MODE") == 0)
434 store_regs(&modes, x1, y1, c1, mnum1, DISABLE_MODE);
435 }
436 } else if (strcmp(wp, "char") == 0) {
437 strcpy(w1, get_word(inp));
438 if (is_res(w1, x1, y1, c1, &mnum1)) {
439 unsigned char *regs;
440 int rv;
441
442 rv = read_regs(inp, ®s);
443 if (rv == 0)
444 continue;
445 if (regs_count > 0 && rv != regs_count) {
446 fprintf(stderr, "regextr.c: Expected %d register values in %s, found %d\n",
447 regs_count, w1, rv);
448 exit(1);
449 }
450 regs_count = rv;
451 store_regs(&modes, x1, y1, c1, mnum1, regs);
452 }
453 }
454 }
455 /* resolve all equates */
456 do {
457 change = FALSE;
458 p = modes;
459 while (p != NULL) {
460 if (p->equ) {
461 q = modes;
462 cmp = (ModeList *) p->regs;
463 while (q != NULL) {
464 if (!q->equ &&
465 !strcmp(q->x, cmp->x) &&
466 !strcmp(q->y, cmp->y) &&
467 !strcmp(q->c, cmp->c)) {
468 free(p->regs);
469 p->regs = q->regs;
470 p->equ = FALSE;
471 change = TRUE;
472 break;
473 }
474 q = q->nxt;
475 }
476 }
477 p = p->nxt;
478 }
479 }
480 while (change);
481 /* Store modes from *mt */
482 if (*mt != NULL)
483 while ((*mt)->regs != NULL) {
484 __store_regs(&modes, (*mt)->mode_number, (*mt)->regs);
485 (*mt)++;
486 }
487 /* Check equates, count modes */
488 mode_cnt = 0;
489 p = modes;
490 while (p != NULL) {
491 if (p->equ) {
492 fprintf(stderr, "regextr.c: Unresolved equate (%sx%sx%s)\n", p->x, p->y, p->c);
493 exit(1);
494 }
495 p = p->nxt;
496 ++mode_cnt;
497 }
498 ++mode_cnt;
499 /* Now generate the mode table */
500 *mt = (ModeTable *) Malloc(mode_cnt * sizeof(ModeTable));
501 i = 0;
502 p = modes;
503 while (p != NULL) {
504 #ifdef DEBUG
505 printf("Found mode %2d: %s\n", p->mnum, mode2name(p->x, p->y, p->c));
506 #endif
507 (*mt)[i].mode_number = p->mnum;
508 (*mt)[i].regs = p->regs;
509 q = p;
510 p = p->nxt;
511 free(q);
512 ++i;
513 }
514 (*mt)[i].mode_number = 0;
515 (*mt)[i].regs = NULL;
516 }
517