Version bumped to 1.0.0 for the initial release.
[wllib.git] / gmk2mk.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5
6 #undef DEBUG
7
8 #define iofail() do { perror(pname); exit(EXIT_FAILURE); } while (0)
9 #define iofailn(e) do { errno=(e); perror(pname); exit(EXIT_FAILURE); } while (0)
10
11 struct sym {
12         struct sym *succ;
13         char *sym,*val;
14         } *symt;
15 char *pname;
16
17 #define WHITE(c) ((c)==' '||(c)=='\t')
18
19 static char *getsym(char *s)
20 {
21 struct sym *sm=symt;
22 #ifdef DEBUG
23         fprintf(stderr,"getsym(\"%s\")\n",s);
24 #endif
25         while (sm) {
26                 if (!strcmp(sm->sym,s)) {
27 #ifdef DEBUG
28                         fputs("getsym() - OK",stderr);
29 #endif
30                         return(sm->val);
31                         }
32                 sm=sm->succ;
33                 }
34 #ifdef DEBUG
35         fputs("getsym() - NOT FOUND",stderr);
36 #endif
37         return(NULL);
38 }
39
40 static void addsym(char *sym,char *val)
41 {
42 size_t syml;
43 struct sym *sm=malloc(sizeof(*sm)+(syml=strlen(sym)+1)+strlen(val)+1);
44 #ifdef DEBUG
45         fprintf(stderr,"addsym(\"%s\",\"%s\")\n",sym,val);
46 #endif
47         if (!sm) iofail();
48         sm->succ=symt;
49         symt=sm;
50         strcpy(symt->val=strcpy(symt->sym=(char *)sm+sizeof(*sm),sym)+syml,val);
51 #ifdef DEBUG
52         fputs("addsym() end\n",stderr);
53 #endif
54 }
55
56 static char *strip(char *s)
57 {
58 char *s2;
59 #ifdef DEBUG
60         fprintf(stderr,"strip(\"%s\")\n",s);
61 #endif
62         while (WHITE(*s)) s++;
63         for (s2=s;*s2;s2++); s2--;
64         while (s2>=s&&WHITE(*s2)) s2--;
65         *(s2+1)='\0';
66 #ifdef DEBUG
67         fprintf(stderr,"strip()==\"%s\"\n",s);
68 #endif
69         return(s);
70 }
71
72 static char *quote(char **sp)
73 {
74 char *s=*sp,*s2;
75         while (WHITE(*s)) s++;
76         if (*s++!='"') return(NULL);
77         s2=s;
78         while (*s&&*s!='"') s++;
79         if (!*s) return(NULL);
80         *s++='\0'; *sp=s;
81         return(s2);
82 }
83
84 int eval(char *s,char *buf,int bs)
85 {
86 #ifdef DEBUG
87         fprintf(stderr,"eval(\"%s\")\n",s);
88 #endif
89         for (;;) {
90                 while (*s&&*s!='$'&&bs) bs--,*buf++=*s++;
91                 if (!bs) return(0);
92                 if (!*s) {
93                         *buf++='\0';
94 #ifdef DEBUG
95                         fputs("eval() end\n",stderr);
96 #endif
97                         return(1);
98                         }
99                 if (*++s=='(') {
100 char *smn=++s,*sym;
101                         while (*s&&*s!=')') s++;
102                         if (!*s) return(0);
103                         *s++='\0';
104                         if ((sym=getsym(smn))) {
105                                 while (*sym&&bs) bs--,*buf++=*sym++;
106                                 if (!bs) return(0);
107                                 }
108                         }
109                 else *buf++='$';
110                 }
111 }
112
113 int main(int argc,char **argv)
114 {
115 char line[512],outt[sizeof(line)],*s;
116 char *c1,*c2,cn1[512],cn2[sizeof(cn1)];
117 int lins,run=1,cdpos,proc,i;
118         if ((pname=rindex(*argv,'/'))) pname++;
119         else pname=*argv;
120         puts("\
121 ##############################################################\n\
122 ### This file was created automatically by gmk2mk utility. ###\n\
123 ### PLEASE DON'T EDIT THIS FILE, edit GNUmakefile instead. ###\n\
124 ##############################################################\n");
125         while (fgets(line,sizeof(line),stdin)) {
126                 if (line[(lins=strlen(line))-1]=='\n') line[--lins]='\0';
127                 strcpy(outt,line);
128                 cdpos=1;
129                 for (i=0;i<lins;i++)
130                         if (line[i]=='"') cdpos=!cdpos;
131                         else if (cdpos&&line[i]=='#') {
132                                 line[lins=i]='\0';
133                                 break;
134                                 }
135                 proc=1;
136                 if (!strncmp(line,"ifeq ",5)) {
137                         cdpos=5;
138 valcond:
139                         proc=0; s=&line[cdpos];
140                         if ((c1=quote(&s))) if ((c2=quote(&s))) {
141                                 while (WHITE(*s)) s++;
142                                 if (!*s&&eval(c1,cn1,sizeof(cn1))&&eval(c2,cn2,sizeof(cn2))) {
143                                         i=strcmp(cn1,cn2);
144                                         run=(!i&&cdpos==5)||(!!i&&cdpos==6);
145                                         }
146                                 }
147                         }
148                 else if (!strncmp(line,"ifneq ",6)) {
149                         cdpos=6;
150                         goto valcond;
151                         }
152                 else if (!strncmp(line,"ifdef ",6)) {
153                         run=!!getsym(strip(&line[6]));
154                         proc=0;
155                         }
156                 else if (!strncmp(line,"ifndef ",7)) {
157                         run=!getsym(strip(&line[7]));
158                         proc=0;
159                         }
160                 else if (!strncmp(line,"else",4)) {
161                         run=!run;
162                         proc=0;
163                         }
164                 else if (!strncmp(line,"endif",5)) {
165                         run=1;
166                         proc=0;
167                         }
168                 if (!run||!proc) putchar('#');
169                 else {
170                         for (i=0;i<lins;i++)
171                                 if (line[i]=='=') {
172                                         line[i++]='\0';
173                                         if (eval(strip(&line[i]),cn1,sizeof(cn1))) {
174                                                 addsym(strip(line),cn1);
175                                                 }
176                                         break;
177                                         }
178                         }
179                 puts(outt);
180                 }
181         return(EXIT_SUCCESS);
182 }