Git init
[external/mawk.git] / code.c
1
2 /********************************************
3 code.c
4 copyright 1991-93, 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: code.c,v $
15  * Revision 1.6  1995/06/18  19:42:13  mike
16  * Remove some redundant declarations and add some prototypes
17  *
18  * Revision 1.5  1995/06/09  23:21:36  mike
19  * make sure there is an execution block in case user defines function,
20  * but no pattern-action pairs
21  *
22  * Revision 1.4  1995/03/08  00:06:22  mike
23  * add a pointer cast
24  *
25  * Revision 1.3  1994/10/08  19:15:29  mike
26  * remove SM_DOS
27  *
28  * Revision 1.2  1993/07/07  00:07:38  mike
29  * more work on 1.2
30  *
31  * Revision 1.1.1.1  1993/07/03  18:58:10  mike
32  * move source to cvs
33  *
34  * Revision 5.4  1993/01/14  13:11:11  mike
35  * code2() -> xcode2()
36  *
37  * Revision 5.3  1993/01/09  20:15:35  mike
38  * code_pop checks if the resolve_list needs relocation
39  *
40  * Revision 5.2  1993/01/07  02:50:33  mike
41  * relative vs absolute code
42  *
43  * Revision 5.1  1991/12/05  07:55:43  brennan
44  * 1.1 pre-release
45  *
46 */
47
48 /*  code.c  */
49
50 #include "mawk.h"
51 #include "code.h"
52 #include "init.h"
53 #include "jmp.h"
54 #include "field.h"
55
56
57 static CODEBLOCK *PROTO(new_code, (void)) ;
58
59 CODEBLOCK active_code ;
60
61 CODEBLOCK *main_code_p, *begin_code_p, *end_code_p ;
62
63 INST *begin_start, *main_start, *end_start ;
64 unsigned begin_size, main_size ;
65
66 INST *execution_start = 0 ;
67
68
69 /* grow the active code */
70 void
71 code_grow()
72 {
73    unsigned oldsize = code_limit - code_base ;
74    unsigned newsize = PAGESZ + oldsize ;
75    unsigned delta = code_ptr - code_base ;
76
77    if (code_ptr > code_limit)  bozo("CODEWARN is too small") ;
78
79    code_base = (INST *)
80       zrealloc(code_base, INST_BYTES(oldsize),
81                INST_BYTES(newsize)) ;
82    code_limit = code_base + newsize ;
83    code_warn = code_limit - CODEWARN ;
84    code_ptr = code_base + delta ;
85 }
86
87 /* shrinks executable code that's done to its final size */
88 INST *
89 code_shrink(p, sizep)
90    CODEBLOCK *p ;
91    unsigned *sizep ;
92 {
93
94    unsigned oldsize = INST_BYTES(p->limit - p->base) ;
95    unsigned newsize = INST_BYTES(p->ptr - p->base) ;
96    INST *retval ;
97
98    *sizep = newsize ;
99
100    retval = (INST *) zrealloc(p->base, oldsize, newsize) ;
101    ZFREE(p) ;
102    return retval ;
103 }
104
105
106 /* code an op and a pointer in the active_code */
107 void
108 xcode2(op, ptr)
109    int op ;
110    PTR ptr ;
111 {
112    register INST *p = code_ptr + 2 ;
113
114    if (p >= code_warn)
115    {
116       code_grow() ;
117       p = code_ptr + 2 ;
118    }
119
120    p[-2].op = op ;
121    p[-1].ptr = ptr ;
122    code_ptr = p ;
123 }
124
125 /* code two ops in the active_code */
126 void
127 code2op(x, y)
128    int x, y ;
129 {
130    register INST *p = code_ptr + 2 ;
131
132    if (p >= code_warn)
133    {
134       code_grow() ;
135       p = code_ptr + 2 ;
136    }
137
138    p[-2].op = x ;
139    p[-1].op = y ;
140    code_ptr = p ;
141 }
142
143 void
144 code_init()
145 {
146    main_code_p = new_code() ;
147
148    active_code = *main_code_p ;
149    code1(_OMAIN) ;
150 }
151
152 /* final code relocation
153    set_code() as in set concrete */
154 void
155 set_code()
156 {
157    /* set the main code which is active_code */
158    if (end_code_p || code_offset > 1)
159    {
160       int gl_offset = code_offset ;
161       extern int NR_flag ;
162
163       if (NR_flag)  code2op(OL_GL_NR, _HALT) ;
164       else  code2op(OL_GL, _HALT) ;
165
166       *main_code_p = active_code ;
167       main_start = code_shrink(main_code_p, &main_size) ;
168       next_label = main_start + gl_offset ;
169       execution_start = main_start ;
170    }
171    else  /* only BEGIN */
172    {
173       zfree(code_base, INST_BYTES(PAGESZ)) ;
174       ZFREE(main_code_p) ;
175    }
176
177    /* set the END code */
178    if (end_code_p)
179    {
180       unsigned dummy ;
181
182       active_code = *end_code_p ;
183       code2op(_EXIT0, _HALT) ;
184       *end_code_p = active_code ;
185       end_start = code_shrink(end_code_p, &dummy) ;
186    }
187
188    /* set the BEGIN code */
189    if (begin_code_p)
190    {
191       active_code = *begin_code_p ;
192       if (main_start)  code2op(_JMAIN, _HALT) ;
193       else  code2op(_EXIT0, _HALT) ;
194       *begin_code_p = active_code ;
195       begin_start = code_shrink(begin_code_p, &begin_size) ;
196
197       execution_start = begin_start ;
198    }
199
200    if ( ! execution_start )
201    {
202       /* program had functions but no pattern-action bodies */
203       execution_start = begin_start = (INST*) zmalloc(2*sizeof(INST)) ;
204       execution_start[0].op = _EXIT0 ;
205       execution_start[1].op = _HALT  ;
206    }
207 }
208
209 void
210 dump_code()
211 {
212    fdump() ;                     /* dumps all user functions */
213    if (begin_start)  
214    { fprintf(stdout, "BEGIN\n") ; 
215      da(begin_start, stdout) ; }
216    if (end_start)  
217    { fprintf(stdout, "END\n") ; 
218      da(end_start, stdout) ; }
219    if (main_start)  
220    { fprintf(stdout, "MAIN\n") ; 
221      da(main_start, stdout) ; }
222 }
223
224
225 static CODEBLOCK *
226 new_code()
227 {
228    CODEBLOCK *p = ZMALLOC(CODEBLOCK) ;
229
230    p->base = (INST *) zmalloc(INST_BYTES(PAGESZ)) ;
231    p->limit = p->base + PAGESZ ;
232    p->warn = p->limit - CODEWARN ;
233    p->ptr = p->base ;
234
235    return p ;
236 }
237
238 /* moves the active_code from MAIN to a BEGIN or END */
239
240 void
241 be_setup(scope)
242    int scope ;
243 {
244    *main_code_p = active_code ;
245
246    if (scope == SCOPE_BEGIN)
247    {
248       if (!begin_code_p)  begin_code_p = new_code() ;
249       active_code = *begin_code_p ;
250    }
251    else
252    {
253       if (!end_code_p)  end_code_p = new_code() ;
254       active_code = *end_code_p ;
255    }
256 }