"Fossies" - the Fresh Open Source Software Archive

Member "bc-1.06.95/bc/execute.c" (5 Sep 2006, 18066 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 "execute.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.07_vs_1.07.1.

    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 /* execute.c - run a bc program. */
   30 
   31 #include "bcdefs.h"
   32 #include <signal.h>
   33 #include "proto.h"
   34 
   35 
   36 /* The SIGINT interrupt handling routine. */
   37 
   38 int had_sigint;
   39 
   40 void
   41 stop_execution (sig)
   42      int sig;
   43 {
   44   had_sigint = TRUE;
   45 }
   46 
   47 
   48 /* Get the current byte and advance the PC counter. */
   49 
   50 unsigned char
   51 byte (p)
   52      program_counter *p;
   53 {
   54   return (functions[p->pc_func].f_body[p->pc_addr++]);
   55 }
   56 
   57 
   58 /* The routine that actually runs the machine. */
   59 
   60 void
   61 execute ()
   62 {
   63   int label_num, l_gp, l_off;
   64   bc_label_group *gp;
   65   
   66   char inst, ch;
   67   int  new_func;
   68   int  var_name;
   69 
   70   int const_base;
   71 
   72   bc_num temp_num;
   73   arg_list *auto_list;
   74 
   75   /* Initialize this run... */
   76   pc.pc_func = 0;
   77   pc.pc_addr = 0;
   78   runtime_error = FALSE;
   79   bc_init_num (&temp_num);
   80 
   81   /* Set up the interrupt mechanism for an interactive session. */
   82   if (interactive)
   83     {
   84       signal (SIGINT, stop_execution);
   85     }
   86    
   87   had_sigint = FALSE;
   88   while (pc.pc_addr < functions[pc.pc_func].f_code_size
   89      && !runtime_error && !had_sigint)
   90     {
   91       inst = byte(&pc);
   92 
   93 #if DEBUG > 3
   94       { /* Print out address and the stack before each instruction.*/
   95     int depth; estack_rec *temp = ex_stack;
   96     
   97     printf ("func=%d addr=%d inst=%c\n",pc.pc_func, pc.pc_addr, inst);
   98     if (temp == NULL) printf ("empty stack.\n", inst);
   99     else
  100       {
  101         depth = 1;
  102         while (temp != NULL)
  103           {
  104         printf ("  %d = ", depth);
  105         bc_out_num (temp->s_num, 10, out_char, std_only);
  106         depth++;
  107         temp = temp->s_next;
  108           }
  109         out_char ('\n');
  110       }
  111       }
  112 #endif
  113 
  114     switch ( inst )
  115       {
  116 
  117       case 'A' : /* increment array variable (Add one). */
  118     var_name = byte(&pc);
  119     if ((var_name & 0x80) != 0)
  120       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  121     incr_array (var_name);
  122     break;
  123 
  124       case 'B' : /* Branch to a label if TOS != 0. Remove value on TOS. */
  125       case 'Z' : /* Branch to a label if TOS == 0. Remove value on TOS. */
  126     c_code = !bc_is_zero (ex_stack->s_num);
  127     pop ();
  128       case 'J' : /* Jump to a label. */
  129     label_num = byte(&pc);  /* Low order bits first. */
  130     label_num += byte(&pc) << 8;
  131     if (inst == 'J' || (inst == 'B' && c_code)
  132         || (inst == 'Z' && !c_code)) {
  133       gp = functions[pc.pc_func].f_label;
  134       l_gp  = label_num >> BC_LABEL_LOG;
  135       l_off = label_num % BC_LABEL_GROUP;
  136       while (l_gp-- > 0) gp = gp->l_next;
  137       pc.pc_addr = gp->l_adrs[l_off];
  138     }
  139     break;
  140 
  141       case 'C' : /* Call a function. */
  142     /* Get the function number. */
  143     new_func = byte(&pc);
  144     if ((new_func & 0x80) != 0) 
  145       new_func = ((new_func & 0x7f) << 8) + byte(&pc);
  146 
  147     /* Check to make sure it is defined. */
  148     if (!functions[new_func].f_defined)
  149       {
  150         rt_error ("Function %s not defined.", f_names[new_func]);
  151         break;
  152       }
  153 
  154     /* Check and push parameters. */
  155     process_params (&pc, new_func);
  156 
  157     /* Push auto variables. */
  158     for (auto_list = functions[new_func].f_autos;
  159          auto_list != NULL;
  160          auto_list = auto_list->next)
  161       auto_var (auto_list->av_name);
  162 
  163     /* Push pc and ibase. */
  164     fpush (pc.pc_func);
  165     fpush (pc.pc_addr);
  166     fpush (i_base);
  167 
  168     /* Reset pc to start of function. */
  169     pc.pc_func = new_func;
  170     pc.pc_addr = 0;
  171     break;
  172 
  173       case 'D' : /* Duplicate top of stack */
  174     push_copy (ex_stack->s_num);
  175     break;
  176 
  177       case 'K' : /* Push a constant */
  178     /* Get the input base and convert it to a bc number. */
  179     if (pc.pc_func == 0) 
  180       const_base = i_base;
  181     else
  182       const_base = fn_stack->s_val;
  183     if (const_base == 10)
  184       push_b10_const (&pc);
  185     else
  186       push_constant (prog_char, const_base);
  187     break;
  188 
  189       case 'L' : /* load array variable */
  190     var_name = byte(&pc);
  191     if ((var_name & 0x80) != 0)
  192       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  193     load_array (var_name);
  194     break;
  195 
  196       case 'M' : /* decrement array variable (Minus!) */
  197     var_name = byte(&pc);
  198     if ((var_name & 0x80) != 0)
  199       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  200     decr_array (var_name);
  201     break;
  202 
  203       case 'O' : /* Write a string to the output with processing. */
  204     while ((ch = byte(&pc)) != '"')
  205       if (ch != '\\')
  206         out_schar (ch);
  207       else
  208         {
  209           ch = byte(&pc);
  210           if (ch == '"') break;
  211           switch (ch)
  212         {
  213         case 'a':  out_schar (007); break;
  214         case 'b':  out_schar ('\b'); break;
  215         case 'f':  out_schar ('\f'); break;
  216         case 'n':  out_schar ('\n'); break;
  217         case 'q':  out_schar ('"'); break;
  218         case 'r':  out_schar ('\r'); break;
  219         case 't':  out_schar ('\t'); break;
  220         case '\\': out_schar ('\\'); break;
  221         default:  break;
  222         }
  223         }
  224     fflush (stdout);
  225     break;
  226 
  227       case 'R' : /* Return from function */
  228     if (pc.pc_func != 0)
  229       {
  230         /* "Pop" autos and parameters. */
  231         pop_vars(functions[pc.pc_func].f_autos);
  232         pop_vars(functions[pc.pc_func].f_params);
  233         /* reset the pc. */
  234         fpop ();
  235         pc.pc_addr = fpop ();
  236         pc.pc_func = fpop ();
  237       }
  238     else
  239       rt_error ("Return from main program.");
  240     break;
  241 
  242       case 'S' : /* store array variable */
  243     var_name = byte(&pc);
  244     if ((var_name & 0x80) != 0)
  245       var_name = ((var_name & 0x7f ) << 8) + byte(&pc);
  246     store_array (var_name);
  247     break;
  248 
  249       case 'T' : /* Test tos for zero */
  250     c_code = bc_is_zero (ex_stack->s_num);
  251     assign (c_code);
  252     break;
  253 
  254       case 'W' : /* Write the value on the top of the stack. */
  255       case 'P' : /* Write the value on the top of the stack.  No newline. */
  256     bc_out_num (ex_stack->s_num, o_base, out_char, std_only);
  257     if (inst == 'W') out_char ('\n');
  258     store_var (4);  /* Special variable "last". */
  259     fflush (stdout);
  260     pop ();
  261     break;
  262 
  263       case 'c' : /* Call special function. */
  264     new_func = byte(&pc);
  265 
  266       switch (new_func)
  267     {
  268     case 'L':  /* Length function. */
  269       /* For the number 0.xxxx,  0 is not significant. */
  270       if (ex_stack->s_num->n_len == 1 &&
  271           ex_stack->s_num->n_scale != 0 &&
  272           ex_stack->s_num->n_value[0] == 0 )
  273         bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
  274       else
  275         bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_len
  276              + ex_stack->s_num->n_scale);
  277       break;
  278         
  279     case 'S':  /* Scale function. */ 
  280       bc_int2num (&ex_stack->s_num, ex_stack->s_num->n_scale);
  281       break;
  282 
  283     case 'R':  /* Square Root function. */
  284       if (!bc_sqrt (&ex_stack->s_num, scale))
  285         rt_error ("Square root of a negative number");
  286       break;
  287 
  288     case 'I': /* Read function. */
  289       push_constant (input_char, i_base);
  290       break;
  291 
  292     case 'X': /* Random function. */
  293       push_copy (_zero_);
  294       bc_int2num (&ex_stack->s_num, random());
  295       break;
  296     }
  297     break;
  298 
  299       case 'd' : /* Decrement number */
  300     var_name = byte(&pc);
  301     if ((var_name & 0x80) != 0)
  302       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  303     decr_var (var_name);
  304     break;
  305       
  306       case 'h' : /* Halt the machine. */
  307     exit (0);
  308 
  309       case 'i' : /* increment number */
  310     var_name = byte(&pc);
  311     if ((var_name & 0x80) != 0)
  312       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  313     incr_var (var_name);
  314     break;
  315 
  316       case 'l' : /* load variable */
  317     var_name = byte(&pc);
  318     if ((var_name & 0x80) != 0)
  319       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  320     load_var (var_name);
  321     break;
  322 
  323       case 'n' : /* Negate top of stack. */
  324     bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num, 0);
  325     break;
  326 
  327       case 'p' : /* Pop the execution stack. */
  328     pop ();
  329     break;
  330 
  331       case 's' : /* store variable */
  332     var_name = byte(&pc);
  333     if ((var_name & 0x80) != 0)
  334       var_name = ((var_name & 0x7f) << 8) + byte(&pc);
  335     store_var (var_name);
  336     break;
  337 
  338       case 'w' : /* Write a string to the output. */
  339     while ((ch = byte(&pc)) != '"') out_schar (ch);
  340     fflush (stdout);
  341     break;
  342            
  343       case 'x' : /* Exchange Top of Stack with the one under the tos. */
  344     if (check_stack(2)) {
  345       bc_num temp = ex_stack->s_num;
  346       ex_stack->s_num = ex_stack->s_next->s_num;
  347       ex_stack->s_next->s_num = temp;
  348     }
  349     break;
  350 
  351       case '0' : /* Load Constant 0. */
  352     push_copy (_zero_);
  353     break;
  354 
  355       case '1' : /* Load Constant 1. */
  356     push_copy (_one_);
  357     break;
  358 
  359       case '!' : /* Negate the boolean value on top of the stack. */
  360     c_code = bc_is_zero (ex_stack->s_num);
  361     assign (c_code);
  362     break;
  363 
  364       case '&' : /* compare greater than */
  365     if (check_stack(2))
  366       {
  367         c_code = !bc_is_zero (ex_stack->s_next->s_num)
  368           && !bc_is_zero (ex_stack->s_num);
  369         pop ();
  370         assign (c_code);
  371       }
  372     break;
  373 
  374       case '|' : /* compare greater than */
  375     if (check_stack(2))
  376       {
  377         c_code = !bc_is_zero (ex_stack->s_next->s_num)
  378           || !bc_is_zero (ex_stack->s_num);
  379         pop ();
  380         assign (c_code);
  381       }
  382     break;
  383 
  384       case '+' : /* add */
  385     if (check_stack(2))
  386       {
  387         bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
  388         pop();
  389         pop();
  390         push_num (temp_num);
  391         bc_init_num (&temp_num);
  392       }
  393     break;
  394 
  395       case '-' : /* subtract */
  396     if (check_stack(2))
  397       {
  398         bc_sub (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
  399         pop();
  400         pop();
  401         push_num (temp_num);
  402         bc_init_num (&temp_num);
  403       }
  404     break;
  405 
  406       case '*' : /* multiply */
  407     if (check_stack(2))
  408       {
  409         bc_multiply (ex_stack->s_next->s_num, ex_stack->s_num,
  410              &temp_num, scale);
  411         pop();
  412         pop();
  413         push_num (temp_num);
  414         bc_init_num (&temp_num);
  415       }
  416     break;
  417 
  418       case '/' : /* divide */
  419     if (check_stack(2))
  420       {
  421         if (bc_divide (ex_stack->s_next->s_num,
  422                ex_stack->s_num, &temp_num, scale) == 0)
  423           {
  424         pop();
  425         pop();
  426         push_num (temp_num);
  427         bc_init_num (&temp_num);
  428           }
  429         else
  430           rt_error ("Divide by zero");
  431       }
  432     break;
  433 
  434       case '%' : /* remainder */
  435     if (check_stack(2))
  436       {
  437         if (bc_is_zero (ex_stack->s_num))
  438           rt_error ("Modulo by zero");
  439         else
  440           {
  441         bc_modulo (ex_stack->s_next->s_num,
  442                ex_stack->s_num, &temp_num, scale);
  443         pop();
  444         pop();
  445         push_num (temp_num);
  446         bc_init_num (&temp_num);
  447           }
  448       }
  449     break;
  450 
  451       case '^' : /* raise */
  452     if (check_stack(2))
  453       {
  454         bc_raise (ex_stack->s_next->s_num,
  455               ex_stack->s_num, &temp_num, scale);
  456         if (bc_is_zero (ex_stack->s_next->s_num) && bc_is_neg (ex_stack->s_num))
  457           rt_error ("divide by zero");
  458         pop();
  459         pop();
  460         push_num (temp_num);
  461         bc_init_num (&temp_num);
  462       }
  463     break;
  464 
  465       case '=' : /* compare equal */
  466     if (check_stack(2))
  467       {
  468         c_code = bc_compare (ex_stack->s_next->s_num,
  469                  ex_stack->s_num) == 0;
  470         pop ();
  471         assign (c_code);
  472       }
  473     break;
  474 
  475       case '#' : /* compare not equal */
  476     if (check_stack(2))
  477       {
  478         c_code = bc_compare (ex_stack->s_next->s_num,
  479                  ex_stack->s_num) != 0;
  480         pop ();
  481         assign (c_code);
  482       }
  483     break;
  484 
  485       case '<' : /* compare less than */
  486     if (check_stack(2))
  487       {
  488         c_code = bc_compare (ex_stack->s_next->s_num,
  489                  ex_stack->s_num) == -1;
  490         pop ();
  491         assign (c_code);
  492       }
  493     break;
  494 
  495       case '{' : /* compare less than or equal */
  496     if (check_stack(2))
  497       {
  498         c_code = bc_compare (ex_stack->s_next->s_num,
  499                  ex_stack->s_num) <= 0;
  500         pop ();
  501         assign (c_code);
  502       }
  503     break;
  504 
  505       case '>' : /* compare greater than */
  506     if (check_stack(2))
  507       {
  508         c_code = bc_compare (ex_stack->s_next->s_num,
  509                  ex_stack->s_num) == 1;
  510         pop ();
  511         assign (c_code);
  512       }
  513     break;
  514 
  515       case '}' : /* compare greater than or equal */
  516     if (check_stack(2))
  517       {
  518         c_code = bc_compare (ex_stack->s_next->s_num,
  519                  ex_stack->s_num) >= 0;
  520         pop ();
  521         assign (c_code);
  522       }
  523     break;
  524 
  525     default  : /* error! */
  526       rt_error ("bad instruction: inst=%c", inst);
  527       }
  528     }
  529 
  530   /* Clean up the function stack and pop all autos/parameters. */
  531   while (pc.pc_func != 0)
  532     {
  533       pop_vars(functions[pc.pc_func].f_autos);
  534       pop_vars(functions[pc.pc_func].f_params);
  535       fpop ();
  536       pc.pc_addr = fpop ();
  537       pc.pc_func = fpop ();
  538     }
  539 
  540   /* Clean up the execution stack. */ 
  541   while (ex_stack != NULL) pop();
  542 
  543   /* Clean up the interrupt stuff. */
  544   if (interactive)
  545     {
  546       signal (SIGINT, use_quit);
  547       if (had_sigint)
  548     printf ("\ninterrupted execution.\n");
  549     }
  550 }
  551 
  552 
  553 /* Prog_char gets another byte from the program.  It is used for
  554    conversion of text constants in the code to numbers. */
  555 
  556 int
  557 prog_char ()
  558 {
  559   return (int) byte(&pc);
  560 }
  561 
  562 
  563 /* Read a character from the standard input.  This function is used
  564    by the "read" function. */
  565 
  566 int
  567 input_char ()
  568 {
  569   int in_ch;
  570   
  571   /* Get a character from the standard input for the read function. */
  572   in_ch = getchar();
  573 
  574   /* Check for a \ quoted newline. */
  575   if (in_ch == '\\')
  576     {
  577       in_ch = getchar();
  578       if (in_ch == '\n') {
  579       in_ch = getchar();
  580       out_col = 0;  /* Saw a new line */
  581     }
  582     }
  583 
  584   /* Classify and preprocess the input character. */
  585   if (isdigit(in_ch))
  586     return (in_ch - '0');
  587   if (in_ch >= 'A' && in_ch <= 'F')
  588     return (in_ch + 10 - 'A');
  589   if (in_ch >= 'a' && in_ch <= 'f')
  590     return (in_ch + 10 - 'a');
  591   if (in_ch == '.' || in_ch == '+' || in_ch == '-')
  592     return (in_ch);
  593   if (in_ch <= ' ')
  594     return (' ');
  595   
  596   return (':');
  597 }
  598 
  599 
  600 /* Push_constant converts a sequence of input characters as returned
  601    by IN_CHAR into a number.  The number is pushed onto the execution
  602    stack.  The number is converted as a number in base CONV_BASE. */
  603 
  604 void
  605 push_constant (in_char, conv_base)
  606    int (*in_char)(VOID);
  607    int conv_base;
  608 {
  609   int digits;
  610   bc_num build, temp, result, mult, divisor;
  611   int   in_ch, first_ch;
  612   char  negative;
  613 
  614   /* Initialize all bc numbers */
  615   bc_init_num (&temp);
  616   bc_init_num (&result);
  617   bc_init_num (&mult);
  618   build = bc_copy_num (_zero_);
  619   negative = FALSE;
  620 
  621   /* The conversion base. */
  622   bc_int2num (&mult, conv_base);
  623   
  624   /* Get things ready. */
  625   in_ch = in_char();
  626   while (in_ch == ' ')
  627     in_ch = in_char();
  628 
  629   if (in_ch == '+')
  630     in_ch = in_char();
  631   else
  632     if (in_ch == '-')
  633       {
  634     negative = TRUE;
  635     in_ch = in_char();
  636       }
  637 
  638   /* Check for the special case of a single digit. */
  639   if (in_ch < 16)
  640     {
  641       first_ch = in_ch;
  642       in_ch = in_char();
  643       if (in_ch < 16 && first_ch >= conv_base)
  644     first_ch = conv_base - 1;
  645       bc_int2num (&build, (int) first_ch);
  646     }
  647 
  648   /* Convert the integer part. */
  649   while (in_ch < 16)
  650     {
  651       if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
  652       bc_multiply (build, mult, &result, 0);
  653       bc_int2num (&temp, (int) in_ch);
  654       bc_add (result, temp, &build, 0);
  655       in_ch = in_char();
  656     }
  657   if (in_ch == '.')
  658     {
  659       in_ch = in_char();
  660       if (in_ch >= conv_base) in_ch = conv_base-1;
  661       bc_free_num (&result);
  662       bc_free_num (&temp);
  663       divisor = bc_copy_num (_one_);
  664       result = bc_copy_num (_zero_);
  665       digits = 0;
  666       while (in_ch < 16)
  667     {
  668       bc_multiply (result, mult, &result, 0);
  669       bc_int2num (&temp, (int) in_ch);
  670       bc_add (result, temp, &result, 0);
  671       bc_multiply (divisor, mult, &divisor, 0);
  672       digits++;
  673       in_ch = in_char();
  674       if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
  675     }
  676       bc_divide (result, divisor, &result, digits);
  677       bc_add (build, result, &build, 0);
  678     }
  679   
  680   /* Final work.  */
  681   if (negative)
  682     bc_sub (_zero_, build, &build, 0);
  683 
  684   push_num (build);
  685   bc_free_num (&temp);
  686   bc_free_num (&result);
  687   bc_free_num (&mult);
  688 }
  689 
  690 
  691 /* When converting base 10 constants from the program, we use this
  692    more efficient way to convert them to numbers.  PC tells where
  693    the constant starts and is expected to be advanced to after
  694    the constant. */
  695 
  696 void
  697 push_b10_const (progctr)
  698      program_counter *progctr;
  699 {
  700   bc_num build;
  701   program_counter look_pc;
  702   int kdigits, kscale;
  703   unsigned char inchar;
  704   char *ptr;
  705   
  706   /* Count the digits and get things ready. */
  707   look_pc = *progctr;
  708   kdigits = 0;
  709   kscale  = 0;
  710   inchar = byte (&look_pc);
  711   while (inchar != '.' && inchar != ':')
  712     {
  713       kdigits++;
  714       inchar = byte(&look_pc);
  715     }
  716   if (inchar == '.' )
  717     {
  718       inchar = byte(&look_pc);
  719       while (inchar != ':')
  720     {
  721       kscale++;
  722       inchar = byte(&look_pc);
  723     }
  724     }
  725 
  726   /* Get the first character again and move the progctr. */
  727   inchar = byte(progctr);
  728   
  729   /* Secial cases of 0, 1, and A-F single inputs. */
  730   if (kdigits == 1 && kscale == 0)
  731     {
  732       if (inchar == 0)
  733     {
  734       push_copy (_zero_);
  735       inchar = byte(progctr);
  736       return;
  737     }
  738       if (inchar == 1) {
  739       push_copy (_one_);
  740       inchar = byte(progctr);
  741       return;
  742     }
  743     if (inchar > 9)
  744       {
  745     bc_init_num (&build);
  746     bc_int2num (&build, inchar);
  747     push_num (build);
  748     inchar = byte(progctr);
  749     return;
  750       }
  751     }
  752 
  753   /* Build the new number. */
  754   if (kdigits == 0)
  755     {
  756       build = bc_new_num (1,kscale);
  757       ptr = build->n_value;
  758       *ptr++ = 0;
  759     }
  760   else
  761     {
  762       build = bc_new_num (kdigits,kscale);
  763       ptr = build->n_value;
  764     }
  765 
  766   while (inchar != ':')
  767     {
  768       if (inchar != '.')
  769     {
  770       if (inchar > 9)
  771         *ptr++ = 9;
  772       else
  773         *ptr++ = inchar;
  774     }
  775       inchar = byte(progctr);
  776     }
  777   push_num (build);
  778 }
  779 
  780 
  781 /* Put the correct value on the stack for C_CODE.  Frees TOS num. */
  782 
  783 void
  784 assign (code)
  785      char code;
  786 {
  787   bc_free_num (&ex_stack->s_num);
  788   if (code)
  789     ex_stack->s_num = bc_copy_num (_one_);
  790   else
  791     ex_stack->s_num = bc_copy_num (_zero_);
  792 }
  793