1 /* $NetBSD: load.c,v 1.1 2017/04/10 02:28:23 phil Exp $ */
2
3 /*
4 * Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
5 * Copyright (C) 2016-2017 Philip A. Nelson.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The names Philip A. Nelson and Free Software Foundation may not be
18 * used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY PHILIP A. NELSON ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL PHILIP A. NELSON OR THE FREE SOFTWARE FOUNDATION BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* load.c: This code "loads" code into the code segments. */
35
36 #include "bcdefs.h"
37 #include "proto.h"
38
39 /* Load variables. */
40
41 program_counter load_adr;
42 char load_str;
43 char load_const;
44
45 /* Initialize the load sequence. */
46 void
init_load(void)47 init_load (void)
48 {
49 clear_func(0);
50 load_adr.pc_func = 0;
51 load_adr.pc_addr = 0;
52 load_str = FALSE;
53 load_const = FALSE;
54 }
55
56 /* addbyte adds one BYTE to the current code segment. */
57 void
addbyte(unsigned char thebyte)58 addbyte (unsigned char thebyte)
59 {
60 unsigned long prog_addr;
61 bc_function *f;
62 char *new_body;
63
64 /* If there was an error, don't continue. */
65 if (had_error) return;
66
67 /* Calculate the segment and offset. */
68 prog_addr = load_adr.pc_addr++;
69 f = &functions[load_adr.pc_func];
70
71 if (prog_addr >= f->f_body_size)
72 {
73 f->f_body_size *= 2;
74 new_body = bc_malloc (f->f_body_size);
75 memcpy(new_body, f->f_body, f->f_body_size/2);
76 free (f->f_body);
77 f->f_body = new_body;
78 }
79
80 /* Store the thebyte. */
81 f->f_body[prog_addr] = (char) (thebyte & 0xff);
82 f->f_code_size++;
83 }
84
85
86 /* Define a label LAB to be the current program counter. */
87
88 void
def_label(unsigned long lab)89 def_label (unsigned long lab)
90 {
91 bc_label_group *temp;
92 unsigned long group, offset, func;
93
94 /* Get things ready. */
95 group = lab >> BC_LABEL_LOG;
96 offset = lab % BC_LABEL_GROUP;
97 func = load_adr.pc_func;
98
99 /* Make sure there is at least one label group. */
100 if (functions[func].f_label == NULL)
101 {
102 functions[func].f_label = bc_malloc (sizeof(bc_label_group));
103 functions[func].f_label->l_next = NULL;
104 }
105
106 /* Add the label group. */
107 temp = functions[func].f_label;
108 while (group > 0)
109 {
110 if (temp->l_next == NULL)
111 {
112 temp->l_next = bc_malloc (sizeof(bc_label_group));
113 temp->l_next->l_next = NULL;
114 }
115 temp = temp->l_next;
116 group --;
117 }
118
119 /* Define it! */
120 temp->l_adrs [offset] = load_adr.pc_addr;
121 }
122
123 /* Several instructions have integers in the code. They
124 are all known to be legal longs. So, no error code
125 is added. STR is the pointer to the load string and
126 must be moved to the last non-digit character. */
127
128 long
long_val(const char ** str)129 long_val (const char **str)
130 { int val = 0;
131 char neg = FALSE;
132
133 if (**str == '-')
134 {
135 neg = TRUE;
136 (*str)++;
137 }
138 while (isdigit((int)(**str)))
139 val = val*10 + *(*str)++ - '0';
140
141 if (neg)
142 return -val;
143 else
144 return val;
145 }
146
147
148 /* load_code loads the CODE into the machine. */
149
150 void
load_code(const char * code)151 load_code (const char *code)
152 {
153 const char *str;
154 unsigned long ap_name; /* auto or parameter name. */
155 unsigned long label_no;
156 unsigned long vaf_name; /* variable, array or function number. */
157 unsigned long func;
158 static program_counter save_adr;
159
160 /* Initialize. */
161 str = code;
162
163 /* Scan the code. */
164 while (*str != 0)
165 {
166 /* If there was an error, don't continue. */
167 if (had_error) return;
168
169 if (load_str)
170 {
171 if (*str == '"') load_str = FALSE;
172 addbyte (*str++);
173 }
174 else
175 if (load_const)
176 {
177 if (*str == '\n')
178 str++;
179 else
180 {
181 if (*str == ':')
182 {
183 load_const = FALSE;
184 addbyte (*str++);
185 }
186 else
187 if (*str == '.')
188 addbyte (*str++);
189 else
190 {
191 if (*str > 'F' && (warn_not_std || std_only))
192 {
193 if (std_only)
194 yyerror ("Error in numeric constant");
195 else
196 ct_warn ("Non-standard base in numeric constant");
197 }
198 if (*str >= 'A')
199 addbyte (*str++ + 10 - 'A');
200 else
201 addbyte (*str++ - '0');
202 }
203 }
204 }
205 else
206 {
207 switch (*str)
208 {
209
210 case '"': /* Starts a string. */
211 load_str = TRUE;
212 break;
213
214 case 'N': /* A label */
215 str++;
216 label_no = long_val (&str);
217 def_label (label_no);
218 break;
219
220 case 'B': /* Branch to label. */
221 case 'J': /* Jump to label. */
222 case 'Z': /* Branch Zero to label. */
223 addbyte(*str++);
224 label_no = long_val (&str);
225 if (label_no > 65535L)
226 { /* Better message? */
227 fprintf (stderr,"Program too big.\n");
228 bc_exit(1);
229 }
230 addbyte ( (char) (label_no & 0xFF));
231 addbyte ( (char) (label_no >> 8));
232 break;
233
234 case 'F': /* A function, get the name and initialize it. */
235 str++;
236 func = long_val (&str);
237 clear_func (func);
238 #if DEBUG > 2
239 printf ("Loading function number %d\n", func);
240 #endif
241 /* get the parameters */
242 while (*str++ != '.')
243 {
244 if (*str == '.')
245 {
246 str++;
247 break;
248 }
249 if (*str == '*')
250 {
251 str++;
252 ap_name = long_val (&str);
253 #if DEBUG > 2
254 printf ("var parameter number %d\n", ap_name);
255 #endif
256 functions[(int)func].f_params =
257 nextarg (functions[(int)func].f_params, ap_name,
258 TRUE);
259 }
260 else
261 {
262 ap_name = long_val (&str);
263 #if DEBUG > 2
264 printf ("parameter number %d\n", ap_name);
265 #endif
266 functions[(int)func].f_params =
267 nextarg (functions[(int)func].f_params, ap_name,
268 FALSE);
269 }
270 }
271
272 /* get the auto vars */
273 while (*str != '[')
274 {
275 if (*str == ',') str++;
276 ap_name = long_val (&str);
277 #if DEBUG > 2
278 printf ("auto number %d\n", ap_name);
279 #endif
280 functions[(int)func].f_autos =
281 nextarg (functions[(int)func].f_autos, ap_name, FALSE);
282 }
283 save_adr = load_adr;
284 load_adr.pc_func = func;
285 load_adr.pc_addr = 0;
286 break;
287
288 case ']': /* A function end */
289 functions[load_adr.pc_func].f_defined = TRUE;
290 load_adr = save_adr;
291 break;
292
293 case 'C': /* Call a function. */
294 addbyte (*str++);
295 func = long_val (&str);
296 if (func < 128)
297 addbyte ( (char) func);
298 else
299 {
300 addbyte (((func >> 8) & 0xff) | 0x80);
301 addbyte (func & 0xff);
302 }
303 if (*str == ',') str++;
304 while (*str != ':')
305 addbyte (*str++);
306 addbyte (':');
307 break;
308
309 case 'c': /* Call a special function. */
310 addbyte (*str++);
311 addbyte (*str);
312 break;
313
314 case 'K': /* A constant.... may have an "F" in it. */
315 addbyte (*str);
316 load_const = TRUE;
317 break;
318
319 case 'd': /* Decrement. */
320 case 'i': /* Increment. */
321 case 'l': /* Load. */
322 case 's': /* Store. */
323 case 'A': /* Array Increment */
324 case 'M': /* Array Decrement */
325 case 'L': /* Array Load */
326 case 'S': /* Array Store */
327 addbyte (*str++);
328 vaf_name = long_val (&str);
329 if (vaf_name < 128)
330 addbyte (vaf_name);
331 else
332 {
333 addbyte (((vaf_name >> 8) & 0xff) | 0x80);
334 addbyte (vaf_name & 0xff);
335 }
336 break;
337
338 case '@': /* A command! */
339 switch (*(++str))
340 {
341 case 'i':
342 init_load ();
343 break;
344 case 'r':
345 execute ();
346 break;
347 }
348 break;
349
350 case '\n': /* Ignore the newlines */
351 break;
352
353 default: /* Anything else */
354 addbyte (*str);
355 }
356 str++;
357 }
358 }
359 }
360