Fix up mix of man(7)/mdoc(7).
[netbsd-mini2440.git] / gnu / dist / bc / bc / util.c
blob9af6a062c6714d819e5a2ea7b39c0ee3b634a623
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
20 Boston, MA 02111 USA
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 *************************************************************************/
32 #include "bcdefs.h"
33 #ifndef VARARGS
34 #include <stdarg.h>
35 #else
36 #include <varargs.h>
37 #endif
38 #include "global.h"
39 #include "proto.h"
42 /* strcopyof mallocs new memory and copies a string to to the new
43 memory. */
45 char *
46 strcopyof (str)
47 char *str;
49 char *temp;
51 temp = (char *) bc_malloc (strlen (str)+1);
52 return (strcpy (temp,str));
56 /* nextarg adds another value to the list of arguments. */
58 arg_list *
59 nextarg (args, val, is_var)
60 arg_list *args;
61 int val;
62 int is_var;
63 { arg_list *temp;
65 temp = (arg_list *) bc_malloc (sizeof (arg_list));
66 temp->av_name = val;
67 temp->arg_is_var = is_var;
68 temp->next = args;
70 return (temp);
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));
89 static char *
90 make_arg_str (args, len)
91 arg_list *args;
92 int len;
94 char *temp;
95 char sval[20];
97 /* Recursive call. */
98 if (args != NULL)
99 temp = make_arg_str (args->next, len+12);
100 else
102 temp = (char *) bc_malloc (len);
103 *temp = 0;
104 return temp;
107 /* Add the current number to the end of the string. */
108 if (args->arg_is_var)
109 if (len != 1)
110 sprintf (sval, "*%d,", args->av_name);
111 else
112 sprintf (sval, "*%d", args->av_name);
113 else
114 if (len != 1)
115 sprintf (sval, "%d,", args->av_name);
116 else
117 sprintf (sval, "%d", args->av_name);
118 temp = strcat (temp, sval);
119 return (temp);
122 char *
123 arg_str (args)
124 arg_list *args;
126 if (arglist2 != NULL)
127 free (arglist2);
128 arglist2 = arglist1;
129 arglist1 = make_arg_str (args, 1);
130 return (arglist1);
133 char *
134 call_str (args)
135 arg_list *args;
137 arg_list *temp;
138 int arg_count;
139 int ix;
141 if (arglist2 != NULL)
142 free (arglist2);
143 arglist2 = arglist1;
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)
147 arg_count++;
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');
151 arglist1[ix] = 0;
153 return (arglist1);
156 /* free_args frees an argument list ARGS. */
158 void
159 free_args (args)
160 arg_list *args;
162 arg_list *temp;
164 temp = args;
165 while (temp != NULL)
167 args = args->next;
168 free (temp);
169 temp = 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. */
178 void
179 check_params ( params, autos )
180 arg_list *params, *autos;
182 arg_list *tmp1, *tmp2;
184 /* Check for duplicate parameters. */
185 if (params != NULL)
187 tmp1 = params;
188 while (tmp1 != NULL)
190 tmp2 = tmp1->next;
191 while (tmp2 != NULL)
193 if (tmp2->av_name == tmp1->av_name)
194 yyerror ("duplicate parameter names");
195 tmp2 = tmp2->next;
197 if (tmp1->arg_is_var)
198 warn ("Variable array parameter");
199 tmp1 = tmp1->next;
203 /* Check for duplicate autos. */
204 if (autos != NULL)
206 tmp1 = autos;
207 while (tmp1 != NULL)
209 tmp2 = tmp1->next;
210 while (tmp2 != NULL)
212 if (tmp2->av_name == tmp1->av_name)
213 yyerror ("duplicate auto variable names");
214 tmp2 = tmp2->next;
216 if (tmp1->arg_is_var)
217 yyerror ("* not allowed here");
218 tmp1 = tmp1->next;
222 /* Check for duplicate between parameters and autos. */
223 if ((params != NULL) && (autos != NULL))
225 tmp1 = params;
226 while (tmp1 != NULL)
228 tmp2 = autos;
229 while (tmp2 != NULL)
231 if (tmp2->av_name == tmp1->av_name)
232 yyerror ("variable in both parameter and auto lists");
233 tmp2 = tmp2->next;
235 tmp1 = tmp1->next;
241 /* Initialize the code generator the parser. */
243 void
244 init_gen ()
246 /* Get things ready. */
247 break_label = 0;
248 continue_label = 0;
249 next_label = 1;
250 out_count = 2;
251 if (compile_only)
252 printf ("@i");
253 else
254 init_load ();
255 had_error = FALSE;
256 did_gen = FALSE;
260 /* generate code STR for the machine. */
262 void
263 generate (str)
264 char *str;
266 did_gen = TRUE;
267 if (compile_only)
269 printf ("%s",str);
270 out_count += strlen(str);
271 if (out_count > 60)
273 printf ("\n");
274 out_count = 0;
277 else
278 load_code (str);
282 /* Execute the current code as loaded. */
284 void
285 run_code()
287 /* If no compile errors run the current code. */
288 if (!had_error && did_gen)
290 if (compile_only)
292 printf ("@r\n");
293 out_count = 0;
295 else
296 execute ();
299 /* Reinitialize the code generation and machine. */
300 if (did_gen)
301 init_gen();
302 else
303 had_error = FALSE;
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. */
311 void
312 out_char (ch)
313 int ch;
315 if (ch == '\n')
317 out_col = 0;
318 putchar ('\n');
320 else
322 out_col++;
323 if (out_col == line_size-1)
325 putchar ('\\');
326 putchar ('\n');
327 out_col = 1;
329 putchar (ch);
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. */
338 void
339 out_schar (ch)
340 int ch;
342 if (ch == '\n')
344 out_col = 0;
345 putchar ('\n');
347 else
349 if (!std_only)
351 out_col++;
352 if (out_col == line_size-1)
354 putchar ('\\');
355 putchar ('\n');
356 out_col = 1;
359 putchar (ch);
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. */
369 id_rec *
370 find_id (tree, id)
371 id_rec *tree;
372 char *id;
374 int cmp_result;
376 /* Check for an empty tree. */
377 if (tree == NULL)
378 return NULL;
380 /* Recursively search the tree. */
381 cmp_result = strcmp (id, tree->id);
382 if (cmp_result == 0)
383 return tree; /* This is the item. */
384 else if (cmp_result < 0)
385 return find_id (tree->left, id);
386 else
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)
397 id_rec **root;
398 id_rec *new_id;
400 id_rec *A, *B;
402 /* If root is NULL, this where it is to be inserted. */
403 if (*root == NULL)
405 *root = new_id;
406 new_id->left = NULL;
407 new_id->right = NULL;
408 new_id->balance = 0;
409 return (TRUE);
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. */
419 (*root)->balance --;
421 switch ((*root)->balance)
423 case 0: /* no height increase. */
424 return (FALSE);
425 case -1: /* height increase. */
426 return (FALSE);
427 case -2: /* we need to do a rebalancing act. */
428 A = *root;
429 B = (*root)->left;
430 if (B->balance <= 0)
432 /* Single Rotate. */
433 A->left = B->right;
434 B->right = A;
435 *root = B;
436 A->balance = 0;
437 B->balance = 0;
439 else
441 /* Double Rotate. */
442 *root = B->right;
443 B->right = (*root)->left;
444 A->left = (*root)->right;
445 (*root)->left = B;
446 (*root)->right = A;
447 switch ((*root)->balance)
449 case -1:
450 A->balance = 1;
451 B->balance = 0;
452 break;
453 case 0:
454 A->balance = 0;
455 B->balance = 0;
456 break;
457 case 1:
458 A->balance = 0;
459 B->balance = -1;
460 break;
462 (*root)->balance = 0;
467 else
469 /* Insert it on the right. */
470 if (insert_id_rec (&((*root)->right), new_id))
472 /* The height increased. */
473 (*root)->balance ++;
474 switch ((*root)->balance)
476 case 0: /* no height increase. */
477 return (FALSE);
478 case 1: /* height increase. */
479 return (FALSE);
480 case 2: /* we need to do a rebalancing act. */
481 A = *root;
482 B = (*root)->right;
483 if (B->balance >= 0)
485 /* Single Rotate. */
486 A->right = B->left;
487 B->left = A;
488 *root = B;
489 A->balance = 0;
490 B->balance = 0;
492 else
494 /* Double Rotate. */
495 *root = B->left;
496 B->left = (*root)->right;
497 A->right = (*root)->left;
498 (*root)->left = A;
499 (*root)->right = B;
500 switch ((*root)->balance)
502 case -1:
503 A->balance = 0;
504 B->balance = 1;
505 break;
506 case 0:
507 A->balance = 0;
508 B->balance = 0;
509 break;
510 case 1:
511 A->balance = -1;
512 B->balance = 0;
513 break;
515 (*root)->balance = 0;
521 /* If we fall through to here, the tree did not grow in height. */
522 return (FALSE);
526 /* Initialize variables for the symbol table tree. */
528 void
529 init_tree()
531 name_tree = NULL;
532 next_array = 1;
533 next_func = 1;
534 /* 0 => ibase, 1 => obase, 2 => scale, 3 => history, 4 => last. */
535 next_var = 5;
539 /* Lookup routines for symbol table names. */
542 lookup (name, namekind)
543 char *name;
544 int namekind;
546 id_rec *id;
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);
554 if (id == NULL)
556 /* We need to make a new item. */
557 id = (id_rec *) bc_malloc (sizeof (id_rec));
558 id->id = strcopyof (name);
559 id->a_name = 0;
560 id->f_name = 0;
561 id->v_name = 0;
562 insert_id_rec (&name_tree, id);
565 /* Return the correct value. */
566 switch (namekind)
569 case ARRAY:
570 /* ARRAY variable numbers are returned as negative numbers. */
571 if (id->a_name != 0)
573 free (name);
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)
580 more_arrays ();
581 a_names[id->a_name] = name;
582 return (-id->a_name);
584 yyerror ("Too many array variables");
585 exit (1);
587 case FUNCT:
588 case FUNCTDEF:
589 if (id->f_name != 0)
591 free(name);
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++;
595 return (id->f_name);
597 id->f_name = next_func++;
598 if (id->f_name < MAX_STORE)
600 if (id->f_name >= f_count)
601 more_functions ();
602 f_names[id->f_name] = name;
603 return (id->f_name);
605 yyerror ("Too many functions");
606 exit (1);
608 case SIMPLE:
609 if (id->v_name != 0)
611 free(name);
612 return (id->v_name);
614 id->v_name = next_var++;
615 if (id->v_name <= MAX_STORE)
617 if (id->v_name >= v_count)
618 more_variables ();
619 v_names[id->v_name - 1] = name;
620 return (id->v_name);
622 yyerror ("Too many variables");
623 exit (1);
626 yyerror ("End of util.c/lookup() reached. Please report this bug.");
627 exit (1);
628 /* not reached */
632 /* Print the welcome banner. */
634 void
635 welcome()
637 printf ("This is free software with ABSOLUTELY NO WARRANTY.\n");
638 printf ("For details type `warranty'. \n");
641 /* Print out the version information. */
642 void
643 show_bc_version()
645 printf("%s %s\n%s\n", PACKAGE, VERSION, BC_COPYRIGHT);
649 /* Print out the warranty information. */
651 void
652 warranty(prefix)
653 char *prefix;
655 printf ("\n%s", prefix);
656 show_bc_version ();
657 printf ("\n"
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. */
675 void
676 limits()
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);
684 #ifdef OLD_EQ_OP
685 printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
686 #endif
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. */
692 char *
693 bc_malloc (size)
694 int size;
696 char *ptr;
698 ptr = (char *) malloc (size);
699 if (ptr == NULL)
700 out_of_memory ();
702 return ptr;
706 /* The following routines are error routines for various problems. */
708 /* Malloc could not get enought memory. */
710 void
711 out_of_memory()
713 fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
714 exit (1);
719 /* The standard yyerror routine. Built with variable number of argumnets. */
721 #ifndef VARARGS
722 #ifdef __STDC__
723 void
724 yyerror (char *str, ...)
725 #else
726 void
727 yyerror (str)
728 char *str;
729 #endif
730 #else
731 void
732 yyerror (str, va_alist)
733 char *str;
734 #endif
736 char *name;
737 va_list args;
739 #ifndef VARARGS
740 va_start (args, str);
741 #else
742 va_start (args);
743 #endif
744 if (is_std_in)
745 name = "(standard_in)";
746 else
747 name = file_name;
748 fprintf (stderr,"%s %d: ",name,line_no);
749 vfprintf (stderr, str, args);
750 fprintf (stderr, "\n");
751 had_error = TRUE;
752 va_end (args);
756 /* The routine to produce warnings about non-standard features
757 found during parsing. */
759 #ifndef VARARGS
760 #ifdef __STDC__
761 void
762 warn (char *mesg, ...)
763 #else
764 void
765 warn (mesg)
766 char *mesg;
767 #endif
768 #else
769 void
770 warn (mesg, va_alist)
771 char *mesg;
772 #endif
774 char *name;
775 va_list args;
777 #ifndef VARARGS
778 va_start (args, mesg);
779 #else
780 va_start (args);
781 #endif
782 if (std_only)
784 if (is_std_in)
785 name = "(standard_in)";
786 else
787 name = file_name;
788 fprintf (stderr,"%s %d: ",name,line_no);
789 vfprintf (stderr, mesg, args);
790 fprintf (stderr, "\n");
791 had_error = TRUE;
793 else
794 if (warn_not_std)
796 if (is_std_in)
797 name = "(standard_in)";
798 else
799 name = file_name;
800 fprintf (stderr,"%s %d: (Warning) ",name,line_no);
801 vfprintf (stderr, mesg, args);
802 fprintf (stderr, "\n");
804 va_end (args);
807 /* Runtime error will print a message and stop the machine. */
809 #ifndef VARARGS
810 #ifdef __STDC__
811 void
812 rt_error (char *mesg, ...)
813 #else
814 void
815 rt_error (mesg)
816 char *mesg;
817 #endif
818 #else
819 void
820 rt_error (mesg, va_alist)
821 char *mesg;
822 #endif
824 va_list args;
826 fprintf (stderr, "Runtime error (func=%s, adr=%d): ",
827 f_names[pc.pc_func], pc.pc_addr);
828 #ifndef VARARGS
829 va_start (args, mesg);
830 #else
831 va_start (args);
832 #endif
833 vfprintf (stderr, mesg, args);
834 va_end (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. */
845 #ifndef VARARGS
846 #ifdef __STDC__
847 void
848 rt_warn (char *mesg, ...)
849 #else
850 void
851 rt_warn (mesg)
852 char *mesg;
853 #endif
854 #else
855 void
856 rt_warn (mesg, va_alist)
857 char *mesg;
858 #endif
860 va_list args;
862 fprintf (stderr, "Runtime warning (func=%s, adr=%d): ",
863 f_names[pc.pc_func], pc.pc_addr);
864 #ifndef VARARGS
865 va_start (args, mesg);
866 #else
867 va_start (args);
868 #endif
869 vfprintf (stderr, mesg, args);
870 va_end (args);
872 fprintf (stderr, "\n");