386BSD 0.1 development
[unix-history] / usr / othersrc / public / bc-1.01 / load.c
CommitLineData
f87489ac
WJ
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 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 /* Calculate the segment and offset. */
58 seg = load_adr.pc_addr >> BC_SEG_LOG;
59 offset = load_adr.pc_addr++ % BC_SEG_SIZE;
60 func = load_adr.pc_func;
61
62 if (functions[func].f_body[seg] == NULL)
63 functions[func].f_body[seg] = (char *) bc_malloc (BC_SEG_SIZE);
64
65 /* Store the byte. */
66 functions[func].f_body[seg][offset] = byte;
67 functions[func].f_code_size++;
68}
69
70
71/* Define a label LAB to be the current program counter. */
72
73void
74def_label (lab)
75 long lab;
76{
77 bc_label_group *temp;
78 int group, offset, func;
79
80 /* Get things ready. */
81 group = lab >> BC_LABEL_LOG;
82 offset = lab % BC_LABEL_GROUP;
83 func = load_adr.pc_func;
84
85 /* Make sure there is at least one label group. */
86 if (functions[func].f_label == NULL)
87 {
88 functions[func].f_label =
89 (bc_label_group *) bc_malloc (sizeof(bc_label_group));
90 functions[func].f_label->l_next = NULL;
91 }
92
93 /* Add the label group. */
94 temp = functions[func].f_label;
95 while (group > 0)
96 {
97 if (temp->l_next == NULL)
98 {
99 temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
100 temp->l_next->l_next = NULL;
101 }
102 temp = temp->l_next;
103 group --;
104 }
105
106 /* Define it! */
107 temp->l_adrs [offset] = load_adr.pc_addr;
108}
109
110/* Several instructions have integers in the code. They
111 are all known to be legal longs. So, no error code
112 is added. STR is the pointer to the load string and
113 must be moved to the last non-digit character. */
114
115long
116long_val (str)
117 char **str;
118{ int val = 0;
119 char neg = FALSE;
120
121 if (**str == '-')
122 {
123 neg = TRUE;
124 (*str)++;
125 }
126 while (isdigit(**str))
127 val = val*10 + *(*str)++ - '0';
128
129 if (neg)
130 return -val;
131 else
132 return val;
133}
134
135
136/* load_code loads the CODE into the machine. */
137
138void
139load_code (code)
140 char *code;
141{
142 char *str;
143 long ap_name; /* auto or parameter name. */
144 long label_no;
145 long vaf_name; /* variable, array or function number. */
146 long func;
147 program_counter save_adr;
148
149 /* Initialize. */
150 str = code;
151
152 /* Scan the code. */
153 while (*str != 0)
154 {
155 if (load_str)
156 {
157 if (*str == '"') load_str = FALSE;
158 addbyte (*str++);
159 }
160 else
161 if (load_const)
162 {
163 if (*str == '\n')
164 str++;
165 else
166 {
167 if (*str == ':')
168 {
169 load_const = FALSE;
170 addbyte (*str++);
171 }
172 else
173 if (*str == '.')
174 addbyte (*str++);
175 else
176 if (*str >= 'A')
177 addbyte (*str++ + 10 - 'A');
178 else
179 addbyte (*str++ - '0');
180 }
181 }
182 else
183 {
184 switch (*str)
185 {
186
187 case '"': /* Starts a string. */
188 load_str = TRUE;
189 break;
190
191 case 'N': /* A label */
192 str++;
193 label_no = long_val (&str);
194 def_label (label_no);
195 break;
196
197 case 'B': /* Branch to label. */
198 case 'J': /* Jump to label. */
199 case 'Z': /* Branch Zero to label. */
200 addbyte(*str++);
201 label_no = long_val (&str);
202 if (label_no > 65535L)
203 { /* Better message? */
204 fprintf (stderr,"Program too big.\n");
205 exit(1);
206 }
207 addbyte ( (char) label_no & 0xFF);
208 addbyte ( (char) label_no >> 8);
209 break;
210
211 case 'F': /* A function, get the name and initialize it. */
212 str++;
213 func = long_val (&str);
214 clear_func (func);
215#if DEBUG > 2
216 printf ("Loading function number %d\n", func);
217#endif
218 /* get the parameters */
219 while (*str++ != '.')
220 {
221 if (*str == '.')
222 {
223 str++;
224 break;
225 }
226 ap_name = long_val (&str);
227#if DEBUG > 2
228 printf ("parameter number %d\n", ap_name);
229#endif
230 functions[(int)func].f_params =
231 nextarg (functions[(int)func].f_params, ap_name);
232 }
233
234 /* get the auto vars */
235 while (*str != '[')
236 {
237 if (*str == ',') str++;
238 ap_name = long_val (&str);
239#if DEBUG > 2
240 printf ("auto number %d\n", ap_name);
241#endif
242 functions[(int)func].f_autos =
243 nextarg (functions[(int)func].f_autos, ap_name);
244 }
245 save_adr = load_adr;
246 load_adr.pc_func = func;
247 load_adr.pc_addr = 0;
248 break;
249
250 case ']': /* A function end */
251 if (!had_error)
252 functions[load_adr.pc_func].f_defined = TRUE;
253 load_adr = save_adr;
254 break;
255
256 case 'C': /* Call a function. */
257 addbyte (*str++);
258 func = long_val (&str);
259 if (func < 128)
260 addbyte ( (char) func);
261 else
262 {
263 addbyte ((func >> 8) & 0xff | 0x80);
264 addbyte (func & 0xff);
265 }
266 if (*str == ',') str++;
267 while (*str != ':')
268 addbyte (*str++);
269 addbyte (':');
270 break;
271
272 case 'c': /* Call a special function. */
273 addbyte (*str++);
274 addbyte (*str);
275 break;
276
277 case 'K': /* A constant.... may have an "F" in it. */
278 addbyte (*str);
279 load_const = TRUE;
280 break;
281
282 case 'd': /* Decrement. */
283 case 'i': /* Increment. */
284 case 'l': /* Load. */
285 case 's': /* Store. */
286 case 'A': /* Array Increment */
287 case 'M': /* Array Decrement */
288 case 'L': /* Array Load */
289 case 'S': /* Array Store */
290 addbyte (*str++);
291 vaf_name = long_val (&str);
292 if (vaf_name < 128)
293 addbyte (vaf_name);
294 else
295 {
296 addbyte ((vaf_name >> 8) & 0xff | 0x80);
297 addbyte (vaf_name & 0xff);
298 }
299 break;
300
301 case '@': /* A command! */
302 switch (*(++str))
303 {
304 case 'i':
305 init_load ();
306 break;
307 case 'r':
308 execute ();
309 break;
310 }
311 break;
312
313 case '\n': /* Ignore the newlines */
314 break;
315
316 default: /* Anything else */
317 addbyte (*str);
318 }
319 str++;
320 }
321 }
322}