2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
16 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
18 # define VA_START(args, lastarg) va_start(args, lastarg)
21 # define VA_START(args, lastarg) va_start(args)
28 #endif /* PROTOTYPES */
32 typedef struct _Node Node
;
84 # define NewList(l) (((List *)l)->prelast = (Node *)(l), \
85 ((List *)l)->last = 0, \
86 ((List *)l)->first = (Node *)&(((List *)l)->last))
88 # define AddHead(l,n) ((void)(\
89 ((Node *)n)->next = ((List *)l)->first, \
90 ((Node *)n)->prev = (Node *)&((List *)l)->first, \
91 ((List *)l)->first->prev = ((Node *)n), \
92 ((List *)l)->first = ((Node *)n)))
94 # define AddTail(l,n) ((void)(\
95 ((Node *)n)->next = (Node *)&((List *)l)->last, \
96 ((Node *)n)->prev = ((List *)l)->prelast, \
97 ((List *)l)->prelast->next = ((Node *)n), \
98 ((List *)l)->prelast = ((Node *)n) ))
100 # define Remove(n) ((void)(\
101 ((Node *)n)->prev->next = ((Node *)n)->next,\
102 ((Node *)n)->next->prev = ((Node *)n)->prev ))
104 # define GetHead(l) (void *)(((List *)l)->first->next \
105 ? ((List *)l)->first \
107 # define GetTail(l) (void *)(((List *)l)->prelast->prev \
108 ? ((List *)l)->prelast \
110 # define GetNext(n) (void *)(((Node *)n)->next->next \
111 ? ((Node *)n)->next \
113 # define GetPrev(n) (void *)(((Node *)n)->prev->prev \
114 ? ((Node *)n)->prev \
116 # define ForeachNode(l,n) \
117 for (n=(void *)(((List *)(l))->first); \
118 ((Node *)(n))->next; \
119 n=(void *)(((Node *)(n))->next))
120 # define ForeachNodeSafe(l,node,nextnode) \
121 for (node=(void *)(((List *)(l))->first); \
122 ((nextnode)=(void*)((Node *)(node))->next); \
123 (node)=(void *)(nextnode))
125 #define cfree(x) if (x) free (x)
126 #define SETSTR(str,val) \
128 str = val ? xstrdup (val) : NULL
130 #define xstrdup(str) _xstrdup(str,__FILE__,__LINE__)
131 #define xmalloc(size) _xmalloc(size,__FILE__,__LINE__)
132 #define xfree(ptr) _xfree(ptr,__FILE__,__LINE__)
134 #define new(type) xmalloc(sizeof(type))
137 extern void cleanup
PARAMS ((int exitcode
));
138 extern void error
PARAMS ((const char * fmt
, ...));
142 _xstrdup (const char * str
, const char * file
, int line
)
148 fprintf (stderr
, "NULL string passed to strdup from %s:%d\n", file
, line
);
156 fprintf (stderr
, "Out of memory in %s:%d\n", file
, line
);
164 _xmalloc (size_t size
, const char * file
, int line
)
172 fprintf (stderr
, "Out of memory in %s:%d", file
, line
);
180 _xfree (void * ptr
, const char * file
, int line
)
185 ((int *)ptr
)[0] = 0xDEADBEEF;
190 fprintf (stderr
, "Illegal free(NULL) in %s:%d", file
, line
);
193 Node
* FindNode (const List
* l
, const char * name
)
199 if (!strcmp (n
->name
, name
))
206 void error (const char * fmt
, ...)
209 VA_START (args
, fmt
);
210 fprintf (stderr
, "Error: ");
211 vfprintf (stderr
, fmt
, args
);
212 fprintf (stderr
, ": %s\n", strerror (errno
));
217 void cleanup (int exitcode
)
230 String
* new_string (const char * init
)
232 String
* s
= new (String
);
236 s
->len
= strlen (init
);
237 s
->max
= (s
->len
+31)&-32;
238 s
->value
= xmalloc (s
->max
+1);
239 strcpy (s
->value
, init
);
245 s
->value
= xmalloc (s
->max
+1);
252 void free_string (String
* s
)
258 void append_string (String
* s
, const char * app
)
267 if (len
< s
->max
- s
->len
- 1)
269 strcpy (s
->value
+s
->len
, app
);
276 s
->max
= (s
->len
+len
+31) & -32;
278 ns
= xmalloc (s
->max
+1);
280 strcpy (ns
, s
->value
);
281 strcpy (ns
+s
->len
, app
);
290 String
* getline (FILE * fh
)
293 char line
[256], * ptr
;
298 ptr
= fgets (line
, sizeof (line
), fh
);
305 if (line
[len
- 1] == '\n')
310 append_string (s
, line
);
312 s
= new_string (line
);
318 append_string (s
, line
);
320 s
= new_string (line
);
326 void add_continuation(String
*s
, FILE *fh
)
330 while (s
->value
[s
->len
-1]=='\\')
333 s
->value
[s
->len
-1]='\0';
335 append_string(s
, s2
->value
);
341 void output (const char * line
, FILE * outfile
)
343 const char * ptr
= line
;
347 if (*ptr
== '$' && ptr
[1] == '(' && curdir
&&
348 !strncmp ("CURDIR)", ptr
+2, 7)
352 fputs (curdir
, outfile
);
356 fputc (*ptr
, outfile
);
362 char ** getargs (const char * line
, int * argc
)
364 static char * argv
[64];
365 static char * buffer
= NULL
;
373 buffer
= xstrdup (line
);
382 while (isspace (*src
))
391 while (*src
&& !isspace (*src
))
397 while (*src
&& *src
!= '"')
418 void print_template (Template
* tmpl
)
422 printf ("Template %s:\n", tmpl
->node
.name
);
423 ForeachNode (&tmpl
->args
, arg
)
425 printf (" %s (%s) %d\n", arg
->node
.name
,
426 arg
->defval
? arg
->defval
: "--none--",
430 printf (" body=%s---\n", tmpl
->body
->value
);
433 void read_templates (const char * fn
)
437 Template
* tmpl
= NULL
;
442 if (!(fh
= fopen (fn
, "r")) )
444 error ("Can't open %s for reading", fn
);
448 while ((line
= getline (fh
)))
451 while (isspace (*ptr
)) ptr
++;
453 if (!strncmp (ptr
, "%define", 7))
456 char * defval
, * flags
;
459 add_continuation(line
, fh
);
461 tmpl
= new (Template
);
463 NewList (&tmpl
->args
);
466 argv
= getargs (line
->value
, &argc
);
468 tmpl
->node
.name
= xstrdup (argv
[1]);
469 tmpl
->argcount
= argc
-2;
471 for (t
=2; t
<argc
; t
++)
475 while (*defval
&& *defval
!= '=') defval
++;
484 flags
+= strlen (flags
);
486 while (flags
-2 >= defval
&& flags
[-2] == '/' && isalpha (flags
[-1]))
494 printf ("arg=\"%s\" defval=\"%s\" flags=\"%s\"\n",
495 argv
[t
], defval
, flags
);
500 arg
->node
.name
= xstrdup (argv
[t
]);
508 defval
[strlen (defval
) -1] = 0;
511 arg
->defval
= xstrdup (defval
);
521 arg
->flags
|= ARGF_MULTI
;
522 else if(*flags
== 'A')
523 arg
->flags
|= ARGF_ALWAYS
;
525 error ("Unknown flag %s in argument %s of template %s",
526 flags
, arg
->node
.name
, tmpl
->node
.name
);
533 AddTail (&tmpl
->args
, arg
);
538 while ((line
= getline (fh
)))
540 if (!strcmp (line
->value
, "%end"))
544 while (isspace(*ptr
)) ptr
++;
545 if (*ptr
=='%' && ptr
[1]!='(' && ptr
[1]!='\0')
546 add_continuation(line
, fh
);
549 append_string (tmpl
->body
, line
->value
);
551 tmpl
->body
= new_string (line
->value
);
553 append_string (tmpl
->body
, "\n");
557 print_template (tmpl
);
559 AddTail (&templates
, tmpl
);
568 Arg
* findArg (Template
* tmpl
, char ** argstr
)
571 char * ptr
= *argstr
;
578 while (*ptr
&& *ptr
!= ')')
579 argname
[len
++] = *ptr
++;
584 arg
= (Arg
*)FindNode (&tmpl
->args
, argname
);
587 error ("Unknown argument %s for template %s",
588 argname
, tmpl
->node
.name
);
595 void replace_template (const char * string
, FILE * outfile
)
601 char * argnptr
, * value
, * ptr
;
602 char ** values
, * freeflags
;
604 argv
= getargs (string
, &argc
);
606 tmpl
= (Template
*) FindNode (&templates
, argv
[0]+1);
610 /* Print no error for GNU Make patterns */
611 /* error ("Can't find template %s\n", argv[0]); */
612 fputs (string
, outfile
);
616 values
= xmalloc (sizeof (values
[0]) * tmpl
->argcount
);
617 freeflags
= xmalloc (sizeof (freeflags
[0]) * tmpl
->argcount
);
620 ForeachNode (&tmpl
->args
, arg
)
623 values
[t
] = arg
->defval
? arg
->defval
: "";
626 assert (t
== tmpl
->argcount
);
628 arg
= GetHead (&tmpl
->args
);
630 for (t
=1; t
<argc
; t
++)
633 while (*value
&& *value
!= '=') value
++;
649 value
[strlen (value
) - 1] = 0;
654 arg
= (Arg
*) FindNode (&tmpl
->args
, argnptr
);
656 error ("Unknown argument %s to template %s", argnptr
, tmpl
->node
.name
);
659 if (arg
->flags
& ARGF_MULTI
)
661 String
* vals
= new_string (value
);
663 for (t
++; t
<argc
; t
++)
665 append_string (vals
, " ");
666 append_string (vals
, argv
[t
]);
669 values
[arg
->pos
] = vals
->value
;
670 freeflags
[arg
->pos
] = 1;
673 arg
->flags
|= ARGF_GOTIT
;
677 arg
->flags
|= ARGF_GOTIT
;
678 values
[arg
->pos
] = xstrdup (value
);
679 freeflags
[arg
->pos
] = 1;
684 ForeachNode (&tmpl
->args
, arg
)
686 if( arg
->flags
& ARGF_ALWAYS
687 && (arg
->flags
& ARGF_GOTIT
) == 0 )
689 error("No value supplied for argument %s for template %s",
690 arg
->node
.name
, tmpl
->node
.name
695 for (ptr
=tmpl
->body
->value
; *ptr
; )
697 if (*ptr
== '%' && ptr
[1] == '(' /*)*/)
699 arg
= findArg (tmpl
, &ptr
);
701 output (values
[arg
->pos
], outfile
);
703 else if (*ptr
== '%')
705 /* nested template */
706 String
* str
= new_string ("");
712 if (*ptr
== '%' && ptr
[1] == '(' /*)*/)
714 arg
= findArg (tmpl
, &ptr
);
716 append_string (str
, values
[arg
->pos
]);
721 append_string (str
, app
);
728 replace_template (str
->value
, outfile
);
731 else if (*ptr
== '$' && ptr
[1] == '(' && curdir
&&
732 !strncmp ("CURDIR)", ptr
+2, 7)
736 fputs (curdir
, outfile
);
740 fputc (*ptr
, outfile
);
745 for (t
=0; t
<tmpl
->argcount
; t
++)
756 void process_file(FILE * infile
, FILE *outfile
)
763 "####################################################################\n"
764 "####################################################################\n"
765 "############# THIS IS A GENERATED FILE ! DO NOT EDIT ###############\n"
766 "####################################################################\n"
767 "####################################################################\n"
771 while ((line
= getline (infile
)))
774 while (isspace (*ptr
)) ptr
++;
778 int pos
= ptr
- line
->value
;
780 if (!strncmp (ptr
+1, "common", 6))
783 add_continuation (line
, infile
);
784 ptr
= line
->value
+ pos
;
786 replace_template (ptr
, outfile
);
790 output (line
->value
, outfile
);
791 fputc ('\n', outfile
);
799 replace_template ("%common", outfile
);
804 int main (int argc
, char ** argv
)
807 FILE * infile
= NULL
, * outfile
= NULL
;
808 FILE * listfile
= NULL
;
809 char * infilename
, *outfilename
;
812 NewList (&templates
);
814 for (t
=1; t
<argc
; t
++)
816 if (!strncmp ("--curdir=", argv
[t
], 9))
817 curdir
= argv
[t
] + 9;
818 else if(!strncmp ("--listfile", argv
[t
], 10))
820 // next parameter is the list file name
823 if (!(listfile
= fopen (argv
[t
+1], "r" )))
825 error ( "Can't open list file %s\n", argv
[t
+1] );
830 error ( "No list file name given\n" );
833 read_templates (argv
[t
]);
837 for (t
= 0; line
= getline (listfile
); t
++)
839 infilename
= strtok (line
->value
, " \t");
841 error("Syntax error in list file at line %d\n", t
);
842 outfilename
= strtok (NULL
, " \t");
844 error("Syntax error in list file at line %d\n", t
);
845 if (!(infile
= fopen (infilename
, "r")))
846 error("Can't open input file %s\n", infilename
);
847 if (!(outfile
= fopen (outfilename
, "w")))
848 error("Can't open output file %s\n", outfilename
);
849 process_file (infile
, outfile
);
856 else process_file (stdin
, stdout
);