source: trunk/minix/commands/bc/load.c@ 10

Last change on this file since 10 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 7.2 KB
RevLine 
[9]1/* load.c: This code "loads" code into the code segments. */
2
3/* This file is part of bc written for MINIX.
4 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License , or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 You may contact the author by:
21 e-mail: phil@cs.wwu.edu
22 us-mail: Philip A. Nelson
23 Computer Science Department, 9062
24 Western Washington University
25 Bellingham, WA 98226-9062
26
27*************************************************************************/
28
29#include "bcdefs.h"
30#include "global.h"
31#include "proto.h"
32
33/* Load variables. */
34
35program_counter load_adr;
36char load_str;
37char load_const;
38
39/* Initialize the load sequence. */
40void
41init_load ()
42{
43 clear_func(0);
44 load_adr.pc_func = 0;
45 load_adr.pc_addr = 0;
46 load_str = FALSE;
47 load_const = FALSE;
48}
49
50/* addbyte adds one BYTE to the current code segment. */
51void
52addbyte (byte)
53 char byte;
54{
55 int seg, offset, func;
56
57 /* If there was an error, don't continue. */
58 if (had_error) return;
59
60 /* Calculate the segment and offset. */
61 seg = load_adr.pc_addr >> BC_SEG_LOG;
62 offset = load_adr.pc_addr++ % BC_SEG_SIZE;
63 func = load_adr.pc_func;
64
65 if (seg >= BC_MAX_SEGS)
66 {
67 yyerror ("Function too big.");
68 return;
69 }
70
71 if (functions[func].f_body[seg] == NULL)
72 functions[func].f_body[seg] = (char *) bc_malloc (BC_SEG_SIZE);
73
74 /* Store the byte. */
75 functions[func].f_body[seg][offset] = byte;
76 functions[func].f_code_size++;
77}
78
79
80/* Define a label LAB to be the current program counter. */
81
82void
83def_label (lab)
84 long lab;
85{
86 bc_label_group *temp;
87 int group, offset, func;
88
89 /* Get things ready. */
90 group = lab >> BC_LABEL_LOG;
91 offset = lab % BC_LABEL_GROUP;
92 func = load_adr.pc_func;
93
94 /* Make sure there is at least one label group. */
95 if (functions[func].f_label == NULL)
96 {
97 functions[func].f_label =
98 (bc_label_group *) bc_malloc (sizeof(bc_label_group));
99 functions[func].f_label->l_next = NULL;
100 }
101
102 /* Add the label group. */
103 temp = functions[func].f_label;
104 while (group > 0)
105 {
106 if (temp->l_next == NULL)
107 {
108 temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
109 temp->l_next->l_next = NULL;
110 }
111 temp = temp->l_next;
112 group --;
113 }
114
115 /* Define it! */
116 temp->l_adrs [offset] = load_adr.pc_addr;
117}
118
119/* Several instructions have integers in the code. They
120 are all known to be legal longs. So, no error code
121 is added. STR is the pointer to the load string and
122 must be moved to the last non-digit character. */
123
124long
125long_val (str)
126 char **str;
127{ int val = 0;
128 char neg = FALSE;
129
130 if (**str == '-')
131 {
132 neg = TRUE;
133 (*str)++;
134 }
135 while (isdigit(**str))
136 val = val*10 + *(*str)++ - '0';
137
138 if (neg)
139 return -val;
140 else
141 return val;
142}
143
144
145/* load_code loads the CODE into the machine. */
146
147void
148load_code (code)
149 char *code;
150{
151 char *str;
152 long ap_name; /* auto or parameter name. */
153 long label_no;
154 long vaf_name; /* variable, array or function number. */
155 long func;
156 program_counter save_adr;
157
158 /* Initialize. */
159 str = code;
160
161 /* Scan the code. */
162 while (*str != 0)
163 {
164 /* If there was an error, don't continue. */
165 if (had_error) return;
166
167 if (load_str)
168 {
169 if (*str == '"') load_str = FALSE;
170 addbyte (*str++);
171 }
172 else
173 if (load_const)
174 {
175 if (*str == '\n')
176 str++;
177 else
178 {
179 if (*str == ':')
180 {
181 load_const = FALSE;
182 addbyte (*str++);
183 }
184 else
185 if (*str == '.')
186 addbyte (*str++);
187 else
188 if (*str >= 'A')
189 addbyte (*str++ + 10 - 'A');
190 else
191 addbyte (*str++ - '0');
192 }
193 }
194 else
195 {
196 switch (*str)
197 {
198
199 case '"': /* Starts a string. */
200 load_str = TRUE;
201 break;
202
203 case 'N': /* A label */
204 str++;
205 label_no = long_val (&str);
206 def_label (label_no);
207 break;
208
209 case 'B': /* Branch to label. */
210 case 'J': /* Jump to label. */
211 case 'Z': /* Branch Zero to label. */
212 addbyte(*str++);
213 label_no = long_val (&str);
214 if (label_no > 65535L)
215 { /* Better message? */
216 fprintf (stderr,"Program too big.\n");
217 exit(1);
218 }
219 addbyte ( (char) label_no & 0xFF);
220 addbyte ( (char) label_no >> 8);
221 break;
222
223 case 'F': /* A function, get the name and initialize it. */
224 str++;
225 func = long_val (&str);
226 clear_func (func);
227#if DEBUG > 2
228 printf ("Loading function number %d\n", func);
229#endif
230 /* get the parameters */
231 while (*str++ != '.')
232 {
233 if (*str == '.')
234 {
235 str++;
236 break;
237 }
238 ap_name = long_val (&str);
239#if DEBUG > 2
240 printf ("parameter number %d\n", ap_name);
241#endif
242 functions[(int)func].f_params =
243 nextarg (functions[(int)func].f_params, ap_name);
244 }
245
246 /* get the auto vars */
247 while (*str != '[')
248 {
249 if (*str == ',') str++;
250 ap_name = long_val (&str);
251#if DEBUG > 2
252 printf ("auto number %d\n", ap_name);
253#endif
254 functions[(int)func].f_autos =
255 nextarg (functions[(int)func].f_autos, ap_name);
256 }
257 save_adr = load_adr;
258 load_adr.pc_func = func;
259 load_adr.pc_addr = 0;
260 break;
261
262 case ']': /* A function end */
263 functions[load_adr.pc_func].f_defined = TRUE;
264 load_adr = save_adr;
265 break;
266
267 case 'C': /* Call a function. */
268 addbyte (*str++);
269 func = long_val (&str);
270 if (func < 128)
271 addbyte ( (char) func);
272 else
273 {
274 addbyte ((func >> 8) & 0xff | 0x80);
275 addbyte (func & 0xff);
276 }
277 if (*str == ',') str++;
278 while (*str != ':')
279 addbyte (*str++);
280 addbyte (':');
281 break;
282
283 case 'c': /* Call a special function. */
284 addbyte (*str++);
285 addbyte (*str);
286 break;
287
288 case 'K': /* A constant.... may have an "F" in it. */
289 addbyte (*str);
290 load_const = TRUE;
291 break;
292
293 case 'd': /* Decrement. */
294 case 'i': /* Increment. */
295 case 'l': /* Load. */
296 case 's': /* Store. */
297 case 'A': /* Array Increment */
298 case 'M': /* Array Decrement */
299 case 'L': /* Array Load */
300 case 'S': /* Array Store */
301 addbyte (*str++);
302 vaf_name = long_val (&str);
303 if (vaf_name < 128)
304 addbyte (vaf_name);
305 else
306 {
307 addbyte ((vaf_name >> 8) & 0xff | 0x80);
308 addbyte (vaf_name & 0xff);
309 }
310 break;
311
312 case '@': /* A command! */
313 switch (*(++str))
314 {
315 case 'i':
316 init_load ();
317 break;
318 case 'r':
319 execute ();
320 break;
321 }
322 break;
323
324 case '\n': /* Ignore the newlines */
325 break;
326
327 default: /* Anything else */
328 addbyte (*str);
329 }
330 str++;
331 }
332 }
333}
Note: See TracBrowser for help on using the repository browser.