1 /*------------------------------------------------------------*
2  | preprocess.c                                               |
3  | copyright 1999,  Andrew Sumner (andrewsumner@yahoo.com)    |
4  |                                                            |
5  | This is a source file for the awka package, a translator   |
6  | of the AWK programming language to ANSI C.                 |
7  |                                                            |
8  | This program is free software; you can redistribute it     |
9  | and/or modify it under the terms of the GNU General Public |
10  | License as published by the Free Software Foundation;      |
11  | either version 2 of the License, or any later version.     |
12  |                                                            |
13  | This program is distributed in the hope that it will be    |
14  | useful, but WITHOUT ANY WARRANTY; without even the implied |
15  | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR    |
16  | PURPOSE.  See the GNU General Public License for more      |
17  | details.                                                   |
18  |                                                            |
19  | You should have received a copy of the GNU General Public  |
20  | License along with this program; if not, write to the      |
21  | Free Software Foundation, Inc., 675 Mass Ave, Cambridge,   |
22  | MA 02139, USA.                                             |
23  *------------------------------------------------------------*/
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <limits.h>
30 
31 #include <stdarg.h>
32 #include "awka.h"
33 #include "msg.h"
34 #include "../config.h"
35 #include "mem.h"
36 #include "memory.h"
37 #include "awka_exe.h"
38 
39 extern struct ivar_idx ivar[];
40 extern int indent;
41 extern int split_req, split_max, mode, dol0_used;
42 extern int var_allc, var_used;
43 extern int lvar_allc, lvar_used;
44 extern int litr_allc, litr_used;
45 extern int lits_allc, lits_used;
46 extern int litd_allc, litd_used;
47 extern awka_varname *varname;
48 extern char **litrname, **litsname, **litdname;
49 extern char **litr_val, **lits_val, **litd_val;
50 extern FILE *outfp;
51 extern int awka_main;
52 extern char *awka_main_func;
53 extern int cur_func;
54 extern int al_count;
55 extern int array_sort;
56 extern int range_no;
57 extern int max_call_args;
58 extern char **vardeclare;
59 extern int vdec_no;
60 extern char **functions;
61 extern int func_no;
62 char *lvar_type = NULL;
63 
64 void awka_warning(char *, ...);
65 int findivar(char *);
66 
67 int
is_ext_builtin(name)68 is_ext_builtin(name)
69   char *name;
70 {
71   struct a_sc *fp;
72 
73   fp = ext_funcs;
74   while (fp->name)
75   {
76     if (!strcmp(fp->name, name))
77       return 1;
78     fp++;
79   }
80 
81   return 0;
82 }
83 
84 void
moveprog(int k,int i)85 moveprog(int k, int i)
86 {
87   progcode[i].op = progcode[k].op;
88   progcode[i].pop = progcode[k].pop;
89   progcode[i].func = progcode[k].func;
90   progcode[i].val = progcode[k].val;
91   progcode[i].arg = progcode[k].arg;
92   progcode[i].minst = progcode[k].minst;
93   progcode[i].inst = progcode[k].inst;
94   progcode[i].line = progcode[k].line;
95   progcode[i].jumpfrom = progcode[k].jumpfrom;
96   progcode[i].jumpto = progcode[k].jumpto;
97   progcode[i].earliest = progcode[k].earliest;
98   progcode[i].done = progcode[k].done;
99   progcode[i].endloop = progcode[k].endloop;
100   progcode[i].doloop = progcode[k].doloop;
101   progcode[i].context = progcode[k].context;
102   progcode[i].label = progcode[k].label;
103   progcode[i].varidx = progcode[k].varidx;
104   progcode[i].ftype = progcode[k].ftype;
105   progcode[i].file = progcode[k].file;
106 }
107 
108 int
findvarname(awka_varname * vname,char * name,int used)109 findvarname(awka_varname *vname, char *name, int used)
110 {
111   int i;
112 
113   if (!vname) return -1;
114   for (i=0; i<used; i++)
115     if (!strcmp(vname[i].name, name))
116       return i;
117   return -1;
118 }
119 
120 void
initlvartypes()121 initlvartypes()
122 {
123   int i;
124 
125   if (!lvar_type)
126     lvar_type = (char *) malloc(128);
127   memset(lvar_type, _VALTYPE_UNK, 128);
128 }
129 
130 void
setlvartype(int idx,char flag)131 setlvartype(int idx, char flag)
132 {
133   if (idx > 127) return;
134 
135   lvar_type[idx] = flag;
136 }
137 
138 int
getlvartype(int idx)139 getlvartype(int idx)
140 {
141   if (idx > 127) return _VALTYPE_UNK;
142   return (int) lvar_type[idx];
143 }
144 
145 int
findvaltype(char * name)146 findvaltype(char *name)
147 {
148   int i;
149 
150   if (!strncmp(name, "_litd", 5))
151     return _VALTYPE_NUM;
152 
153   if (!strncmp(name, "_lits", 5))
154     return _VALTYPE_STR;
155 
156   if (!strncmp(name, "_lvar[", 6))
157     return getlvartype(atoi(name+6));
158 
159   if (!strcmp(name, "a_bivar[a_NF]") ||
160       !strcmp(name, "a_bivar[a_NR]") ||
161       !strcmp(name, "awka_NFget()"))
162     return _VALTYPE_NUM;
163 
164   if ((i = findvarname(varname, name, var_used)) == -1)
165     return _VALTYPE_UNK;
166 
167   if (varname[i].valtype == _VALTYPE_UNK ||
168       varname[i].valtype >= _VALTYPE_NUM + _VALTYPE_STR)
169     return _VALTYPE_UNK;
170 
171   return varname[i].valtype;
172 }
173 
174 char *
getstringvalue(char * name)175 getstringvalue(char *name)
176 {
177   int i;
178   char *p = name, *buf;
179   static char *buf1 = NULL, *buf2 = NULL;
180   static int alloc = 0;
181   static char last = 0;
182 
183   if (!strncmp(name, "_lits", 5))
184   {
185     i = atoi(name+5);
186     p = lits_val[i];
187   }
188 
189   i = strlen(p);
190   if (alloc == 0)
191   {
192     alloc = i + 6;
193     alloc += 16 - (alloc % 16);
194     buf1 = (char *) malloc(alloc);
195     buf2 = (char *) malloc(alloc);
196   }
197   else if ((i+6) >= alloc)
198   {
199     alloc = i + 6;
200     alloc += 16 - (alloc % 16);
201     buf1 = (char *) realloc(buf1, alloc);
202     buf2 = (char *) realloc(buf2, alloc);
203   }
204 
205   if (last == 0)
206   {
207     buf = buf1;
208     last = 1;
209   }
210   else
211   {
212     buf = buf2;
213     last = 0;
214   }
215 
216   if (p == name)
217     sprintf(buf, "%s->ptr", p);
218   else
219     sprintf(buf, "\"%s\"", p);
220   return buf;
221 }
222 
223 char *
getdoublevalue(char * name)224 getdoublevalue(char *name)
225 {
226   int i;
227   char *p, *buf;
228   static char *buf1 = NULL, *buf2 = NULL;
229   static int alloc = 0;
230   static char last = 0;
231 
232   if (!strncmp(name, "_litd", 5))
233   {
234     i = atoi(name+5);
235     if (i < litd_used && i >= 0)
236       return litd_val[i];
237   }
238 
239   i = strlen(name);
240   if (alloc == 0)
241   {
242     alloc = i + 7;
243     alloc += 16 - (alloc % 16);
244     buf1 = (char *) malloc(alloc);
245     buf2 = (char *) malloc(alloc);
246   }
247   else if ((i+7) >= alloc)
248   {
249     alloc = i + 7;
250     alloc += 16 - (alloc % 16);
251     buf1 = (char *) realloc(buf1, alloc);
252     buf2 = (char *) realloc(buf2, alloc);
253   }
254 
255   if (last == 0)
256   {
257     buf = buf1;
258     last = 1;
259   }
260   else
261   {
262     buf = buf2;
263     last = 0;
264   }
265 
266   sprintf(buf, "%s->dval", name);
267   return buf;
268 }
269 
270 void
setvaltype(char * name,char flag)271 setvaltype(char *name, char flag)
272 {
273   int i;
274 
275   if (*name == '(' || !strncmp(name, "_lit", 4))
276     return;
277 
278   if (!strncmp(name, "_lvar[", 6))
279   {
280     setlvartype(atoi(name+6), flag);
281     return;
282   }
283 
284   if ((i = findvarname(varname, name, var_used)) == -1)
285     return;
286 
287   varname[i].valtype |= flag;
288 }
289 
290 void
setvaltype2(char * n1,char * n2)291 setvaltype2(char *n1, char *n2)
292 {
293   int i, j, type, local = -1;
294 
295   if (*n2 == '(') return;
296   if (*n1 == '(' || !strncmp(n1, "_lit", 4))
297     return;
298 
299   if (!strncmp(n1, "_lvar[", 6))
300   {
301     local = atoi(n1+6);
302     if (local > 127) return;
303   }
304   else if ((i = findvarname(varname, n1, var_used)) == -1)
305     return;
306   if (!strncmp(n2, "_lvar[", 6))
307   {
308     if ((type = atoi(n2+6)) > 127)
309       return;
310     type = lvar_type[type];
311   }
312   else if ((j = findvarname(varname, n2, var_used)) != -1)
313     type = varname[j].valtype;
314   else
315     return;
316 
317   if (local != -1)
318     lvar_type[local] = type;
319   else
320     varname[i].valtype |= type;
321 }
322 
323 void
addvarname(awka_varname ** vname,char * name,char type)324 addvarname(awka_varname **vname, char *name, char type)
325 {
326   int i = var_used;
327   awka_varname *pvname = *vname;
328 
329   if (!pvname)
330   {
331     var_allc = 10;
332     pvname = (awka_varname *) malloc(var_allc * sizeof(awka_varname));
333   }
334   else if (++var_used == var_allc)
335   {
336     var_allc += 10;
337     pvname = (awka_varname *) realloc(pvname, var_allc * sizeof(awka_varname));
338   }
339   pvname[i].name = (char *) malloc(strlen(name)+1);
340   strcpy(pvname[i].name, name);
341   pvname[i].usage = (unsigned int *) malloc( 16 * sizeof(int) );
342   pvname[i].lines = (unsigned int *) malloc( 16 * sizeof(int) );
343   pvname[i].files = (char **) malloc( 16 * sizeof(char *) );
344   pvname[i].line_no = 0;
345   pvname[i].line_allc = 16;
346   pvname[i].type = _VARTYPE_G_SCALAR;
347   pvname[i].valtype = _VALTYPE_UNK;
348   fprintf(outfp, "a_VAR *%s = NULL;\n",pvname[i].name);
349   *vname = pvname;
350 }
351 
352 void
laddvarname(awka_varname ** vname,char * name,char type)353 laddvarname(awka_varname **vname, char *name, char type)
354 {
355   int i = lvar_used;
356   awka_varname *pvname = *vname;
357 
358   if (!pvname)
359   {
360     lvar_allc = 10;
361     pvname = (awka_varname *) malloc(lvar_allc * sizeof(awka_varname));
362   }
363   else if (++lvar_used == var_allc)
364   {
365     lvar_allc += 10;
366     pvname = (awka_varname *) realloc(pvname, lvar_allc * sizeof(awka_varname));
367   }
368   pvname[i].name = (char *) malloc(strlen(name)+1);
369   strcpy(pvname[i].name, name);
370   pvname[i].usage = (unsigned int *) malloc( 16 * sizeof(int) );
371   pvname[i].lines = (unsigned int *) malloc( 16 * sizeof(int) );
372   pvname[i].files = (char **) malloc( 16 * sizeof(char *) );
373   pvname[i].line_no = 0;
374   pvname[i].line_allc = 16;
375   pvname[i].type = _VARTYPE_G_SCALAR;
376   /*fprintf(outfp, "a_VAR *%s = NULL;\n",pvname[i].name); */
377   *vname = pvname;
378 }
379 
380 void
addvarname_ref(awka_varname * vname,int i,char op,char * file,unsigned int line)381 addvarname_ref(awka_varname *vname, int i, char op, char *file, unsigned int line)
382 {
383   int j;
384   j = vname[i].line_no++;
385   if (vname[i].line_no >= vname[i].line_allc)
386   {
387     vname[i].line_allc *= 2;
388     vname[i].lines = (unsigned int *) realloc(vname[i].lines, vname[i].line_allc * sizeof(int));
389     vname[i].usage = (unsigned int *) realloc(vname[i].usage, vname[i].line_allc * sizeof(int));
390     vname[i].files = (char **) realloc(vname[i].files, vname[i].line_allc * sizeof(char *));
391   }
392   vname[i].lines[j] = line;
393   vname[i].usage[j] = op;
394   vname[i].files[j] = file;
395 }
396 
397 char *
fix_litsval(char * str)398 fix_litsval( char *str )
399 {
400   static char *output = NULL;
401   char *p, *q;
402   int len;
403   static int alloc = 0;
404 
405   if (!str) return "";
406   len = strlen(str);
407 
408   if (!alloc)
409   {
410     output = (char *) malloc( len * 2 + 1 );
411     alloc = len * 2 + 1;
412   }
413   else if (alloc < (len * 2 + 1))
414   {
415     alloc = len * 2 + 1;
416     output = (char *) realloc( output, alloc );
417   }
418 
419   p = output;
420   q = str;
421 
422   while (*q) {
423     if (*q == '\r')
424     {
425       *p = '\\'; ++p;
426       *p = 'r'; ++p; ++q;
427     }
428     else
429     {
430       *p = *q;
431       p++; q++;
432     }
433   }
434   *p = '\0';
435 
436   return output;
437 }
438 
439 void
preprocess()440 preprocess()
441 {
442   int cur = 0;
443   int i, j, j2, j3, k, p;
444   char *x, *q;
445   int func_allc = 10;
446   struct a_sc *ebp;
447 
448   functions = (char **) malloc( 10 * sizeof(char *) );
449   varname = (awka_varname *) malloc( 10 * sizeof(awka_varname) );
450   var_allc = 10;
451 
452   /* PREPROCESSING - identify variables & code jumps */
453   for (cur=0; cur<prog_no; cur++)
454   {
455     switch (progcode[cur].op)
456     {
457       case _END:
458         end_used = TRUE;
459         break;
460 
461       case _BEGIN:
462         begin_used = TRUE;
463         break;
464 
465       case _MAIN:
466         main_used = TRUE;
467         break;
468 
469       case _PUSHI:
470         if (!strcmp(progcode[cur].val, "@fs_shadow")) break;
471         if (progcode[cur].val[0] == '$')
472         {
473           progcode[cur].op = F_PUSHI;
474           progcode[cur].func = code[F_PUSHI-1].func;
475           break;
476         }
477       case A_PUSHA:
478       case AE_PUSHA:
479       case AE_PUSHI:
480         if (progcode[cur].op != _PUSHI)
481           add2arraylist(progcode[cur].val);
482       case _PUSHA:
483         if ((i = findivar(progcode[cur].val)) != -1)
484         {
485           if (!strcmp(ivar[i].vname, "a_bivar[a_ARGV]") && progcode[cur].op != AE_PUSHI)
486           {
487             progcode[cur].val = (char *) malloc(15);
488             strcpy(progcode[cur].val, "awka_argv()");
489           }
490           else
491           {
492             progcode[cur].val = (char *) malloc(strlen(ivar[i].vname)+1);
493             strcpy(progcode[cur].val, ivar[i].vname);
494           }
495           break;
496         }
497         /* adding _awk on end avoids conflicts with system defined names */
498         x = (char *) malloc(strlen(progcode[cur].val) + 6);
499         sprintf(x, "%s_awk", progcode[cur].val);
500         free(progcode[cur].val);
501         progcode[cur].val = x;
502 
503         for (i=0; i<var_used; i++)
504           if (!strcmp(varname[i].name, progcode[cur].val))
505             break;
506 
507         if (i == var_used)
508           addvarname(&varname, progcode[cur].val, _VARTYPE_G_SCALAR);
509         break;
510 
511       case _MATCH0:
512       case _MATCH1:
513       case _PUSHC:
514         if (progcode[cur].val[0] != '0')
515           break;
516 
517         for (i=0; i<litr_used; i++)
518           if (!strcmp(litr_val[i], progcode[cur].arg))
519             break;
520 
521         if (i == litr_used)
522         {
523           if (litr_allc == 0)
524           {
525             litr_allc = 20;
526             litrname = (char **) malloc(20 * sizeof(char *));
527             litr_val = (char **) malloc(20 * sizeof(char *));
528           }
529           else if (litr_used == litr_allc)
530           {
531             litr_allc += 20;
532             litrname = (char **) realloc(litrname, litr_allc * sizeof(char *));
533             litr_val = (char **) realloc(litr_val, litr_allc * sizeof(char *));
534           }
535 
536           litrname[i] = (char *) malloc(20);
537           sprintf(litrname[i], "_litr%d_awka", i);
538           /* litr_val[i] = progcode[cur].arg; */
539           litr_val[i] = (char *) malloc(strlen(progcode[cur].arg)*2);
540           strcpy(litr_val[i], fix_litsval(progcode[cur].arg));
541           litr_used++;
542         }
543         progcode[cur].arg = (char *) malloc(20);
544         strcpy(progcode[cur].arg, litrname[i]);
545         break;
546 
547 
548       case _PUSHD:
549         for (i=0; i<litd_used; i++)
550           if (!strcmp(litd_val[i], progcode[cur].val))
551             break;
552 
553         if (i == litd_used)
554         {
555           if (litd_allc == 0)
556           {
557             litd_allc = 20;
558             litdname = (char **) malloc(20 * sizeof(char *));
559             litd_val = (char **) malloc(20 * sizeof(char *));
560           }
561           else if (litd_used == litd_allc)
562           {
563             litd_allc += 20;
564             litdname = (char **) realloc(litdname, litd_allc * sizeof(char *));
565             litd_val = (char **) realloc(litd_val, litd_allc * sizeof(char *));
566           }
567 
568           litdname[i] = (char *) malloc(20);
569           sprintf(litdname[i], "_litd%d_awka", i);
570           litd_val[i] = (char *) malloc(strlen(progcode[cur].val)+1);
571           strcpy(litd_val[i], progcode[cur].val);
572           litd_used++;
573         }
574 
575         progcode[cur].val = (char *) malloc(20);
576         strcpy(progcode[cur].val, litdname[i]);
577         break;
578 
579       case _PUSHS:
580         for (i=0; i<lits_used; i++)
581           if (!strcmp(lits_val[i], progcode[cur].val))
582             break;
583 
584         if (i == lits_used)
585         {
586           if (lits_allc == 0)
587           {
588             lits_allc = 20;
589             litsname = (char **) malloc(20 * sizeof(char *));
590             lits_val = (char **) malloc(20 * sizeof(char *));
591           }
592           else if (lits_used == lits_allc)
593           {
594             lits_allc += 20;
595             litsname = (char **) realloc(litsname, lits_allc * sizeof(char *));
596             lits_val = (char **) realloc(lits_val, lits_allc * sizeof(char *));
597           }
598 
599           litsname[i] = (char *) malloc(20);
600           sprintf(litsname[i], "_lits%d_awka", i);
601           lits_val[i] = (char *) malloc((strlen(progcode[cur].val)*2)+1);
602           strcpy(lits_val[i], fix_litsval(progcode[cur].val));
603           lits_used++;
604         }
605 
606         progcode[cur].val = (char *) malloc(20);
607         strcpy(progcode[cur].val, litsname[i]);
608         break;
609 
610       case _LJNZ:
611       case _LJZ:
612         j = atoi(progcode[cur].val);
613         progcode[cur].jumpto = -1;
614         if (j > progcode[cur].minst)
615         {
616           for (i=cur+1; i<prog_no; i++)
617           {
618             if (progcode[i].minst > j ||
619                 progcode[i].minst < progcode[cur].minst)
620               break;
621             if (progcode[i].minst == j)
622             {
623               progcode[i].ljumpfrom = cur;
624               progcode[cur].jumpto = i;
625               break;
626             }
627           }
628         }
629         else
630         {
631           for (i=cur-1; i>=0; i--)
632           {
633             if (progcode[i].minst < j ||
634                 progcode[i].minst > progcode[cur].minst)
635               break;
636             if (progcode[i].minst == j)
637             {
638               progcode[i].ljumpfrom = cur;
639               progcode[cur].jumpto = i;
640               break;
641             }
642           }
643         }
644         if (progcode[cur].jumpto == -1)
645           awka_error("parse error: lj[n]z target not found, line %d.\n",progcode[cur].line);
646         break;
647 
648       case _JMP:
649         j = atoi(progcode[cur].val);
650         progcode[cur].jumpto = -1;
651         if (j > progcode[cur].minst)
652         {
653           for (i=cur+1; i<prog_no; i++)
654           {
655             if (progcode[i].minst < progcode[cur].minst)
656               break;
657             if (progcode[i].minst >= j && progcode[i].op == _JNZ)
658             {
659               progcode[i].jumpfrom = cur;
660               progcode[i].jumpto = cur+1;
661               progcode[cur].jumpto = i;
662               break;
663             }
664           }
665         }
666         else
667         {
668           for (i=cur; i>=0; i--)
669           {
670             if (progcode[i].minst > progcode[cur].minst)
671               break;
672             if (progcode[i].minst == j)
673             {
674               progcode[i].jumpfrom = cur;
675               progcode[i].jumpto = cur+1;
676               progcode[cur].jumpto = i;
677               if (i == cur)
678                 progcode[i].foreverloop = 2;
679               else
680               {
681                 progcode[i].foreverloop = 1;
682                 progcode[cur].endloop++;
683               }
684               break;
685             }
686           }
687         }
688         if (progcode[cur].jumpto == -1 && progcode[cur].op == _JMP)
689           awka_error("parse error: jmp target not found, line %d.\n",progcode[cur].line);
690         break;
691 
692       case SET_ALOOP:
693       case _JZ:
694       case _QMARK:
695         j = atoi(progcode[cur].val);
696         progcode[cur].jumpto = -1;
697         if (j > progcode[cur].minst)
698         {
699           for (i=cur+1; i<prog_no; i++)
700           {
701             if (progcode[i].minst > j ||
702                 progcode[i].minst < progcode[cur].minst)
703               break;
704             if (progcode[i].minst == j)
705             {
706               progcode[cur].jumpto = i;
707               if (progcode[cur].op != _QMARK)
708                 progcode[i].endloop++;
709               break;
710             }
711           }
712         }
713         else
714         {
715           for (i=cur-1; i>=0; i--)
716           {
717             if (progcode[i].minst < j ||
718                 progcode[i].minst > progcode[cur].minst)
719               break;
720             if (progcode[i].minst == j)
721             {
722               progcode[cur].jumpto = i;
723               if (progcode[cur].op != _QMARK)
724                 progcode[i].endloop++;
725               break;
726             }
727           }
728         }
729         if (progcode[cur].jumpto == -1)
730           awka_error("parse error: set_al/jz/qmark target not found, line %d.\n",progcode[cur].line);
731         if (progcode[cur].op != SET_ALOOP)
732         {
733           if (progcode[cur].op == _QMARK)
734           {
735             j = atoi(progcode[i-1].val);
736             k = progcode[i-1].minst;
737             for (p=i; p<prog_no; p++)
738             {
739               if (progcode[p].minst > j ||
740                   progcode[p].minst < k)
741                 break;
742               if (progcode[p].minst == j)
743               {
744                 for (k=i; k<p; k++)
745                   moveprog(k, k-1);
746                 k--;
747                 progcode[k].op = _COLON;
748                 progcode[k].func = code[_COLON-1].func;
749                 break;
750               }
751             }
752           }
753           else if (progcode[i-1].op == _ELSE)
754           {
755             /* wimping out of a proper method */
756             progcode[i-1].op = _GOTO;
757             progcode[i-1].func = code[_GOTO-1].func;
758           }
759           progcode[cur].jumpto = -1;
760         }
761         break;
762 
763       case _JNZ:
764         /* a while or a do/while statement */
765         j = atoi(progcode[cur].val);
766         if (progcode[cur].jumpto == -1 || progcode[cur].jumpfrom == -1)
767         {
768           progcode[cur].jumpto = -1;
769           if (j > progcode[cur].minst)
770           {
771             for (i=cur+1; i<prog_no; i++)
772             {
773               if (progcode[i].minst > j ||
774                   progcode[i].minst < progcode[cur].minst)
775                 break;
776               if (progcode[i].minst == j)
777               {
778                 progcode[cur].jumpto = i;
779                 break;
780               }
781             }
782           }
783           else
784           {
785             for (i=cur-1; i>=0; i--)
786             {
787               if (progcode[i].minst < j ||
788                   progcode[i].minst > progcode[cur].minst)
789                 break;
790               if (progcode[i].minst == j)
791               {
792                 progcode[cur].jumpto = i;
793                 break;
794               }
795             }
796           }
797           if (progcode[cur].jumpto == -1)
798             awka_error("parse error: jnz target not found, line %d.\n",progcode[cur].line);
799           /* progcode[cur].jumpto = -1; */
800           if (cur > 0)
801             if (progcode[cur-1].op == _JMP)
802               break;  /* while loop */
803           progcode[i].doloop = TRUE;
804         }
805         break;
806 
807       case _GOTO:
808         j = atoi(progcode[cur].val);
809         if (j > progcode[cur].minst)
810         {
811           for (i=cur+1; i<prog_no; i++)
812           {
813             if (progcode[i].minst > j ||
814                 progcode[i].minst < progcode[cur].minst)
815               break;
816             if (progcode[i].minst == j)
817             {
818               progcode[i].label = TRUE;
819               break;
820             }
821           }
822         }
823         else
824         {
825           for (i=cur-1; i>=0; i--)
826           {
827             if (progcode[i].minst < j ||
828                 progcode[i].minst > progcode[cur].minst)
829               break;
830             if (progcode[i].minst == j)
831             {
832               progcode[i].label = TRUE;
833               break;
834             }
835           }
836         }
837         break;
838 
839       case _CALL:
840         i = strlen(progcode[cur].val);
841         if (progcode[cur].val[i-1] == '(')
842           progcode[cur].val[i-1] = '\0';
843         j = atoi(progcode[cur].arg);
844         max_call_args = (max_call_args > j ? max_call_args : j);
845         break;
846 
847       case _FUNCTION:
848         i = strlen(progcode[cur].val);
849         if (progcode[cur].val[i-1] == '(')
850           progcode[cur].val[i-1] = '\0';
851         for (i=0; i<func_no; i++)
852           if (!strcmp(functions[i], progcode[cur].val))
853             break;
854 
855         if (i == func_no)
856         {
857           if (func_no == func_allc)
858           {
859             func_allc *= 2;
860             functions = (char **) realloc(functions, func_allc * sizeof(char *));
861           }
862           functions[i] = (char *) malloc(strlen(progcode[cur].val)+1);
863           strcpy(functions[i], progcode[cur].val);
864           func_no++;
865         }
866         break;
867     }
868 
869   }
870 
871   /* another pass to decide whether calls are to functions or to
872      extended builtins. */
873   for (cur=0; cur<prog_no; cur++)
874   {
875     /* find extended builtins & see if the're locals */
876     for (ebp = ext_funcs; ebp->name != NULL; ebp++)
877       if (ebp->op == progcode[cur].op)
878         break;
879 
880     if (ebp->name)
881     {
882       for (i=0; i<func_no; i++)
883         if (!strcmp(functions[i], ebp->name))
884           break;
885 
886       if (i < func_no)
887       {
888         progcode[cur].func = awka_call;
889         progcode[cur].op = _CALL;
890         progcode[cur].pop = FALSE;
891         progcode[cur].val = functions[i];
892         if (cur == 0 || progcode[cur-1].inst != _PUSHINT)
893         {
894           progcode[cur].arg = (char *) malloc(20);
895           sprintf(progcode[cur].arg, "%d", _a_bi_vararg[progcode[cur].varidx].min_args);
896         }
897         progcode[cur].varidx = -1;
898       }
899       continue;
900     }
901 
902     /* find locals & see if the're extended builtins */
903     if (progcode[cur].op == _CALL)
904     {
905       for (i=0; i<func_no; i++)
906         if (!strcmp(functions[i], progcode[cur].val))
907           break;
908 
909       if (i == func_no)
910       {
911         /* local definition don't exist - is it an extended func? */
912         for (ebp = ext_funcs; ebp->name != NULL; ebp++)
913           if (!strcmp(progcode[cur].val, ebp->name))
914           {
915             progcode[cur].op = ebp->op;
916             progcode[cur].varidx = code[ebp->op-1].varidx;
917             progcode[cur].pop = code[ebp->op-1].pop;
918             progcode[cur].func = code[ebp->op-1].func;
919             break;
920           }
921       }
922     }
923 
924   }
925 
926   /* set up range patterns */
927   for (cur=prog_no-1; cur>=0; cur--)
928   {
929     if (progcode[cur].op == _RANGE)
930     {
931       j = atoi(progcode[cur].val);
932       k = progcode[cur].endloop;
933       q = progcode[cur].val;
934       while (*q && *q != ' ') q++;
935       if (!(*q))
936         awka_error("parse error: range value not set correctly, line %d.\n",progcode[cur].line);
937       j2 = atoi(++q);
938       while (*q && *q != ' ') q++;
939       if (!(*q))
940         awka_error("parse error: range value not set correctly, line %d.\n",progcode[cur].line);
941       j3 = atoi(q);
942 
943       /* find end of patterns */
944       for (i=cur+1; i<prog_no; i++)
945       {
946         if (progcode[i].minst > j2)
947           awka_error("parse error: can't find range target (1), line %d.\n", progcode[cur].line);
948         if (progcode[i].minst == j2)
949           break;
950       }
951       if (i == prog_no)
952         awka_error("parse error: can't find range target (2), line %d.\n", progcode[cur].line);
953       j2 = i-1;
954 
955       /* find jumpto opcode */
956       for (i=j2+1; i<prog_no; i++)
957       {
958         if (progcode[i].minst > j3)
959           awka_error("parse error: can't find range target (3), line %d.\n", progcode[cur].line);
960         if (progcode[i].minst == j3)
961           break;
962       }
963       if (i == prog_no)
964         awka_error("parse error: can't find range target (4), line %d.\n", progcode[cur].line);
965       j3 = i;
966       progcode[i].label = TRUE;
967       progcode[cur+1].label = progcode[cur].label;
968       progcode[cur+1].minst = progcode[cur].minst;
969 
970       /* move range opcode to end of patterns */
971       for (i=cur+1; i<=j2; i++)
972         moveprog(i, i-1);
973       progcode[--i].op = _RANGE;
974       progcode[i].val = (char *) malloc(20);
975       sprintf(progcode[i].val, "%d", progcode[j3].minst);
976       progcode[i].arg = NULL;
977       progcode[i].func = awka_range;
978       progcode[i].jumpto = j3;
979       progcode[i].endloop = k;
980     }
981   }
982 
983   if (warning_msg & MSG_VARDECLARE)
984   {
985     for (i=0; i<var_used; i++)
986     {
987       for (j=0; j<vdec_no; j++)
988         if (!strcmp(varname[i].name, vardeclare[j]))
989           break;
990       if (j == vdec_no)
991         awka_warning("global variable '%s' not declared in VDECL comment.\n",varname[i].name);
992     }
993   }
994 
995   fprintf(outfp, "\nstruct gvar_struct *_gvar;\n");
996   fprintf(outfp, "\na_VAR **_lvar;\n");
997 
998   if (litd_used)
999   {
1000     fprintf(outfp, "a_VAR *_litd0_awka=NULL");
1001     for (i=1; i<litd_used; i++)
1002       fprintf(outfp, ", *_litd%d_awka=NULL",i);
1003     fprintf(outfp, ";\n");
1004   }
1005 
1006   if (lits_used)
1007   {
1008     fprintf(outfp, "a_VAR *_lits0_awka=NULL");
1009     for (i=1; i<lits_used; i++)
1010       fprintf(outfp, ", *_lits%d_awka=NULL",i);
1011     fprintf(outfp, ";\n");
1012   }
1013 
1014   if (litr_used)
1015   {
1016     fprintf(outfp, "a_VAR *_litr0_awka=NULL");
1017     for (i=1; i<litr_used; i++)
1018       fprintf(outfp, ", *_litr%d_awka=NULL",i);
1019     fprintf(outfp, ";\n");
1020   }
1021 
1022   for (i=0; i<func_no; i++)
1023     fprintf(outfp, "a_VAR * %s_fn(a_VARARG *);\n",functions[i]);
1024   if (begin_used)
1025     fprintf(outfp, "void BEGIN();\n");
1026   if (main_used)
1027     fprintf(outfp, "void MAIN();\n");
1028   if (end_used)
1029     fprintf(outfp, "void END();\n");
1030 }
1031 
1032