"Fossies" - the Fresh Open Source Software Archive

Member "bc-1.06.95/bc/load.c" (5 Sep 2006, 7732 Bytes) of package /linux/misc/old/bc-1.06.95.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "load.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.06.95_vs_1.07.

    1 /*  This file is part of GNU bc.
    2 
    3     Copyright (C) 1991-1994, 1997, 2006 Free Software Foundation, Inc.
    4 
    5     This program is free software; you can redistribute it and/or modify
    6     it under the terms of the GNU General Public License as published by
    7     the Free Software Foundation; either version 2 of the License , or
    8     (at your option) any later version.
    9 
   10     This program is distributed in the hope that it will be useful,
   11     but WITHOUT ANY WARRANTY; without even the implied warranty of
   12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13     GNU General Public License for more details.
   14 
   15     You should have received a copy of the GNU General Public License
   16     along with this program; see the file COPYING.  If not, write to:
   17       The Free Software Foundation, Inc.
   18       Foundation, Inc.  51 Franklin Street, Fifth Floor,
   19       Boston, MA 02110-1301  USA
   20 
   21     You may contact the author by:
   22        e-mail:  philnelson@acm.org
   23       us-mail:  Philip A. Nelson
   24                 Computer Science Department, 9062
   25                 Western Washington University
   26                 Bellingham, WA 98226-9062
   27        
   28 *************************************************************************/
   29 
   30 /* load.c:  This code "loads" code into the code segments. */
   31 
   32 #include "bcdefs.h"
   33 #include "proto.h"
   34 
   35 /* Load variables. */
   36 
   37 program_counter load_adr;
   38 char load_str;
   39 char load_const;
   40 
   41 /* Initialize the load sequence. */
   42 void
   43 init_load ()
   44 {
   45   clear_func(0);
   46   load_adr.pc_func = 0;
   47   load_adr.pc_addr = 0;
   48   load_str = FALSE;
   49   load_const = FALSE;
   50 }
   51 
   52 /* addbyte adds one BYTE to the current code segment. */
   53 void
   54 addbyte (thebyte)
   55      int thebyte;
   56 {
   57   int prog_addr;
   58   bc_function *f;
   59   char *new_body;
   60 
   61   /* If there was an error, don't continue. */
   62   if (had_error) return;
   63 
   64   /* Calculate the segment and offset. */
   65   prog_addr = load_adr.pc_addr++;
   66   f = &functions[load_adr.pc_func];
   67 
   68   if (prog_addr >= f->f_body_size)
   69     {
   70       f->f_body_size *= 2;
   71       new_body = (char *) bc_malloc (f->f_body_size);
   72       memcpy(new_body, f->f_body, f->f_body_size/2);
   73       free (f->f_body);
   74       f->f_body = new_body;
   75     }
   76 
   77   /* Store the thebyte. */
   78   f->f_body[prog_addr] = (char) (thebyte & 0xff);
   79   f->f_code_size++;
   80 }
   81 
   82 
   83 /* Define a label LAB to be the current program counter. */
   84 
   85 void
   86 def_label (lab)
   87      long lab;
   88 {
   89   bc_label_group *temp;
   90   int group, offset, func;
   91     
   92   /* Get things ready. */
   93   group = lab >> BC_LABEL_LOG;
   94   offset = lab % BC_LABEL_GROUP;
   95   func = load_adr.pc_func;
   96   
   97   /* Make sure there is at least one label group. */
   98   if (functions[func].f_label == NULL)
   99     {
  100       functions[func].f_label = 
  101     (bc_label_group *) bc_malloc (sizeof(bc_label_group));
  102       functions[func].f_label->l_next = NULL;
  103     }
  104 
  105   /* Add the label group. */
  106   temp = functions[func].f_label;
  107   while (group > 0)
  108     {
  109       if (temp->l_next == NULL)
  110     {
  111       temp->l_next = (bc_label_group *) bc_malloc (sizeof(bc_label_group));
  112       temp->l_next->l_next = NULL;
  113     }
  114       temp = temp->l_next;
  115       group --;
  116     }
  117 
  118   /* Define it! */
  119   temp->l_adrs [offset] = load_adr.pc_addr;
  120 }
  121 
  122 /* Several instructions have integers in the code.  They
  123    are all known to be legal longs.  So, no error code
  124    is added.  STR is the pointer to the load string and
  125    must be moved to the last non-digit character. */
  126 
  127 long
  128 long_val (str)
  129      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
  151 load_code (code)
  152      const char *code;
  153 {
  154   const char *str;
  155   long  ap_name;    /* auto or parameter name. */
  156   long  label_no;
  157   long  vaf_name;   /* variable, array or function number. */
  158   long  func;
  159   static program_counter save_adr;
  160 
  161   /* Initialize. */
  162   str = code;
  163    
  164   /* Scan the code. */
  165   while (*str != 0)
  166     {
  167       /* If there was an error, don't continue. */
  168       if (had_error) return;
  169 
  170       if (load_str)
  171     {
  172       if (*str == '"') load_str = FALSE;
  173       addbyte (*str++);
  174     }
  175       else
  176     if (load_const)
  177       {
  178         if (*str == '\n') 
  179           str++;
  180         else
  181           {
  182         if (*str == ':')
  183           {
  184             load_const = FALSE;
  185             addbyte (*str++);
  186           }
  187         else
  188           if (*str == '.')
  189             addbyte (*str++);
  190           else
  191             if (*str >= 'A')
  192               addbyte (*str++ + 10 - 'A');
  193             else
  194               addbyte (*str++ - '0');
  195           }
  196       }
  197     else
  198       {
  199         switch (*str)
  200           {
  201 
  202           case '"': /* Starts a string. */
  203         load_str = TRUE;
  204         break;
  205 
  206           case 'N': /* A label */
  207         str++;
  208         label_no = long_val (&str);
  209         def_label (label_no);
  210         break;
  211 
  212           case 'B':  /* Branch to label. */
  213           case 'J':  /* Jump to label. */
  214           case 'Z':  /* Branch Zero to label. */
  215         addbyte(*str++);
  216         label_no = long_val (&str);
  217         if (label_no > 65535L)
  218           {  /* Better message? */
  219             fprintf (stderr,"Program too big.\n");
  220             exit(1);
  221           }
  222         addbyte ( (char) (label_no & 0xFF));
  223         addbyte ( (char) (label_no >> 8));
  224         break;
  225 
  226           case 'F':  /* A function, get the name and initialize it. */
  227         str++;
  228         func = long_val (&str);
  229         clear_func (func);
  230 #if DEBUG > 2
  231         printf ("Loading function number %d\n", func);
  232 #endif
  233         /* get the parameters */
  234         while (*str++ != '.')
  235           {
  236             if (*str == '.')
  237               {
  238             str++;
  239             break;
  240               }
  241             if (*str == '*')
  242               {
  243             str++;
  244             ap_name = long_val (&str);
  245 #if DEBUG > 2
  246             printf ("var parameter number %d\n", ap_name);
  247 #endif
  248             functions[(int)func].f_params = 
  249               nextarg (functions[(int)func].f_params, ap_name,
  250                    TRUE);
  251               }
  252             else
  253               {
  254             ap_name = long_val (&str);
  255 #if DEBUG > 2
  256             printf ("parameter number %d\n", ap_name);
  257 #endif
  258             functions[(int)func].f_params = 
  259               nextarg (functions[(int)func].f_params, ap_name,
  260                    FALSE);
  261               }
  262           }
  263 
  264         /* get the auto vars */
  265         while (*str != '[')
  266           {
  267             if (*str == ',') str++;
  268             ap_name = long_val (&str);
  269 #if DEBUG > 2
  270             printf ("auto number %d\n", ap_name);
  271 #endif
  272             functions[(int)func].f_autos = 
  273               nextarg (functions[(int)func].f_autos, ap_name, FALSE);
  274           }
  275         save_adr = load_adr;
  276         load_adr.pc_func = func;
  277         load_adr.pc_addr = 0;
  278         break;
  279         
  280           case ']':  /* A function end */
  281         functions[load_adr.pc_func].f_defined = TRUE;
  282         load_adr = save_adr;
  283         break;
  284 
  285           case 'C':  /* Call a function. */
  286         addbyte (*str++);
  287         func = long_val (&str);
  288         if (func < 128)
  289           addbyte ( (char) func);
  290         else
  291           {
  292             addbyte (((func >> 8) & 0xff) | 0x80);
  293             addbyte (func & 0xff);
  294           }
  295         if (*str == ',') str++;
  296         while (*str != ':')
  297           addbyte (*str++);
  298         addbyte (':');
  299         break;
  300         
  301           case 'c':  /* Call a special function. */
  302         addbyte (*str++);
  303         addbyte (*str);
  304         break;
  305 
  306           case 'K':  /* A constant.... may have an "F" in it. */
  307         addbyte (*str);
  308         load_const = TRUE;
  309         break;
  310 
  311           case 'd':  /* Decrement. */
  312           case 'i':  /* Increment. */
  313           case 'l':  /* Load. */
  314           case 's':  /* Store. */
  315           case 'A':  /* Array Increment */
  316           case 'M':  /* Array Decrement */
  317           case 'L':  /* Array Load */
  318           case 'S':  /* Array Store */
  319         addbyte (*str++);
  320         vaf_name = long_val (&str);
  321         if (vaf_name < 128)
  322           addbyte (vaf_name);
  323         else
  324           {
  325             addbyte (((vaf_name >> 8) & 0xff) | 0x80);
  326             addbyte (vaf_name & 0xff);
  327           }
  328         break;
  329 
  330           case '@':  /* A command! */
  331         switch (*(++str))
  332           {
  333           case 'i':
  334             init_load ();
  335             break;
  336           case 'r':
  337             execute ();
  338             break;
  339           } 
  340         break;
  341 
  342           case '\n':  /* Ignore the newlines */
  343         break;
  344         
  345           default:   /* Anything else */
  346         addbyte (*str);    
  347           }
  348         str++;
  349       }
  350     }
  351 }