Git init
[external/mawk.git] / da.c
1
2 /********************************************
3 da.c
4 copyright 1991, Michael D. Brennan
5
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
8
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
12
13
14 /* $Log: da.c,v $
15  * Revision 1.6  1995/06/18  19:19:59  mike
16  * remove use of comma operator that broke some sysVr3 compilers
17  *
18  * Revision 1.5  1994/12/13  00:12:08  mike
19  * delete A statement to delete all of A at once
20  *
21  * Revision 1.4  1994/10/08  19:15:32  mike
22  * remove SM_DOS
23  *
24  * Revision 1.3  1993/12/01  14:25:10  mike
25  * reentrant array loops
26  *
27  * Revision 1.2  1993/07/22  00:04:05  mike
28  * new op code _LJZ _LJNZ
29  *
30  * Revision 1.1.1.1  1993/07/03  18:58:10  mike
31  * move source to cvs
32  *
33  * Revision 5.4  1993/01/09  19:05:48  mike
34  * dump code to stdout and exit(0)
35  *
36  * Revision 5.3  1993/01/07  02:50:33  mike
37  * relative vs absolute code
38  *
39  * Revision 5.2  1992/07/25  21:35:25  brennan
40  * patch2
41  * fixed small typo on da of _PRE_DEC
42  *
43  * Revision 5.1  1991/12/05  07:55:45  brennan
44  * 1.1 pre-release
45  *
46 */
47
48
49 /*  da.c  */
50 /*  disassemble code */
51
52
53
54 #include  "mawk.h"
55
56
57 #include  "code.h"
58 #include  "bi_funct.h"
59 #include  "repl.h"
60 #include  "field.h"
61
62 static char *PROTO(find_bi_name, (PF_CP)) ;
63
64 static struct sc
65 {
66    char op ; 
67    char *name ;
68 } simple_code[] =
69
70 {
71    {_STOP, "stop"},
72    {FE_PUSHA, "fe_pusha"},
73    {FE_PUSHI, "fe_pushi"},
74    {A_TEST, "a_test"},
75    {A_DEL, "a_del"},
76    {DEL_A, "del_a"},
77    {POP_AL, "pop_al"},
78    {_POP, "pop"},
79    {_ADD, "add"},
80    {_SUB, "sub"},
81    {_MUL, "mul"},
82    {_DIV, "div"},
83    {_MOD, "mod"},
84    {_POW, "pow"},
85    {_NOT, "not"},
86    {_UMINUS, "uminus"},
87    {_UPLUS, "uplus"},
88    {_TEST, "test"},
89    {_CAT, "cat"},
90    {_ASSIGN, "assign"},
91    {_ADD_ASG, "add_asg"},
92    {_SUB_ASG, "sub_asg"},
93    {_MUL_ASG, "mul_asg"},
94    {_DIV_ASG, "div_asg"},
95    {_MOD_ASG, "mod_asg"},
96    {_POW_ASG, "pow_asg"},
97    {NF_PUSHI, "nf_pushi"},
98    {F_ASSIGN, "f_assign"},
99    {F_ADD_ASG, "f_add_asg"},
100    {F_SUB_ASG, "f_sub_asg"},
101    {F_MUL_ASG, "f_mul_asg"},
102    {F_DIV_ASG, "f_div_asg"},
103    {F_MOD_ASG, "f_mod_asg"},
104    {F_POW_ASG, "f_pow_asg"},
105    {_POST_INC, "post_inc"},
106    {_POST_DEC, "post_dec"},
107    {_PRE_INC, "pre_inc"},
108    {_PRE_DEC, "pre_dec"},
109    {F_POST_INC, "f_post_inc"},
110    {F_POST_DEC, "f_post_dec"},
111    {F_PRE_INC, "f_pre_inc"},
112    {F_PRE_DEC, "f_pre_dec"},
113    {_EQ, "eq"},
114    {_NEQ, "neq"},
115    {_LT, "lt"},
116    {_LTE, "lte"},
117    {_GT, "gt"},
118    {_GTE, "gte"},
119    {_MATCH2, "match2"},
120    {_EXIT, "exit"},
121    {_EXIT0, "exit0"},
122    {_NEXT, "next"},
123    {_RET, "ret"},
124    {_RET0, "ret0"},
125    {_OMAIN, "omain"},
126    {_JMAIN, "jmain"},
127    {OL_GL, "ol_gl"},
128    {OL_GL_NR, "ol_gl_nr"},
129    {_HALT, (char *) 0}
130 } ;
131
132 static char *jfmt = "%s%s%03d\n" ; 
133    /* format to print jumps */
134 static char *tab2 = "\t\t" ;
135
136 void
137 da(start, fp)
138    INST *start ;
139    FILE *fp ;
140 {
141    CELL *cp ;
142    register INST *p = start ;
143    char *name ;
144
145    while (p->op != _HALT)
146    {
147       /* print the relative code address (label) */
148       fprintf(fp, "%03d ", p - start) ;
149
150       switch (p++->op)
151       {
152
153          case _PUSHC:
154             cp = (CELL *) p++->ptr ;
155             switch (cp->type)
156             {
157                case C_RE:
158                   fprintf(fp, "pushc\t0x%lx\t/%s/\n", (long) cp->ptr,
159                           re_uncompile(cp->ptr)) ;
160                   break ;
161
162                case C_SPACE:
163                   fprintf(fp, "pushc\tspace split\n") ;
164                   break ;
165
166                case C_SNULL:
167                   fprintf(fp, "pushc\tnull split\n") ;
168                   break ;
169                case C_REPL:
170                   fprintf(fp, "pushc\trepl\t%s\n",
171                           repl_uncompile(cp)) ;
172                   break ;
173                case C_REPLV:
174                   fprintf(fp, "pushc\treplv\t%s\n",
175                           repl_uncompile(cp)) ;
176                   break ;
177
178                default:
179                   fprintf(fp,"pushc\tWEIRD\n") ;  ;
180                   break ;
181             }
182             break ;
183
184          case _PUSHD:
185             fprintf(fp, "pushd\t%.6g\n", *(double *) p++->ptr) ;
186             break ;
187          case _PUSHS:
188             {
189                STRING *sval = (STRING *) p++->ptr ;
190                fprintf(fp, "pushs\t\"%s\"\n", sval->str) ;
191                break ;
192             }
193
194          case _MATCH0:
195          case _MATCH1:
196             fprintf(fp, "match%d\t0x%lx\t/%s/\n",
197                     p[-1].op == _MATCH1, (long) p->ptr,
198                     re_uncompile(p->ptr)) ;
199             p++ ;
200             break ;
201
202          case _PUSHA:
203             fprintf(fp, "pusha\t%s\n",
204                     reverse_find(ST_VAR, &p++->ptr)) ;
205             break ;
206
207          case _PUSHI:
208             cp = (CELL *) p++->ptr ;
209             if (cp == field)  fprintf(fp, "pushi\t$0\n") ;
210             else if (cp == &fs_shadow)
211                fprintf(fp, "pushi\t@fs_shadow\n") ;
212             else
213             {
214                if (
215 #ifdef  MSDOS
216                      SAMESEG(cp, field) &&
217 #endif
218                      cp > NF && cp <= LAST_PFIELD)
219                   name = reverse_find(ST_FIELD, &cp) ;
220                else  name = reverse_find(ST_VAR, &cp) ;
221
222                fprintf(fp, "pushi\t%s\n", name) ;
223             }
224             break ;
225
226          case L_PUSHA:
227             fprintf(fp, "l_pusha\t%d\n", p++->op) ;
228             break ;
229
230          case L_PUSHI:
231             fprintf(fp, "l_pushi\t%d\n", p++->op) ;
232             break ;
233
234          case LAE_PUSHI:
235             fprintf(fp, "lae_pushi\t%d\n", p++->op) ;
236             break ;
237
238          case LAE_PUSHA:
239             fprintf(fp, "lae_pusha\t%d\n", p++->op) ;
240             break ;
241
242          case LA_PUSHA:
243             fprintf(fp, "la_pusha\t%d\n", p++->op) ;
244             break ;
245
246          case F_PUSHA:
247             cp = (CELL *) p++->ptr ;
248             if (
249 #ifdef  MSDOS
250                   SAMESEG(cp, field) &&
251 #endif
252                   cp >= NF && cp <= LAST_PFIELD)
253                fprintf(fp, "f_pusha\t%s\n",
254                        reverse_find(ST_FIELD, &cp)) ;
255             else  fprintf(fp, "f_pusha\t$%d\n",
256                        field_addr_to_index(cp)) ;
257             break ;
258
259          case F_PUSHI:
260             p++ ;
261             fprintf(fp, "f_pushi\t$%d\n", p++->op) ;
262             break ;
263
264          case AE_PUSHA:
265             fprintf(fp, "ae_pusha\t%s\n",
266                     reverse_find(ST_ARRAY, &p++->ptr)) ;
267             break ;
268
269          case AE_PUSHI:
270             fprintf(fp, "ae_pushi\t%s\n",
271                     reverse_find(ST_ARRAY, &p++->ptr)) ;
272             break ;
273
274          case A_PUSHA:
275             fprintf(fp, "a_pusha\t%s\n",
276                     reverse_find(ST_ARRAY, &p++->ptr)) ;
277             break ;
278
279          case _PUSHINT:
280             fprintf(fp, "pushint\t%d\n", p++->op) ;
281             break ;
282
283          case _BUILTIN:
284             fprintf(fp, "%s\n",
285                     find_bi_name((PF_CP) p++->ptr)) ;
286             break ;
287
288          case _PRINT:
289             fprintf(fp, "%s\n",
290                     (PF_CP) p++->ptr == bi_printf
291                     ? "printf" : "print") ;
292             break ;
293
294          case _JMP:
295             fprintf(fp, jfmt, "jmp", tab2, (p - start) + p->op) ;
296             p++ ;
297             break ;
298
299          case _JNZ:
300             fprintf(fp, jfmt, "jnz", tab2, (p - start) + p->op) ;
301             p++ ;
302             break ;
303
304          case _JZ:
305             fprintf(fp, jfmt, "jz", tab2, (p - start) + p->op) ;
306             p++ ;
307             break ;
308
309          case _LJZ:
310             fprintf(fp, jfmt, "ljz", tab2, (p - start) + p->op) ;
311             p++ ;
312             break ;
313
314          case _LJNZ:
315             fprintf(fp, jfmt, "ljnz", tab2+1 , (p - start) + p->op) ;
316             p++ ;
317             break ;
318
319          case SET_ALOOP:
320             fprintf(fp, "set_al\t%03d\n", p + p->op - start) ;
321             p++ ;
322             break ;
323
324          case ALOOP:
325             fprintf(fp, "aloop\t%03d\n", p - start + p->op) ;
326             p++ ;
327             break ;
328
329          case  A_CAT :
330             fprintf(fp,"a_cat\t%d\n", p++->op) ;
331             break ;
332
333          case _CALL:
334             fprintf(fp, "call\t%s\t%d\n",
335                     ((FBLOCK *) p->ptr)->name, p[1].op) ;
336             p += 2 ;
337             break ;
338
339          case _RANGE:
340             fprintf(fp, "range\t%03d %03d %03d\n",
341             /* label for pat2, action, follow */
342                     p - start + p[1].op,
343                     p - start + p[2].op,
344                     p - start + p[3].op) ;
345             p += 4 ;
346             break ;
347          default:
348             {
349                struct sc *q = simple_code ;
350                int k = (p - 1)->op ;
351
352                while (q->op != _HALT && q->op != k)  q++ ;
353
354                fprintf(fp, "%s\n",
355                        q->op != _HALT ? q->name : "bad instruction") ;
356             }
357             break ;
358       }
359    }
360    fflush(fp) ;
361 }
362
363 static struct
364 {
365    PF_CP action ;
366    char *name ;
367 }
368 special_cases[] =
369 {
370    {bi_split, "split"},
371    {bi_match, "match"},
372    {bi_getline, "getline"},
373    {bi_sub, "sub"},
374    {bi_gsub, "gsub"},
375    {(PF_CP) 0, (char *) 0}
376 } ;
377
378 static char *
379 find_bi_name(p)
380    PF_CP p ;
381 {
382    BI_REC *q ;
383    int i ;
384
385    for (q = bi_funct; q->name; q++)
386    {
387       if (q->fp == p)
388       {
389          /* found */
390          return q->name ;
391       }
392    }
393    /* next check some special cases */
394    for (i = 0; special_cases[i].action; i++)
395    {
396       if (special_cases[i].action == p)  return special_cases[i].name ;
397    }
398
399    return "unknown builtin" ;
400 }
401
402 static struct fdump
403 {
404    struct fdump *link ;
405    FBLOCK *fbp ;
406 } *fdump_list ;                  /* linked list of all user functions */
407
408 void
409 add_to_fdump_list(fbp)
410    FBLOCK *fbp ;
411 {
412    struct fdump *p = ZMALLOC(struct fdump) ;
413    p->fbp = fbp ;
414    p->link = fdump_list ;  fdump_list = p ;
415 }
416
417 void
418 fdump()
419 {
420    register struct fdump *p, *q = fdump_list ;
421
422    while (q)
423    {
424       p = q ;
425       q = p->link ;
426       fprintf(stdout, "function %s\n", p->fbp->name) ;
427       da(p->fbp->code, stdout) ;
428       ZFREE(p) ;
429    }
430 }
431