5762783 [rkeene@sledge /home/rkeene/devel/old/bc-dos/bc]$ cat -n load.c
  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 }
5762784 [rkeene@sledge /home/rkeene/devel/old/bc-dos/bc]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 1997-04-10 21:36:14