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 if (id
->a_name
< MAX_STORE
)
579 if (id
->a_name
>= a_count
)
581 a_names
[id
->a_name
] = name
;
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 if (id
->f_name
< MAX_STORE
)
600 if (id
->f_name
>= f_count
)
602 f_names
[id
->f_name
] = name
;
605 yyerror ("Too many functions");
614 id
->v_name
= next_var
++;
615 if (id
->v_name
<= MAX_STORE
)
617 if (id
->v_name
>= v_count
)
619 v_names
[id
->v_name
- 1] = name
;
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");