~ubuntu-branches/ubuntu/jaunty/mawk/jaunty

« back to all changes in this revision

Viewing changes to jmp.c

  • Committer: Bazaar Package Importer
  • Author(s): James Troup
  • Date: 2001-07-18 20:40:37 UTC
  • Revision ID: james.westby@ubuntu.com-20010718204037-8hrndw7iapy9yj3w
Tags: upstream-1.3.3
ImportĀ upstreamĀ versionĀ 1.3.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/********************************************
 
3
jmp.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
/* $Log: jmp.c,v $
 
14
 * Revision 1.4  1995/06/18  19:42:19  mike
 
15
 * Remove some redundant declarations and add some prototypes
 
16
 *
 
17
 * Revision 1.3  1995/04/21  14:20:16  mike
 
18
 * move_level variable to fix bug in arglist patching of moved code.
 
19
 *
 
20
 * Revision 1.2  1993/07/14  13:17:49  mike
 
21
 * rm SIZE_T and run thru indent
 
22
 *
 
23
 * Revision 1.1.1.1  1993/07/03  18:58:15  mike
 
24
 * move source to cvs
 
25
 *
 
26
 * Revision 5.3  1993/01/09  19:03:44  mike
 
27
 * code_pop checks if the resolve_list needs relocation
 
28
 *
 
29
 * Revision 5.2  1993/01/07  02:50:33  mike
 
30
 * relative vs absolute code
 
31
 *
 
32
 * Revision 5.1  1991/12/05  07:56:10  brennan
 
33
 * 1.1 pre-release
 
34
 *
 
35
*/
 
36
 
 
37
/* this module deals with back patching jumps, breaks and continues,
 
38
   and with save and restoring code when we move code.
 
39
   There are three stacks.  If we encounter a compile error, the
 
40
   stacks are frozen, i.e., we do not attempt error recovery
 
41
   on the stacks
 
42
*/
 
43
 
 
44
 
 
45
#include "mawk.h"
 
46
#include "symtype.h"
 
47
#include "jmp.h"
 
48
#include "code.h"
 
49
#include "sizes.h"
 
50
#include "init.h"
 
51
#include "memory.h"
 
52
 
 
53
#define error_state  (compile_error_count>0)
 
54
 
 
55
 
 
56
/*---------- back patching jumps  ---------------*/
 
57
 
 
58
typedef struct jmp
 
59
{
 
60
   struct jmp *link ;
 
61
   int source_offset ;
 
62
}
 
63
JMP ;
 
64
 
 
65
static JMP *jmp_top ;
 
66
 
 
67
void
 
68
code_jmp(jtype, target)
 
69
   int jtype ;
 
70
   INST *target ;
 
71
{
 
72
   if (error_state)  return ;
 
73
 
 
74
   /* WARNING: Don't emit any code before using target or
 
75
     relocation might make it invalid */
 
76
 
 
77
   if (target)  code2op(jtype, target - (code_ptr + 1)) ;
 
78
   else
 
79
   {
 
80
      register JMP *p = ZMALLOC(JMP) ;
 
81
 
 
82
      /* stack for back patch */
 
83
      code2op(jtype, 0) ;
 
84
      p->source_offset = code_offset - 1 ;
 
85
      p->link = jmp_top ;
 
86
      jmp_top = p ;
 
87
   }
 
88
}
 
89
 
 
90
void
 
91
patch_jmp(target)               /* patch a jump on the jmp_stack */
 
92
   INST *target ;
 
93
{
 
94
   register JMP *p ;
 
95
   register INST *source ;       /* jmp starts here */
 
96
 
 
97
   if (!error_state)
 
98
   {
 
99
#ifdef  DEBUG
 
100
      if (!jmp_top)  bozo("jmp stack underflow") ;
 
101
#endif
 
102
 
 
103
      p = jmp_top ; jmp_top = p->link ;
 
104
      source = p->source_offset + code_base ;
 
105
      source->op = target - source ;
 
106
 
 
107
      ZFREE(p) ;
 
108
   }
 
109
}
 
110
 
 
111
 
 
112
/*-- break and continue -------*/
 
113
 
 
114
typedef struct bc
 
115
{
 
116
   struct bc *link ;             /* stack as linked list */
 
117
   int type ;                    /* 'B' or 'C' or mark start with 0 */
 
118
   int source_offset ;           /* position of _JMP  */
 
119
}
 
120
BC ;
 
121
 
 
122
static BC *bc_top ;
 
123
 
 
124
 
 
125
 
 
126
void
 
127
BC_new()                        /* mark the start of a loop */
 
128
{
 
129
   BC_insert(0, (INST *) 0) ;
 
130
}
 
131
 
 
132
void
 
133
BC_insert(type, address)
 
134
int type ; INST *address ;
 
