* reordered a little bit
[mascara-docs.git] / i86 / elks / elkscmd / bc / load.c
blobbe4ab3a52160a2fcce72260a640b5a14fdeb7a0a
1 /* load.c: This code "loads" code into the code segments. */
3 /* This file is part of bc written for MINIX.
4 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
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.
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.
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.
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
27 *************************************************************************/
29 #include "bcdefs.h"
30 #include "global.h"
31 #include "proto.h"
33 /* Load variables. */
35 program_counter load_adr;
36 char load_str;
37 char load_const;
39 /* Initialize the load sequence. */
40 void
41 init_load ()
43 clear_func(0);
44 load_adr.pc_func = 0;
45 load_adr.pc_addr = 0;
46 load_str = FALSE;
47 load_const = FALSE;
50 /* addbyte adds one BYTE to the current code segment. */
51 void
52 addbyte (byte)
53 char byte;
55 int seg, offset, func;
57 /* If there was an error, don't continue. */
58 if (had_error) return;
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;
65 if (seg >= BC_MAX_SEGS)
67 yyerror ("Function too big.");
68 return;
71 if (functions[func].f_body[seg] == NULL)
72 functions[func].f_body[seg] = (char *) bc_malloc (BC_SEG_SIZE);
74 /* Store the byte. */
75 functions[func].f_body[seg][offset] = byte;
76 functions[func].f_code_size++;
80 /* Define a label LAB to be the current program counter. */
82 void
83 def_label (lab)
84 long lab;
86 bc_label_group *temp;
87 int group, offset, func;
89 /* Get things ready. */
90 group = lab >> BC_LABEL_LOG;
91 offset = lab % BC_LABEL_GROUP;
92 func = load_adr.pc_func;
94 /* Make sure there is at least one label group. */
95 if (functions[func].f_label == NULL)
97 functions[func].f_label =
98 (bc_label_group *) bc_malloc (sizeof(bc_label_group));
99 functions[func].f_label->l_next = NULL;
102 /* Add the label group. */
103 temp = functions[func].f_label;
104 while (group > 0)
106 if (temp->l_next == NULL)
108 temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
109 temp->l_next->l_next = NULL;
111 temp = temp->l_next;
112 group --;
115 /* Define it! */
116 temp->l_adrs [offset] = load_adr.pc_addr;
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. */
124 long
125 long_val (str)
126 char **str;
127 { int val = 0;
128 char neg = FALSE;
130 if (**str == '-')
132 neg = TRUE;
133 (*str)++;
135 while (isdigit(**str))
136 val = val*10 + *(*str)++ - '0';
138 if (neg)
139 return -val;
140 else
141 return val;
145 /* load_code loads the CODE into the machine. */
147 void
148 load_code (code)
149 char *code;
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;
158 /* Initialize. */
159 str = code;
161 /* Scan the code. */
162 while (*str != 0)
164 /* If there was an error, don't continue. */
165 if (had_error) return;
167 if (load_str)
169 if (*str == '"') load_str = FALSE;
170 addbyte (*str++);
172 else
173 if (load_const)
175 if (*str == '\n')
176 str++;
177 else
179 if (*str == ':')
181 load_const = FALSE;
182 addbyte (*str++);
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');
194 else
196 switch (*str)
199 case '"': /* Starts a string. */
200 load_str = TRUE;
201 break;
203 case 'N': /* A label */
204 str++;
205 label_no = long_val (&str);
206 def_label (label_no);
207 break;
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);
219 addbyte ( (char) label_no & 0xFF);
220 addbyte ( (char) label_no >> 8);
221 break;
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++ != '.')
233 if (*str == '.')
235 str++;
236 break;
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);
246 /* get the auto vars */
247 while (*str != '[')
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);
257 save_adr = load_adr;
258 load_adr.pc_func = func;
259 load_adr.pc_addr = 0;
260 break;
262 case ']': /* A function end */
263 functions[load_adr.pc_func].f_defined = TRUE;
264 load_adr = save_adr;
265 break;
267 case 'C': /* Call a function. */
268 addbyte (*str++);
269 func = long_val (&str);
270 if (func < 128)
271 addbyte ( (char) func);
272 else
274 addbyte ((func >> 8) & 0xff | 0x80);
275 addbyte (func & 0xff);
277 if (*str == ',') str++;
278 while (*str != ':')
279 addbyte (*str++);
280 addbyte (':');
281 break;
283 case 'c': /* Call a special function. */
284 addbyte (*str++);
285 addbyte (*str);
286 break;
288 case 'K': /* A constant.... may have an "F" in it. */
289 addbyte (*str);
290 load_const = TRUE;
291 break;
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
307 addbyte ((vaf_name >> 8) & 0xff | 0x80);
308 addbyte (vaf_name & 0xff);
310 break;
312 case '@': /* A command! */
313 switch (*(++str))
315 case 'i':
316 init_load ();
317 break;
318 case 'r':
319 execute ();
320 break;
322 break;
324 case '\n': /* Ignore the newlines */
325 break;
327 default: /* Anything else */
328 addbyte (*str);
330 str++;