1 /* load.c: This code "loads" code into the code segments. */ 2 3 /* This file is part of GNU bc. 4 Copyright (C) 1991, 1992, 1993, 1994, 1997 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 35 program_counter load_adr; 36 char load_str; 37 char load_const; 38 39 /* Initialize the load sequence. */ 40 void 41 init_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. */ 51 void 52 addbyte (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 82 void 83 def_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 124 long 125 long_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 147 void 148 load_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 if (*str == '*') 239 { 240 str++; 241 ap_name = long_val (&str); 242 #if DEBUG > 2 243 printf ("var parameter number %d\n", ap_name); 244 #endif 245 functions[(int)func].f_params = 246 nextarg (functions[(int)func].f_params, ap_name, 247 TRUE); 248 } 249 else 250 { 251 ap_name = long_val (&str); 252 #if DEBUG > 2 253 printf ("parameter number %d\n", ap_name); 254 #endif 255 functions[(int)func].f_params = 256 nextarg (functions[(int)func].f_params, ap_name, 257 FALSE); 258 } 259 } 260 261 /* get the auto vars */ 262 while (*str != '[') 263 { 264 if (*str == ',') str++; 265 ap_name = long_val (&str); 266 #if DEBUG > 2 267 printf ("auto number %d\n", ap_name); 268 #endif 269 functions[(int)func].f_autos = 270 nextarg (functions[(int)func].f_autos, ap_name, FALSE); 271 } 272 save_adr = load_adr; 273 load_adr.pc_func = func; 274 load_adr.pc_addr = 0; 275 break; 276 277 case ']': /* A function end */ 278 functions[load_adr.pc_func].f_defined = TRUE; 279 load_adr = save_adr; 280 break; 281 282 case 'C': /* Call a function. */ 283 addbyte (*str++); 284 func = long_val (&str); 285 if (func < 128) 286 addbyte ( (char) func); 287 else 288 { 289 addbyte ((func >> 8) & 0xff | 0x80); 290 addbyte (func & 0xff); 291 } 292 if (*str == ',') str++; 293 while (*str != ':') 294 addbyte (*str++); 295 addbyte (':'); 296 break; 297 298 case 'c': /* Call a special function. */ 299 addbyte (*str++); 300 addbyte (*str); 301 break; 302 303 case 'K': /* A constant.... may have an "F" in it. */ 304 addbyte (*str); 305 load_const = TRUE; 306 break; 307 308 case 'd': /* Decrement. */ 309 case 'i': /* Increment. */ 310 case 'l': /* Load. */ 311 case 's': /* Store. */ 312 case 'A': /* Array Increment */ 313 case 'M': /* Array Decrement */ 314 case 'L': /* Array Load */ 315 case 'S': /* Array Store */ 316 addbyte (*str++); 317 vaf_name = long_val (&str); 318 if (vaf_name < 128) 319 addbyte (vaf_name); 320 else 321 { 322 addbyte ((vaf_name >> 8) & 0xff | 0x80); 323 addbyte (vaf_name & 0xff); 324 } 325 break; 326 327 case '@': /* A command! */ 328 switch (*(++str)) 329 { 330 case 'i': 331 init_load (); 332 break; 333 case 'r': 334 execute (); 335 break; 336 } 337 break; 338 339 case '\n': /* Ignore the newlines */ 340 break; 341 342 default: /* Anything else */ 343 addbyte (*str); 344 } 345 str++; 346 } 347 } 348 } |