1 /* util.c: Utility routines for bc. */
3 /* This file is part of GNU bc.
4 Copyright (C) 1991-1994, 1997, 2000 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, Inc.
19 59 Temple Place, Suite 330
22 You may contact the author by:
23 e-mail: philnelson@acm.org
24 us-mail: Philip A. Nelson
25 Computer Science Department, 9062
26 Western Washington University
27 Bellingham, WA 98226-9062
29 *************************************************************************/
42 /* strcopyof mallocs new memory and copies a string to to the new
51 temp = (char *) bc_malloc (strlen (str)+1);
52 return (strcpy (temp,str));
56 /* nextarg adds another value to the list of arguments. */
59 nextarg (args, val, is_var)
65 temp = (arg_list *) bc_malloc (sizeof (arg_list));
67 temp->arg_is_var = is_var;
74 /* For generate, we must produce a string in the form
75 "val,val,...,val". We also need a couple of static variables
76 for retaining old generated strings. It also uses a recursive
77 function that builds the string. */
79 static char *arglist1 = NULL, *arglist2 = NULL;
82 /* make_arg_str does the actual construction of the argument string.
83 ARGS is the pointer to the list and LEN is the maximum number of
84 characters needed. 1 char is the minimum needed.
87 _PROTOTYPE (static char *make_arg_str, (arg_list *args, int len));
90 make_arg_str (args, len)
99 temp = make_arg_str (args->next, len+12);
102 temp = (char *) bc_malloc (len);
107 /* Add the current number to the end of the string. */
108 if (args->arg_is_var)
110 sprintf (sval, "*%d,", args->av_name);
112 sprintf (sval, "*%d", args->av_name);
115 sprintf (sval, "%d,", args->av_name);
117 sprintf (sval, "%d", args->av_name);
118 temp = strcat (temp, sval);
126 if (arglist2 != NULL)
129 arglist1 = make_arg_str (args, 1);
141 if (arglist2 != NULL)
145 /* Count the number of args and add the 0's and 1's. */
146 for (temp = args, arg_count = 0; temp != NULL; temp = temp->next)
148 arglist1 = (char *) bc_malloc(arg_count+1);
149 for (temp = args, ix=0; temp != NULL; temp = temp->next)
150 arglist1[ix++] = ( temp->av_name ? '1' : '0');
156 /* free_args frees an argument list ARGS. */
174 /* Check for valid parameter (PARAMS) and auto (AUTOS) lists.
175 There must be no duplicates any where. Also, this is where
176 warnings are generated for array parameters. */
179 check_params ( params, autos )
180 arg_list *params, *autos;
182 arg_list *tmp1, *tmp2;
184 /* Check for duplicate parameters. */
193 if (tmp2->av_name == tmp1->av_name)
194 yyerror ("duplicate parameter names");
197 if (tmp1->arg_is_var)
198 warn ("Variable array parameter");
203 /* Check for duplicate autos. */
212 if (tmp2->av_name == tmp1->av_name)
213 yyerror ("duplicate auto variable names");
216 if (tmp1->arg_is_var)
217 yyerror ("* not allowed here");
222 /* Check for duplicate between parameters and autos. */
223 if ((params != NULL) && (autos != NULL))
231 if (tmp2->av_name == tmp1->av_name)
232 yyerror ("variable in both parameter and auto lists");
241 /* Initialize the code generator the parser. */
246 /* Get things ready. */
260 /* generate code STR for the machine. */
270 out_count += strlen(str);
282 /* Execute the current code as loaded. */
287 /* If no compile errors run the current code. */
288 if (!had_error && did_gen)
299 /* Reinitialize the code generation and machine. */
307 /* Output routines: Write a character CH to the standard output.
308 It keeps track of the number of characters output and may
309 break the output with a "\<cr>". Always used for numbers. */
323 if (out_col == line_size-1)
333 /* Output routines: Write a character CH to the standard output.
334 It keeps track of the number of characters output and may
335 break the output with a "\<cr>". This one is for strings.
336 In POSIX bc, strings are not broken across lines. */
352 if (out_col == line_size-1)
364 /* The following are "Symbol Table" routines for the parser. */
366 /* find_id returns a pointer to node in TREE that has the correct
367 ID. If there is no node in TREE with ID, NULL is returned. */
376 /* Check for an empty tree. */
380 /* Recursively search the tree. */
381 cmp_result = strcmp (id, tree->id);
383 return tree; /* This is the item. */
384 else if (cmp_result < 0)
385 return find_id (tree->left, id);
387 return find_id (tree->right, id);
391 /* insert_id_rec inserts a NEW_ID rec into the tree whose ROOT is
392 provided. insert_id_rec returns TRUE if the tree height from
393 ROOT down is increased otherwise it returns FALSE. This is a
394 recursive balanced binary tree insertion algorithm. */
396 int insert_id_rec (root, new_id)
402 /* If root is NULL, this where it is to be inserted. */
407 new_id->right = NULL;
412 /* We need to search for a leaf. */
413 if (strcmp (new_id->id, (*root)->id) < 0)
415 /* Insert it on the left. */
416 if (insert_id_rec (&((*root)->left), new_id))
418 /* The height increased. */
421 switch ((*root)->balance)
423 case 0: /* no height increase. */
425 case -1: /* height increase. */
427 case -2: /* we need to do a rebalancing act. */
443 B->right = (*root)->left;
444 A->left = (*root)->right;
447 switch ((*root)->balance)
462 (*root)->balance = 0;
469 /* Insert it on the right. */
470 if (insert_id_rec (&((*root)->right), new_id))
472 /* The height increased. */
474 switch ((*root)->balance)
476 case 0: /* no height increase. */
478 case 1: /* height increase. */
480 case 2: /* we need to do a rebalancing act. */
496 B->left = (*root)->right;
497 A->right = (*root)->left;
500 switch ((*root)->balance)
515 (*root)->balance = 0;
521 /* If we fall through to here, the tree did not grow in height. */
526 /* Initialize variables for the symbol table tree. */
534 /* 0 => ibase, 1 => obase, 2 => scale, 3 => history, 4 => last. */
539 /* Lookup routines for symbol table names. */
542 lookup (name, namekind)
548 /* Warn about non-standard name. */
549 if (strlen(name) != 1)
550 warn ("multiple letter name - %s", name);
552 /* Look for the id. */
553 id = find_id (name_tree, name);
556 /* We need to make a new item. */
557 id = (id_rec *) bc_malloc (sizeof (id_rec));
558 id->id = strcopyof (name);
562 insert_id_rec (&name_tree, id);
565 /* Return the correct value. */
570 /* ARRAY variable numbers are returned as negative numbers. */
574 return (-id->a_name);
576 id->a_name = next_array++;
577 a_names[id->a_name] = name;
578 if (id->a_name < MAX_STORE)
580 if (id->a_name >= a_count)
582 return (-id->a_name);
584 yyerror ("Too many array variables");
592 /* Check to see if we are redefining a math lib function. */
593 if (use_math && namekind == FUNCTDEF && id->f_name <= 6)
594 id->f_name = next_func++;
597 id->f_name = next_func++;
598 f_names[id->f_name] = name;
599 if (id->f_name < MAX_STORE)
601 if (id->f_name >= f_count)
605 yyerror ("Too many functions");
614 id->v_name = next_var++;
615 v_names[id->v_name - 1] = name;
616 if (id->v_name <= MAX_STORE)
618 if (id->v_name >= v_count)
622 yyerror ("Too many variables");
626 yyerror ("End of util.c/lookup() reached. Please report this bug.");
632 /* Print the welcome banner. */
637 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n");
638 printf ("For details type `warranty'. \n");
641 /* Print out the version information. */
645 printf("%s %s\n%s\n", PACKAGE, VERSION, BC_COPYRIGHT);
649 /* Print out the warranty information. */
655 printf ("\n%s", prefix);
658 " This program is free software; you can redistribute it and/or modify\n"
659 " it under the terms of the GNU General Public License as published by\n"
660 " the Free Software Foundation; either version 2 of the License , or\n"
661 " (at your option) any later version.\n\n"
662 " This program is distributed in the hope that it will be useful,\n"
663 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
664 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
665 " GNU General Public License for more details.\n\n"
666 " You should have received a copy of the GNU General Public License\n"
667 " along with this program. If not, write to\n\n"
668 " The Free Software Foundation, Inc.\n"
669 " 59 Temple Place, Suite 330\n"
670 " Boston, MA 02111, USA.\n\n");
673 /* Print out the limits of this program. */
678 printf ("BC_BASE_MAX = %d\n", BC_BASE_MAX);
679 printf ("BC_DIM_MAX = %ld\n", (long) BC_DIM_MAX);
680 printf ("BC_SCALE_MAX = %d\n", BC_SCALE_MAX);
681 printf ("BC_STRING_MAX = %d\n", BC_STRING_MAX);
682 printf ("MAX Exponent = %ld\n", (long) LONG_MAX);
683 printf ("Number of vars = %ld\n", (long) MAX_STORE);
685 printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
689 /* bc_malloc will check the return value so all other places do not
690 have to do it! SIZE is the number of bytes to allocate. */
698 ptr = (char *) malloc (size);
706 /* The following routines are error routines for various problems. */
708 /* Malloc could not get enought memory. */
713 fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
719 /* The standard yyerror routine. Built with variable number of argumnets. */
724 yyerror (char *str, ...)
732 yyerror (str, va_alist)
740 va_start (args, str);
745 name = "(standard_in)";
748 fprintf (stderr,"%s %d: ",name,line_no);
749 vfprintf (stderr, str, args);
750 fprintf (stderr, "\n");
756 /* The routine to produce warnings about non-standard features
757 found during parsing. */
762 warn (char *mesg, ...)
770 warn (mesg, va_alist)
778 va_start (args, mesg);
785 name = "(standard_in)";
788 fprintf (stderr,"%s %d: ",name,line_no);
789 vfprintf (stderr, mesg, args);
790 fprintf (stderr, "\n");
797 name = "(standard_in)";
800 fprintf (stderr,"%s %d: (Warning) ",name,line_no);
801 vfprintf (stderr, mesg, args);
802 fprintf (stderr, "\n");
807 /* Runtime error will print a message and stop the machine. */
812 rt_error (char *mesg, ...)
820 rt_error (mesg, va_alist)
826 fprintf (stderr, "Runtime error (func=%s, adr=%d): ",
827 f_names[pc.pc_func], pc.pc_addr);
829 va_start (args, mesg);
833 vfprintf (stderr, mesg, args);
836 fprintf (stderr, "\n");
837 runtime_error = TRUE;
841 /* A runtime warning tells of some action taken by the processor that
842 may change the program execution but was not enough of a problem
843 to stop the execution. */
848 rt_warn (char *mesg, ...)
856 rt_warn (mesg, va_alist)
862 fprintf (stderr, "Runtime warning (func=%s, adr=%d): ",
863 f_names[pc.pc_func], pc.pc_addr);
865 va_start (args, mesg);
869 vfprintf (stderr, mesg, args);
872 fprintf (stderr, "\n");