1 %{
2 /*
3 * Copyright (C) 1998,1999 Joran Maille
4 * Portions Copyright (C) 2002 Nikos Mavroyanopoulos
5 *
6 * This file is part of GAA-ng.
7 *
8 * GAA-ng is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * GAA-ng is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 */
22
23 /* needed in newer bisons for yytoknum.
24 */
25 #define YYPRINT
26 #define YYERROR_VERBOSE
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include "../config.h"
33
34 #include "gaaout.h"
35
36 #define NEW(x,first, tmp) \
37 tmp = (x*) malloc(sizeof(x)); \
38 tmp->next = first; \
39 first = tmp;
40
41 #define GAA_NOREST -1
42
43 #define GAA_SINGLE 0
44 #define GAA_LIST 1
45
46 #define GAA_OBLIGAT 1
47 #define GAA_INCOMP 2
48 #define GAAMAX_ARGLIST_COUNT 30
49
50
51 #define LOOKUP(first, tmp, id, key, _line) \
52 for(tmp = first; tmp != NULL; tmp = tmp->next) \
53 { \
54 if(tmp->id == key) \
55 { \
56 fprintf(stderr, "%s:%d: identifier '%s' redefined\n", st_in, _line, num2str(key)); \
57 fprintf(stderr, "%s:%d: this is the location of the previous definition\n", st_in, tmp->line); \
58 error_flag = 1; \
59 } \
60 }
61
62 #define SUPERLOOKUP(id, key, line) \
63 LOOKUP(first_option, option_tmp, id, key, line);
64
65 FILE* glb_fd, *glb_skel;
66 FILE* glb_out;
67 FILE* glb_sfd; /* emulates stdin */
68
69 int glb_underscore_strings = 0;
70
71 int yyerror( char* s); /* Called by yyparse on error */
72 int yylex();
73
74 int type = 0;
75 extern int num_lines; /* current line */
76 char* st_in; /* hold input_filename */
77
78 struct _option;
79 struct _option_argless;
80 struct _arg;
81 struct _type;
82 struct _help;
83 struct _struct_elt;
84
85 typedef struct _option option;
86 typedef struct _arg arg;
87 typedef struct _atype atype;
88 typedef struct _struct_elt struct_elt;
89 typedef struct _help help;
90 typedef struct _condition condition;
91
92
93 int k_needed = 0, init_loc = -1, rest_nb_arg = 0;
94 int error_flag = 0;
95
96 int rest_type = GAA_NOREST, rest_action = 0;
97 int c_code = 0;
98 int nb_option = 0, nb_option_argless = 0, nb_atype = 0, nb_struct_elt = 0, nb_help = 0;
99 option *option_tmp, *first_option = NULL;
100 atype *atype_tmp, *first_atype = NULL;
101 struct_elt *struct_elt_tmp, *first_struct_elt = NULL;
102 help *help_tmp, *first_help = NULL;
103 arg *arg_tmp, *first_rest_arg = NULL;
104 condition *condition_tmp, *first_condition = NULL;
105
106 char* num2str(int n);
107 int get_id_line(int n);
108
109 struct _help
110 {
111 int str;
112 int line;
113 help *next;
114 };
115
get_help(int num)116 help* get_help(int num)
117 {
118 int i;
119 help *tmp;
120 tmp = first_help;
121 for(i = 0; (i < num) && (tmp !=NULL); i++)
122 tmp = tmp->next;
123 if(tmp == NULL)
124 {
125 fprintf(stderr, "%s: '%d' out of range\n", st_in, num);
126 exit(1);
127 }
128 return tmp;
129 }
130
131 struct _option
132 {
133 int id1, id2;
134 int action;
135 int help;
136 int nb_arg;
137 arg *fa;
138 int line;
139 option *next;
140 };
141
get_option(int num)142 option* get_option(int num)
143 {
144 int i;
145 option *tmp;
146 tmp = first_option;
147 for(i = 0; (i < num) && (tmp !=NULL); i++)
148 tmp = tmp->next;
149 if(tmp == NULL)
150 {
151 fprintf(stderr, "%s: '%d' out of range\n", st_in, num);
152 exit(1);
153 }
154 return tmp;
155 }
156
157 struct _condition
158 {
159 int type;
160 int options;
161 condition *next;
162 };
163
164
165 struct _arg
166 {
167 int type;
168 int help;
169 int id;
170 arg *next;
171 };
172
get_arg(int numOpt,int num)173 arg* get_arg(int numOpt, int num)
174 {
175 int i;
176 arg *tmp;
177 tmp = (get_option(numOpt))->fa;
178 for(i = 0; (i < num) && (tmp !=NULL); i++)
179 tmp = tmp->next;
180 if(tmp == NULL)
181 {
182 fprintf(stderr, "%s: '%d' out of range\n", st_in, num);
183 exit(1);
184 }
185 return tmp;
186 }
187
188
189
190 struct _atype
191 {
192 int id;
193 int fnName;
194 int argtype;
195 int line;
196 char* type_str;
197 atype *next;
198 };
199
get_atype(int num)200 atype* get_atype(int num)
201 {
202 int i;
203 atype *tmp;
204 tmp = first_atype;
205 for(i = 0; (i < num) && (tmp !=NULL); i++)
206 tmp = tmp->next;
207 if(tmp == NULL)
208 {
209 fprintf(stderr, "%s: '%d' out of range\n", st_in, num);
210 exit(1);
211 }
212 return tmp;
213 }
get_atype_from_id(int num)214 atype* get_atype_from_id(int num)
215 {
216 int i;
217 atype *tmp;
218 tmp = first_atype;
219 for(i = 0; (tmp!=NULL) && (tmp->id != num); i++) {
220 tmp = tmp->next;
221 }
222 if(tmp == NULL)
223 {
224 fprintf(stderr, "%s:%d: identifier '%s' out of range\n", st_in,
225 get_id_line(num), num2str(num));
226 exit(1);
227 }
228 return tmp;
229 }
230
get_type(arg * in)231 atype* get_type(arg *in)
232 {
233 int i;
234 atype *tmp = first_atype;
235 for(i = 0; i < nb_atype; i++)
236 {
237 if(in->id == tmp->id)
238 return tmp;
239 tmp = tmp->next;
240 }
241 fprintf(stderr, "%s:%d: Unknown type '%s'.\n", st_in, num_lines - 1, num2str(in->id));
242 exit(1);
243 }
244
245
246 struct _struct_elt
247 {
248 int data; /* 0 for '#' statement, 1 for 'DATA' 'AS' statement */
249 int type; /* only if data == 1 GAA_LIST / GAA_SINGLE */
250 int id; /* only if data == 1 */
251 int arg_type; /* only if data == 1 */
252 int location; /* only if data == 0 */
253 struct_elt *next;
254 };
255
get_struct_elt(int num)256 struct_elt* get_struct_elt(int num)
257 {
258 int i;
259 struct_elt *tmp;
260 tmp = first_struct_elt;
261 for(i = 0; (i < num) && (tmp !=NULL); i++)
262 tmp = tmp->next;
263 if(tmp == NULL)
264 {
265 printf("Out of range\n");
266 exit(1);
267 }
268 return tmp;
269 };
270
read_str(FILE * fd,int offset,char ** target,char separator)271 void read_str(FILE* fd, int offset, char **target, char separator)
272 {
273 int i, size = -1;
274 int a;
275 fseek(fd, offset, SEEK_SET);
276 do
277 {
278 if( (a=fgetc( fd)) == EOF)
279 {
280 printf("Read error\n");
281 exit(1);
282 }
283 size++;
284 }
285 while(a != separator);
286 *target = malloc(size+1);
287 fseek(fd, offset, SEEK_SET);
288 for(i = 0; i < size; i++)
289 {
290 if( (a=fgetc(fd)) == EOF)
291 {
292 printf("Read error\n");
293 exit(1);
294 }
295 (*target)[i] = a;
296 }
297 (*target)[size] = 0;
298 }
299
300 /* append is appended to the string output */
copy_str(FILE * fd,int offset,FILE * out,const char * append)301 void copy_str(FILE* fd, int offset, FILE* out, const char* append)
302 {
303 int a = '"', b, last = ' ';
304 int flag;
305
306 fseek(fd, offset-1, SEEK_SET);
307 if( (a=fgetc(fd)) == EOF)
308 {
309 printf("Read error\n");
310 exit(1);
311 }
312 while(a == '"' || a == '%')
313 {
314 b = a;
315 if(a == '"') {
316 if (glb_underscore_strings!=0) fputs("_(", out);
317 fprintf(out,"%c", '"');
318 }
319 flag = 1;
320 do
321 {
322 if( (a=fgetc(fd)) == EOF)
323 {
324 printf("Read error\n");
325 exit(1);
326 }
327 if((a == b) && (last != '\\'))
328 {
329 if(flag == 1)
330 flag = 0;
331 else
332 flag = 1;
333 }
334 if((flag == 1) || (a == b && b != '%'))
335 {
336 if (a=='"' && append!=NULL) fputs( append, out);
337 fprintf(out, "%c", a);
338 if (a=='"' && glb_underscore_strings!=0) fputs(")", out);
339 }
340 last = a;
341 }
342 while(flag == 1);
343 do
344 {
345 if( (a=fgetc(fd)) == EOF)
346 {
347 return;
348 }
349 }
350 while ((a == ' ' || a == '\r' || a == '\t' || a == '\n'));
351 }
352 }
353
354 %}
355
356 %token IDENTIFIER
357 %token ACTION
358 %token TERMINATE
359 %token CSOURCE
360 %token CPART
361 %token TYPE
362 %token STRING
363 %token UNDERSCORE_STRINGS
364
365 %token INIT "init"
366 %token DEFITEM "defitem"
367 %token OPTION "option"
368 %token REST "rest"
369 %token HELPNODE "helpnode"
370 %token OBLIGATORY "obligat"
371 %token INCOMPATIBLE "incomp"
372 %token DATA "data"
373 %token AS "as"
374 %token OPTIONAL "optional"
375
376 %token_table
377
378 %%
379
380 input:
381 source TERMINATE { c_code = $2; }
382 | source { c_code = -1; }
383 | CSOURCE source { c_code = $1; }
384 ;
385
386 source:
387 line
388 | source line
389 ;
390 arg:
391 IDENTIFIER
392 {
393 $$ = $1;
394 }
395 | '*' IDENTIFIER
396 {
397 $$ = -$2;
398 }
399 ;
400 arg_list:
401 {
402 $$ = (int)malloc(sizeof(int));
403 ((int*)$$)[0] = 0;
404 }
405 | arg_real_list
406 {
407 $$ = $1;
408 }
409 ;
410 arg_real_list:
411 OPTIONAL arg_real_list
412 {
413 $$ = $2;
414 ((int*)$$)[0]++;
415 ((int*)$$)[2*(((int*)$$)[0] - 1) + 1] = 0;
416 ((int*)$$)[2*(((int*)$$)[0] - 1) + 2] = -1;
417 }
418 | arg STRING
419 {
420 $$ = (int)malloc((2 * GAAMAX_ARGLIST_COUNT + 1)* sizeof(int));
421 ((int*)$$)[0] = 1;
422 ((int*)$$)[2*(((int*)$$)[0] - 1) + 1] = $1;
423 ((int*)$$)[2*(((int*)$$)[0] - 1) + 2] = $2;
424 }
425 | arg STRING arg_real_list
426 {
427 $$ = $3;
428 ((int*)$$)[0]++;
429 ((int*)$$)[2*(((int*)$$)[0] - 1) + 1] = $1;
430 ((int*)$$)[2*(((int*)$$)[0] - 1) + 2] = $2;
431 }
432 | arg
433 {
434 $$ = (int)malloc((2 * GAAMAX_ARGLIST_COUNT + 1)* sizeof(int));
435 ((int*)$$)[0] = 1;
436 ((int*)$$)[2*(((int*)$$)[0] - 1) + 1] = $1;
437 ((int*)$$)[2*(((int*)$$)[0] - 1) + 2] = -1;
438 }
439 | arg arg_real_list
440 {
441 $$ = $2;
442 ((int*)$$)[0]++;
443 ((int*)$$)[2*(((int*)$$)[0] - 1) + 1] = $1;
444 ((int*)$$)[2*(((int*)$$)[0] - 1) + 2] = -1;
445 }
446 ;
447 many_strings:
448 STRING {
449 $$ = $1;
450 }
451 | many_strings STRING {
452 $$ = $1;
453 }
454 ;
455 line:
456 CPART
457 {
458 NEW(struct_elt, first_struct_elt, struct_elt_tmp);
459 struct_elt_tmp->data = 0;
460 struct_elt_tmp->location = $1;
461 nb_struct_elt++;
462 }
463 | DATA IDENTIFIER AS arg
464 {
465 NEW(struct_elt, first_struct_elt, struct_elt_tmp);
466 struct_elt_tmp->data = 1;
467 struct_elt_tmp->id = $2;
468 if($4 < 0)
469 {
470 struct_elt_tmp->type = GAA_LIST;
471 struct_elt_tmp->arg_type = -$4;
472 }
473 else
474 {
475 struct_elt_tmp->type = GAA_SINGLE;
476 struct_elt_tmp->arg_type = $4;
477 }
478 nb_struct_elt++;
479 }
480 | HELPNODE many_strings
481 {
482 NEW(help, first_help, help_tmp);
483 help_tmp->str = $2;
484 help_tmp->line = @1.first_line;
485 nb_help++;
486
487 fprintf(glb_out, "\tprintf(");
488 copy_str(glb_fd, $2, glb_out, "\\n");
489 fprintf(glb_out, ");\n");
490 }
491 | INIT ACTION { init_loc = $2; }
492 | DEFITEM IDENTIFIER IDENTIFIER CPART
493 {
494 NEW(atype, first_atype, atype_tmp);
495 atype_tmp->id = $2;
496 atype_tmp->fnName = $3;
497 atype_tmp->argtype = $4;
498 nb_atype++;
499
500 }
501 | OPTION '(' IDENTIFIER ')' arg_list ACTION many_strings
502 {
503 int i, *tab, sent=0;
504 SUPERLOOKUP(id2, $3, @1.first_line);
505 NEW(option, first_option, option_tmp);
506 option_tmp->fa = NULL;
507 option_tmp->id1 = 0;
508 option_tmp->id2 = $3;
509 option_tmp->action = $6;
510 option_tmp->line = @1.first_line;
511 option_tmp->help = $7;
512 tab = (int*)$5;
513 option_tmp->nb_arg = tab[0];
514 nb_option++;
515
516 fprintf(glb_out, "\t__gaa_helpsingle(0, \"%s\", ", num2str($3));
517
518 for(i = 1; i < option_tmp->nb_arg + 1; i++)
519 {
520
521 NEW(arg, option_tmp->fa, arg_tmp);
522
523 arg_tmp->id = tab[2*(i-1) + 1];
524 if(tab[2*(option_tmp->nb_arg-i) + 2]>0)
525 {
526 sent++;
527 copy_str(glb_fd, tab[2*(option_tmp->nb_arg-i) + 2], glb_out, " ");
528 }
529 if(arg_tmp->id < 0)
530 {
531 arg_tmp->type = GAA_LIST;
532 arg_tmp->id *= -1;
533 }
534 else
535 {
536 arg_tmp->type = GAA_SINGLE;
537 }
538 }
539 if (sent==0) fputs( "\"\"", glb_out);
540 fprintf(glb_out, ", ");
541 copy_str(glb_fd, $7, glb_out, NULL);
542 fprintf(glb_out,");\n");
543 }
544 | OPTION '(' IDENTIFIER ',' IDENTIFIER ')' arg_list ACTION many_strings
545 {
546 int i, *tab, sent=0;
547 SUPERLOOKUP(id2, $5, @1.first_line);
548 SUPERLOOKUP(id1, $3, @1.first_line);
549
550 if(strlen(num2str($3)) != 1)
551 {
552 fprintf( stderr, "%s:%d: first identifier must be a single character\n", st_in, @1.first_line);
553 error_flag = 1;
554 }
555 NEW(option, first_option, option_tmp);
556 option_tmp->fa = NULL;
557 option_tmp->id1 = $3;
558 option_tmp->id2 = $5;
559 option_tmp->action = $8;
560 option_tmp->line = @1.first_line;
561 option_tmp->help = $9;
562 tab = (int*)$7;
563 option_tmp->nb_arg = tab[0];
564 nb_option++;
565 fprintf(glb_out, "\t__gaa_helpsingle('%c', \"%s\", ",
566 num2str($3)[0], num2str($5));
567 for(i = 1; i < option_tmp->nb_arg + 1; i++)
568 {
569
570 NEW(arg, option_tmp->fa, arg_tmp);
571
572 arg_tmp->id = tab[2*(i-1) + 1];
573 if(tab[2*(option_tmp->nb_arg-i) + 2]>0)
574 {
575 sent++;
576 copy_str(glb_fd, tab[2*(option_tmp->nb_arg-i) + 2], glb_out, " ");
577 }
578 if(arg_tmp->id < 0)
579 {
580 arg_tmp->type = GAA_LIST;
581 arg_tmp->id *= -1;
582 }
583 else
584 {
585 arg_tmp->type = GAA_SINGLE;
586 }
587 }
588 if (sent==0) fputs( "\"\"", glb_out);
589 fprintf(glb_out, ", ");
590 copy_str(glb_fd, $9, glb_out, NULL);
591 fprintf(glb_out,");\n");
592 }
593 | REST arg_list ACTION
594 {
595 int i, *tab;
596
597 rest_action = $3;
598 tab = (int*)$2;
599 rest_nb_arg = tab[0];
600
601 for(i = 1; i < rest_nb_arg + 1; i++)
602 {
603 NEW(arg, first_rest_arg, arg_tmp);
604
605 arg_tmp->id = tab[2*(i-1) + 1];
606 if(arg_tmp->id < 0)
607 {
608 arg_tmp->type = GAA_LIST;
609 arg_tmp->id *= -1;
610 }
611 else
612 {
613 arg_tmp->type = GAA_SINGLE;
614 }
615 }
616 }
617 | OBLIGATORY IDENTIFIER
618 {
619 NEW(condition, first_condition, condition_tmp);
620 condition_tmp->options = $2;
621 condition_tmp->type = GAA_OBLIGAT;
622 k_needed = 1;
623 }
624 | INCOMPATIBLE IDENTIFIER
625 {
626 NEW(condition, first_condition, condition_tmp);
627 condition_tmp->options = $2;
628 condition_tmp->type = GAA_INCOMP;
629 k_needed = 1;
630 }
631 | UNDERSCORE_STRINGS
632 {
633 glb_underscore_strings = 1;
634 }
635 ;
636
637 %%
638
639 extern int loc_index;
640
641 struct _idStruct;
642 typedef struct _idStruct idStruct;
643
644 struct _idStruct
645 {
646 char *name;
647 int line; /* the first line it was encountered */
648 idStruct *next;
649 };
650
651 idStruct *firstId = NULL;
652
653 #define RM(x) remove_illegal_C_char(x)
remove_illegal_C_char(const char * str)654 static char *remove_illegal_C_char( const char* str)
655 {
656 static char ret[512];
657 int i;
658 if (strlen(str)+1 > sizeof(ret)) {
659 fprintf(stderr, "num2str: Too long string\n");
660 exit(1);
661 }
662 memset( ret, 0, sizeof ret);
663 for (i=0;i<strlen(str);i++) {
664 ret[i] = str[i];
665 if (ret[i]=='-') ret[i]='_';
666 }
667 ret[i]=0;
668
669 return ret;
670 }
671
num2str(int n)672 char* num2str(int n)
673 {
674 int i;
675 idStruct *tmp;
676 tmp = firstId;
677 if(n == 0)
678 return "";
679 for(i = 0; (i < n - 1) && (tmp != NULL); i++)
680 {
681 tmp = tmp->next;
682 }
683 if(tmp == NULL)
684 {
685 fprintf(stderr, "num2str: Out of range\n");
686 exit(1);
687 }
688 return tmp->name;
689 }
690
691 /* returns the line of the identifier, indexed
692 * by n;
693 */
get_id_line(int n)694 int get_id_line(int n)
695 {
696 int i;
697 idStruct *tmp;
698 tmp = firstId;
699 if(n == 0)
700 return num_lines - 1;
701 for(i = 0; (i < n - 1) && (tmp != NULL); i++)
702 {
703 tmp = tmp->next;
704 }
705 if(tmp == NULL)
706 {
707 fprintf(stderr, "get_id_line: Out of range\n");
708 exit(1);
709 }
710 return tmp->line;
711 }
712
length(char * a)713 int length(char *a)
714 {
715 int i = 0;
716 while(*(a+i) != 0) i++;
717 return i;
718 }
719
720
getTokenNum(char * str)721 int getTokenNum( char* str) {
722 int i;
723 for (i = 0; i < YYNTOKENS; i++)
724 {
725 if (yytname[i] != 0
726 && yytname[i][0] == '"'
727 && strncasecmp (yytname[i] + 1, str, strlen (str)) == 0
728 && yytname[i][strlen (str) + 1] == '"'
729 && yytname[i][strlen (str) + 2] == 0)
730 {
731 return yytoknum[i];
732 }
733 }
734 return -1;
735 }
736
getIdNum(char * name,int line)737 int getIdNum(char *name, int line)
738 {
739 int len, data = 1;
740 idStruct **pter, *blurp;
741
742 pter = &firstId;
743 while(*pter != NULL)
744 {
745 if(strcmp(name, (*pter)->name) == 0)
746 break;
747 data++;
748 pter = &((*pter)->next);
749 }
750 if(*pter == NULL)
751 {
752 blurp = *pter;
753 len = length(name);
754 blurp = malloc(sizeof(idStruct));
755 *pter = blurp;
756 blurp->name = malloc((len + 1)* sizeof(char));
757 strcpy(blurp->name, name);
758 blurp->next = NULL;
759 blurp->line = line;
760 }
761
762 return data;
763 }
764
765 #define MAXIDSIZE 300
766
767 char *tmpStr;
768
769
yyerror(char * s)770 int yyerror( char* s) /* Called by yyparse on error */
771 {
772 fprintf (stderr, "%s:%d: %s\n", st_in, num_lines, s);
773 exit(1);
774 }
775
776 /* Copies the skel file to target file
777 * if term!=EOF, then the file is copied until
778 * the terminator byte.
779 *
780 * This function will use the file seek pointers
781 * to keep a state in copying.
782 */
copy_file_state(FILE * source,FILE * target,int term)783 void copy_file_state(FILE* source, FILE* target, int term)
784 {
785 int a;
786 do
787 {
788 if( (a=fgetc(source)) == EOF && term!=EOF)
789 {
790 fprintf(stderr, "copy_file_state: Source read error\n");
791 exit(1);
792 }
793 if(a != term)
794 {
795 if(fputc(a, target) == EOF)
796 {
797 fprintf(stderr, "copy_file_state: Output write error\n");
798 exit(1);
799 }
800 }
801 }
802 while(a != term);
803 }
804
805 /* Returns the number of the line, that the index-th character
806 * is placed.
807 */
get_line(FILE * fd,int index)808 int get_line(FILE* fd, int index)
809 {
810 int tmp, line = 1, i;
811 int a = 0;
812 tmp = fseek(fd, 0, SEEK_CUR);
813 fseek(fd, 0, SEEK_SET);
814 for(i = 0; i < index; i++)
815 {
816 a=fgetc(fd);
817 if(a==EOF) {
818 printf("Read error\n");
819 exit(1);
820 }
821 if(a == '\n')
822 line++;
823 }
824 fseek(fd, tmp, SEEK_SET);
825 return line;
826 }
827
828 /* term holds the terminator character ';', or '\n'
829 */
copy_line(FILE * fd,int index,FILE * target,char * file,char term)830 void copy_line(FILE* fd, int index, FILE* target, char* file, char term)
831 {
832 int a;
833 fprintf(target, "#line %d \"%s\"\n\t", get_line(fd, index), file);
834 fseek(fd, index, SEEK_SET);
835 do
836 {
837 if( (a=fgetc(fd)) == EOF)
838 {
839 printf("Read error\n");
840 exit(1);
841 }
842 if(fputc(a, target) == EOF)
843 {
844 printf("Output write error\n");
845 exit(1);
846 }
847 }
848 while(a != term);
849 }
850
put_action(FILE * fd,int index,FILE * target,char * opt,int narg,char * file)851 void put_action( FILE* fd, int index, FILE* target, char *opt, int narg, char* file)
852 {
853 int a;
854 char *str_cmp;
855 int i, flag = 1;
856 fprintf(target, "#line %d \"%s\"\n", get_line(fd, index), file);
857 fprintf(target, "{");
858 fseek(fd, index, SEEK_SET);
859 if(opt[0] == 0)
860 str_cmp = "GAAREST_tmp";
861 else
862 str_cmp = "GAATMP_";
863 while(flag != 0)
864 {
865 if( (a=fgetc(fd)) == EOF)
866 {
867 printf("Read error\n");
868 exit(1);
869 }
870 switch(a)
871 {
872 case '{':
873 flag ++;
874 break;
875 case '}':
876 flag --;
877 break;
878 case '@':
879 i = 0;
880 a = '0';
881 flag *= -1;
882 do
883 {
884 i *= 10;
885 i += (a - '0');
886 if( (a=fgetc(fd)) == EOF)
887 {
888 printf("Read error\n");
889 exit(1);
890 }
891 }
892 while(isdigit(a) != 0);
893 fseek(fd, -1, SEEK_CUR);
894 if(( i > narg ) || (i <= 0))
895 {
896 printf("Fatal: Option %s: argument $%d unknown\n", opt, i);
897 exit(1);
898 }
899 fprintf(target, "%s%s.size%d", str_cmp, RM(opt), i);
900 break;
901 case '$':
902 if( (a=fgetc(fd)) == EOF)
903 {
904 printf("Read error\n");
905 exit(1);
906 }
907 fseek(fd, -1, SEEK_CUR);
908 flag *= -1;
909 if(isdigit(a) == 0)
910 {
911 fprintf(target, "gaaval->");
912 }
913 else
914 {
915 i = 0;
916 a = '0';
917 do
918 {
919 i *= 10;
920 i += (a - '0');
921 if( (a=fgetc(fd)) == EOF)
922 {
923 printf("Read error\n");
924 exit(1);
925 }
926 }
927 while(isdigit(a) != 0);
928 fseek(fd, -1, SEEK_CUR);
929 if(( i > narg ) || (i <= 0))
930 {
931 printf("Fatal: Option %s: argument $%d unknown\n", opt, i);
932 exit(1);
933 }
934 fprintf(target, "%s%s.arg%d", str_cmp, RM(opt), i);
935 }
936 break;
937 default: break;
938 }
939 if(flag > 0)
940 {
941 if(fputc( a, target) == EOF)
942 {
943 printf("Output write error\n");
944 exit(1);
945 }
946 }
947 if(flag < 0)
948 flag *= -1;
949 }
950 fprintf(target, ";};\n");
951 }
952
953 /* copies the file until it finds #} */
copy_file(FILE * fd,int index,FILE * target,char * file)954 void copy_file(FILE* fd, int index, FILE* target, char *file)
955 {
956 int a, pa = -1;
957 fprintf(target, "#line %d \"%s\"\n", get_line(fd, index), file);
958 fseek(fd, index, SEEK_SET);
959 while( (a=fgetc(fd)) != EOF)
960 {
961 if (pa=='#' && a=='}') break;
962
963 if (pa!=-1)
964 if(fputc( pa, target) == EOF)
965 {
966 printf("Output write error\n");
967 exit(1);
968 }
969 pa = a;
970 };
971
972 if (a==EOF) {
973 if(fputc( pa, target) == EOF)
974 {
975 printf("Output write error\n");
976 exit(1);
977 }
978 }
979 }
980
add_type(char * id,char * fnName,char * type)981 void add_type(char *id, char *fnName, char *type)
982 {
983 NEW(atype, first_atype, atype_tmp);
984 atype_tmp->id = getIdNum(id, 0);
985 atype_tmp->fnName = getIdNum(fnName, 0);
986 atype_tmp->type_str = type;
987 nb_atype++;
988 }
989
990 #define SHORTNAME num2str(option_tmp_loc->id1)
991 #define LONGNAME num2str(option_tmp_loc->id2)
992
993 char __optional_flag;
994
write_get_arg(FILE * out,arg * x,char * name,int arg_number)995 void write_get_arg(FILE *out, arg *x, char *name, int arg_number)
996 {
997 char *str_name;
998 char _name[512];
999
1000 strcpy( _name, RM(name));
1001
1002 if(x->id == 0)
1003 {
1004 __optional_flag = 1;
1005 return;
1006 }
1007
1008 if(name[0] == 0)
1009 str_name = "GAAREST_tmp";
1010 else
1011 str_name = "GAATMP_";
1012
1013 if(x->type == GAA_SINGLE)
1014 {
1015 if(__optional_flag)
1016 {
1017 fprintf(out, "\t\tGAA_TESTMOREOPTIONALARGS;\n\t\tGAA_FILL(%s%s.arg%d, %s, %s%s.size%d);\n\t\tgaa_index++;\n",
1018 str_name,_name,arg_number,RM(num2str(get_type(x)->fnName)),str_name,_name,arg_number);
1019 }
1020 else
1021 {
1022 fprintf(out, "\t\tGAA_TESTMOREARGS;\n\t\tGAA_FILL(%s%s.arg%d, %s, %s%s.size%d);\n\t\tgaa_index++;\n",
1023 str_name,_name,arg_number,RM(num2str(get_type(x)->fnName)),str_name, _name,arg_number);
1024 }
1025 }
1026 else
1027 {
1028 if(!__optional_flag)
1029 fprintf(out, "\t\tGAA_LIST_FILL(%s%s.arg%d, %s, %s, %s%s.size%d);\n",
1030 str_name,_name,arg_number,
1031 RM(num2str(get_type(x)->fnName)), get_type(x)->type_str,
1032 str_name,_name,arg_number);
1033 else
1034 fprintf(out, "\t\tGAA_OPTIONALLIST_FILL(%s%s.arg%d, %s, %s, %s%s.size%d);\n",
1035 str_name,_name,arg_number,
1036 RM(num2str(get_type(x)->fnName)), get_type(x)->type_str,
1037 str_name,_name,arg_number);
1038 }
1039 }
1040
1041 #define EXT_GAA_H "_gaa.h"
1042 #define EXT_GAA_C "_gaa.c"
1043
main(int argc,char ** argv)1044 int main(int argc, char **argv)
1045 {
1046 option *option_tmp_loc;
1047 atype *atype_tmp_loc;
1048 struct_elt *struct_elt_tmp_loc;
1049 /* help *help_tmp_loc; */
1050 arg *arg_tmp_loc;
1051 FILE* fd,* skel;
1052 FILE *out,*header;
1053 int i, j, k, header_start, header_limit;
1054 int rval;
1055 int a;
1056 char *st_out,*st_header, *ptr;
1057 gaainfo info;
1058
1059 if(gaa(argc, argv, &info) != -1)
1060 {
1061 fprintf(stderr, "Error in the arguments.\n");
1062 fprintf(stderr, "Use the -h or --help parameters for help.\n");
1063 return 0;
1064 }
1065 if(info.skel == NULL)
1066 {
1067 j = 0;
1068 info.skel = malloc(sizeof(char) * (length("gaa.skel") + length(argv[0])));
1069 for(i = 0; i < length(argv[0]); i++)
1070 {
1071 if(argv[0][i] == '\\')
1072 j = i+1;
1073 info.skel[i] = argv[0][i];
1074 }
1075 strcpy(info.skel + j, "gaa.skel");
1076 }
1077 st_in = info.input; st_out = info.output; st_header = info.header;
1078
1079 /* generate file names
1080 */
1081 if (st_header==NULL) {
1082 st_header= malloc( strlen(st_in)+ strlen(EXT_GAA_H));
1083 strcpy(st_header, st_in);
1084 ptr = strstr( st_header, ".gaa");
1085 if (ptr==NULL)
1086 strcat( st_header, EXT_GAA_H);
1087 else
1088 strcpy( ptr, EXT_GAA_H);
1089 }
1090 if (st_out==NULL) {
1091 st_out= malloc( strlen(st_in)+ strlen(EXT_GAA_C));
1092 strcpy(st_out, st_in);
1093 ptr = strstr( st_out, ".gaa");
1094 if (ptr==NULL)
1095 strcat( st_out, EXT_GAA_C);
1096 else
1097 strcpy( ptr, EXT_GAA_C);
1098 }
1099
1100 if((skel = fopen(info.skel, "r")) == NULL)
1101 {
1102 printf("Couldn't open skeleton file: %s\n", info.skel);
1103 exit(1);
1104 }
1105 if((glb_fd = fopen(st_in, "r")) == NULL)
1106 {
1107 printf("Couldn't open gaa file '%s'.\n", st_in);
1108 exit(1);
1109 }
1110 if((out = fopen(st_out, "w+")) == NULL)
1111 {
1112 printf("Couldn't open output file '%s'.\n", st_out);
1113 exit(1);
1114 }
1115 if((glb_out = tmpfile()) == NULL)
1116 {
1117 printf("Couldn't open tmp output file.\n");
1118 exit(1);
1119 }
1120 glb_skel = skel;
1121 tmpStr = malloc((MAXIDSIZE + 1)*sizeof(char));
1122
1123 if(( glb_sfd=fopen(st_in, "r")) == NULL)
1124 {
1125 printf("Couldn't open gaa file\n");
1126 exit(1);
1127 }
1128
1129 fprintf(out, "/* File generated by GAA %s\n */\n", VERSION);
1130
1131
1132 if (info.prefix) {
1133 fprintf(out, "\n#define gaainfo %sgaainfo\n", info.prefix);
1134 fprintf(out, "#define gaa %sgaa\n", info.prefix);
1135 fprintf(out, "#define gaa_help %sgaa_help\n", info.prefix);
1136 fprintf(out, "#define gaa_file %sgaa_file\n", info.prefix);
1137 }
1138
1139 /* write the WIN32 headers */
1140 if(info.win32 == 1)
1141 fprintf(out, "#define GAA_WIN32\n");
1142 else
1143 fprintf(out, "#define GAA_NO_WIN32\n");
1144
1145 /* Parse the input file */
1146 rval = yyparse();
1147 fclose( glb_sfd);
1148 free(tmpStr);
1149
1150 fd = glb_fd;
1151
1152 /* Write the C declarations */
1153 if(c_code != -1)
1154 copy_file(fd, c_code, out, st_in);
1155
1156 /* Write the skel file */
1157 copy_file_state(skel,out, '@');
1158
1159 fseek( glb_out, 0, SEEK_SET);
1160 copy_file_state(glb_out, out, EOF);
1161 fclose(glb_out); /* close tmp file */
1162
1163 copy_file_state(skel,out, '@');
1164
1165 header_start = ftell(out);
1166 if((rval != 0) || (error_flag == 1))
1167 return 1;
1168
1169 for(i = 0; i < nb_atype; i++)
1170 {
1171 atype_tmp_loc = get_atype(i);
1172 read_str(fd, atype_tmp_loc->argtype, &(atype_tmp_loc->type_str), ';');
1173 }
1174 add_type("STR", "gaa_getstr", "char*");
1175 add_type("INT", "gaa_getint", "int");
1176 add_type("CHAR", "gaa_getchar", "char");
1177 add_type("FLOAT", "gaa_getfloat", "float");
1178
1179 copy_file_state(skel,out, '@');
1180 for(i = 0; i < nb_struct_elt; i++)
1181 {
1182 struct_elt_tmp_loc = get_struct_elt(i);
1183 if(struct_elt_tmp_loc->data == 0)
1184 copy_line(fd, struct_elt_tmp_loc->location, out, st_in, ';');
1185 else
1186 {
1187 if(struct_elt_tmp_loc->type == GAA_SINGLE)
1188 fprintf(out, "\t%s %s;",
1189 get_atype_from_id(struct_elt_tmp_loc->arg_type)->type_str,
1190 num2str(struct_elt_tmp_loc->id));
1191 else
1192 fprintf(out, "\t%s *%s;",
1193 get_atype_from_id(struct_elt_tmp_loc->arg_type)->type_str,
1194 num2str(struct_elt_tmp_loc->id));
1195 }
1196 fprintf(out, "\n");
1197 }
1198 copy_file_state(skel,out, '@');
1199 header_limit = ftell(out);
1200 copy_file_state(skel,out, '@');
1201
1202 fprintf(out, "%d\n", nb_option + nb_option_argless);
1203
1204 for(j = 0; j < nb_option; j++)
1205 {
1206 option_tmp_loc = get_option(j);
1207
1208 fprintf(out,"#define GAAOPTID_%s\t%d\n", RM(num2str( option_tmp_loc->id2)),
1209 j + 1 );
1210 }
1211
1212 copy_file_state(skel,out, '@');
1213 for(i = 0; i < nb_option; i++)
1214 {
1215 k = 0;
1216 option_tmp_loc = get_option(i);
1217 if(option_tmp_loc->nb_arg > 0)
1218 {
1219 fprintf(out, "\nstruct GAAOPTION_%s \n{\n", RM(num2str(option_tmp_loc->id2)));
1220 for(j = 0; j < option_tmp_loc->nb_arg; j++)
1221 {
1222 arg_tmp_loc = get_arg(i,j);
1223 if(arg_tmp_loc->id != 0)
1224 {
1225 k++;
1226 atype_tmp_loc = get_type(arg_tmp_loc);
1227 fprintf(out, "\t%s", atype_tmp_loc->type_str);
1228 if(arg_tmp_loc->type == GAA_LIST)
1229 fprintf(out, "*");
1230 fprintf(out, " arg%d;\n", k);
1231 /* if(arg_tmp_loc->type == GAA_LIST) */
1232 fprintf(out, "\tint size%d;\n", k);
1233 }
1234 }
1235 fprintf(out, "};\n");
1236 }
1237 }
1238 if(rest_nb_arg != 0)
1239 {
1240 fprintf(out, "#define GAA_REST_EXISTS\n");
1241 fprintf(out, "\nstruct GAAREST\n{\n");
1242 j = 0;
1243 for(arg_tmp_loc = first_rest_arg; arg_tmp_loc != NULL; arg_tmp_loc = arg_tmp_loc->next)
1244 {
1245
1246 if(arg_tmp_loc->id != 0)
1247 {
1248 atype_tmp_loc = get_type(arg_tmp_loc);
1249 fprintf(out, "\t%s", atype_tmp_loc->type_str);
1250 if(arg_tmp_loc->type == GAA_LIST)
1251 fprintf(out, "*");
1252 fprintf(out, " arg%d;\n", j + 1);
1253 /* if(arg_tmp_loc->type == GAA_LIST)*/
1254 fprintf(out, "\tint size%d;\n", j+1);
1255 j++;
1256 }
1257 }
1258 fprintf(out, "};\n");
1259 }
1260 copy_file_state(skel,out, '@');
1261 for(j = 0; j < nb_option; j++)
1262 {
1263 option_tmp_loc = get_option(j);
1264 if(option_tmp_loc->nb_arg != 0)
1265 fprintf(out,"\t\t\tGAA_CHECK1STR(\"%s\", GAAOPTID_%s);\n",
1266 num2str(option_tmp_loc->id1), RM(num2str(option_tmp_loc->id2)));
1267 }
1268 copy_file_state(skel,out,'@');
1269 for(j = 0; j < nb_option; j++)
1270 {
1271 option_tmp_loc = get_option(j);
1272 if(option_tmp_loc->nb_arg == 0)
1273 fprintf(out,"\t\t\tGAA_CHECK1STR(\"%s\", GAAOPTID_%s);\n",
1274 num2str(option_tmp_loc->id1), RM(num2str(option_tmp_loc->id2)));
1275 }
1276 copy_file_state(skel,out, '@');
1277 for(j = 0; j < nb_option; j++)
1278 {
1279 option_tmp_loc = get_option(j);
1280 fprintf(out,"\t\t\tGAA_CHECKSTR(\"%s\", GAAOPTID_%s);\n",
1281 num2str(option_tmp_loc->id2), RM(num2str(option_tmp_loc->id2)));
1282 }
1283 copy_file_state(skel,out, '@');
1284
1285 for(j = 0; j < nb_option; j++)
1286 {
1287 option_tmp_loc = get_option(j);
1288 if(option_tmp_loc->nb_arg > 0)
1289 fprintf(out,"\tstruct GAAOPTION_%s GAATMP_%s;\n",
1290 RM(num2str(option_tmp_loc->id2)), RM(num2str(option_tmp_loc->id2)));
1291 }
1292 copy_file_state(skel,out, '@');
1293 /* for(j = 0; j < nb_option_argless; j++)
1294 {
1295 option_argless_tmp_loc = get_option_argless(j);
1296 fprintf(out,"\tcase GAAOPTID_%s:\n", RM(ALONGNAME));
1297 put_action(fd, option_argless_tmp_loc->action, out, ALONGNAME, 0, st_in);
1298 fprintf(out,"\n\t\treturn GAA_OK;\n\t\tbreak;\n");
1299 } */
1300 for(i = 0; i < nb_option; i++)
1301 {
1302 __optional_flag = 0;
1303 option_tmp_loc = get_option(i);
1304 fprintf(out,"\tcase GAAOPTID_%s:\n\tOK = 0;\n", RM(LONGNAME));
1305 k = 0;
1306 for(j = 0; j < option_tmp_loc->nb_arg; j++)
1307 {
1308 arg_tmp_loc = get_arg(i,j);
1309 if(arg_tmp_loc->id != 0)
1310 k ++;
1311 write_get_arg(out, arg_tmp_loc, LONGNAME, k);
1312 }
1313 put_action(fd, option_tmp_loc->action, out, LONGNAME, option_tmp_loc->nb_arg, st_in);
1314 fprintf(out,"\n\t\treturn GAA_OK;\n\t\tbreak;\n");
1315 }
1316 if(rest_nb_arg != 0)
1317 {
1318 j = 1;
1319 fprintf(out,"\tcase GAA_REST:\n");
1320 for(arg_tmp_loc = first_rest_arg; arg_tmp_loc != NULL; arg_tmp_loc = arg_tmp_loc->next)
1321 {
1322 write_get_arg(out, arg_tmp_loc, "", j);
1323 if(arg_tmp_loc->id != 0)
1324 j++;
1325 }
1326 put_action(fd, rest_action, out, "", rest_nb_arg, st_in);
1327 fprintf(out,"\n\t\treturn GAA_OK;\n\t\tbreak;\n");
1328 }
1329 copy_file_state(skel,out, '@');
1330 if(k_needed)
1331 fprintf(out, ", k");
1332 copy_file_state(skel, out, '@');
1333 if(init_loc >= 0)
1334 put_action(fd, init_loc, out, "init", 0, st_in);
1335 copy_file_state(skel,out, '@');
1336 for(condition_tmp = first_condition; condition_tmp != NULL;
1337 condition_tmp = condition_tmp->next)
1338 {
1339 switch(condition_tmp->type)
1340 {
1341 case GAA_OBLIGAT:
1342 fprintf(out, "\tGAA_OBLIGAT(\"%s\");\n", num2str(condition_tmp->options));
1343 break;
1344 case GAA_INCOMP:
1345 fprintf(out, "\tGAA_INCOMP(\"%s\");\n", num2str(condition_tmp->options));
1346 break;
1347 default: break;
1348 }
1349 }
1350 copy_file_state(skel,out, '@');
1351
1352
1353 if((header = fopen(st_header, "w")) == NULL)
1354 {
1355 printf("Couldn't open header file '%s'.\n", st_header);
1356 exit(1);
1357 }
1358
1359 if (info.prefix) {
1360 fprintf(header, "\n#define gaainfo %sgaainfo\n", info.prefix);
1361 fprintf(header, "#define gaa %sgaa\n", info.prefix);
1362 fprintf(header, "#define gaa_help %sgaa_help\n", info.prefix);
1363 fprintf(header, "#define gaa_file %sgaa_file\n", info.prefix);
1364 }
1365
1366 fseek(out, header_start, SEEK_SET);
1367 for(i = header_start; i < header_limit; i++)
1368 {
1369 if( (a=fgetc(out)) == EOF)
1370 {
1371 printf("Read error\n");
1372 exit(1);
1373 }
1374 if(fputc( a, header) == EOF)
1375 {
1376 printf("Header write error\n");
1377 exit(1);
1378 }
1379 }
1380
1381 if (info.prefix) {
1382 fprintf(header, "\n#undef gaainfo\n");
1383 fprintf(header, "#undef gaa\n");
1384 fprintf(header, "#undef gaa_help\n");
1385 fprintf(header, "#undef gaa_file\n\n");
1386 }
1387
1388 return 0;
1389 }
1390
gaa_version(void)1391 void gaa_version(void) {
1392 printf("Reading skeleton from %s\n", SKEL_DIR);
1393 printf("gaa version %s\n", VERSION);
1394 }
1395