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