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, &regs);
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