135
{
 
136
   register BC *p ;
 
137
 
 
138
   if (error_state)  return ;
 
139
 
 
140
   if (type && !bc_top)
 
141
   {
 
142
      compile_error("%s statement outside of loop",
 
143
                    type == 'B' ? "break" : "continue") ;
 
144
 
 
145
      return ;
 
146
   }
 
147
   else
 
148
   {
 
149
      p = ZMALLOC(BC) ;
 
150
      p->type = type ;
 
151
      p->source_offset = address - code_base ;
 
152
      p->link = bc_top ;
 
153
      bc_top = p ;
 
154
   }
 
155
}
 
156
 
 
157
 
 
158
/* patch all break and continues for one loop */
 
159
void
 
160
BC_clear(B_address, C_address)
 
161
   INST *B_address, *C_address ;
 
162
{
 
163
   register BC *p, *q ;
 
164
   INST *source ;
 
165
 
 
166
   if (error_state)  return ;
 
167
 
 
168
   p = bc_top ;
 
169
   /* pop down to the mark node */
 
170
   while (p->type)
 
171
   {
 
172
      source = code_base + p->source_offset ;
 
173
      source->op = (p->type == 'B' ? B_address : C_address)
 
174
         - source ;
 
175
 
 
176
      q = p ; p = p->link ; ZFREE(q) ;
 
177
   }
 
178
   /* remove the mark node */
 
179
   bc_top = p->link ;
 
180
   ZFREE(p) ;
 
181
}
 
182
 
 
183
/*-----  moving code --------------------------*/
 
184
 
 
185
/* a stack to hold some pieces of code while
 
186
   reorganizing loops .
 
187
*/
 
188
 
 
189
typedef struct mc
 
190
{                               /* mc -- move code */
 
191
   struct mc *link ;
 
192
   INST *code ;                  /* the save code */
 
193
   unsigned len ;                /* its length */
 
194
   int scope ;                   /* its scope */
 
195
   int move_level ;              /* size of this stack when coded */
 
196
   FBLOCK *fbp ;                 /* if scope FUNCT */
 
197
   int offset ;                  /* distance from its code base */
 
198
}
 
199
MC ;
 
200
 
 
201
static MC *mc_top ;
 
202
int code_move_level = 0 ; /* see comment in jmp.h */
 
203
 
 
204
#define  NO_SCOPE       -1
 
205
 /* means relocation of resolve list not needed */
 
206
 
 
207
void
 
208
code_push(code, len, scope, fbp)
 
209
   INST *code ;
 
210
   unsigned len ;
 
211
   int scope ;
 
212
   FBLOCK *fbp ;
 
213
{
 
214
   register MC *p ;
 
215
 
 
216
   if (!error_state)
 
217
   {
 
218
      p = ZMALLOC(MC) ;
 
219
      p->len = len ;
 
220
      p->link = mc_top ;
 
221
      mc_top = p ;
 
222
 
 
223
      if (len)
 
224
      {
 
225
         p->code = (INST *) zmalloc(sizeof(INST) * len) ;
 
226
         memcpy(p->code, code, sizeof(INST) * len) ;
 
227
      }
 
228
      if (!resolve_list)  p->scope = NO_SCOPE ;
 
229
      else
 
230
      {
 
231
         p->scope = scope ;
 
232
         p->move_level = code_move_level ;
 
233
         p->fbp = fbp ;
 
234
         p->offset = code - code_base ;
 
235
      }
 
236
   }
 
237
   code_move_level++ ;
 
238
}
 
239
 
 
240
/* copy the code at the top of the mc stack to target.
 
241
   return the number of INSTs moved */
 
242
 
 
243
unsigned
 
244
code_pop(target)
 
245
   INST *target ;
 
246
{
 
247
   register MC *p ;
 
248
   unsigned len ;
 
249
   int target_offset ;
 
250
 
 
251
   if (error_state)  return 0 ;
 
252
 
 
253
#ifdef  DEBUG
 
254
   if (!mc_top)  bozo("mc underflow") ;
 
255
#endif
 
256
 
 
257
   p = mc_top ; mc_top = p->link ;
 
258
   len = p->len ;
 
259
 
 
260
   while (target + len >= code_warn)
 
261
   {
 
262
      target_offset = target - code_base ;
 
263
      code_grow() ;
 
264
      target = code_base + target_offset ;
 
265
   }
 
266
 
 
267
   if (len)
 
268
   {
 
269
      memcpy(target, p->code, len * sizeof(INST)) ;
 
270
      zfree(p->code, len * sizeof(INST)) ;
 
271
   }
 
272
 
 
273
   if (p->scope != NO_SCOPE)
 
274
   {
 
275
      target_offset = target - code_base ;
 
276
      relocate_resolve_list(p->scope, p->move_level, p->fbp,
 
277
                         p->offset, len, target_offset - p->offset) ;
 
278
   }
 
279
 
 
280
   ZFREE(p) ;
 
281
   code_move_level-- ;
 
282
   return len ;
 
283
}