diff options
Diffstat (limited to 'bc/util.c')
-rw-r--r-- | bc/util.c | 319 |
1 files changed, 142 insertions, 177 deletions
@@ -1,11 +1,10 @@ -/* util.c: Utility routines for bc. */ - /* This file is part of GNU bc. - Copyright (C) 1991-1994, 1997, 2000 Free Software Foundation, Inc. + + Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License , or + the Free Software Foundation; either version 3 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,10 +13,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - The Free Software Foundation, Inc. - 59 Temple Place, Suite 330 - Boston, MA 02111 USA + along with this program; see the file COPYING. If not, see + <http://www.gnu.org/licenses>. You may contact the author by: e-mail: philnelson@acm.org @@ -28,6 +25,7 @@ *************************************************************************/ +/* util.c: Utility routines for bc. */ #include "bcdefs.h" #ifndef VARARGS @@ -35,7 +33,6 @@ #else #include <varargs.h> #endif -#include "global.h" #include "proto.h" @@ -43,12 +40,11 @@ memory. */ char * -strcopyof (str) - char *str; +strcopyof (const char *str) { char *temp; - temp = (char *) bc_malloc (strlen (str)+1); + temp = bc_malloc (strlen (str)+1); return (strcpy (temp,str)); } @@ -56,13 +52,10 @@ strcopyof (str) /* nextarg adds another value to the list of arguments. */ arg_list * -nextarg (args, val, is_var) - arg_list *args; - int val; - int is_var; +nextarg (arg_list *args, int val, int is_var) { arg_list *temp; - temp = (arg_list *) bc_malloc (sizeof (arg_list)); + temp = bc_malloc (sizeof (arg_list)); temp->av_name = val; temp->arg_is_var = is_var; temp->next = args; @@ -84,22 +77,20 @@ static char *arglist1 = NULL, *arglist2 = NULL; characters needed. 1 char is the minimum needed. */ -_PROTOTYPE (static char *make_arg_str, (arg_list *args, int len)); +static char *make_arg_str (arg_list *args, int len); static char * -make_arg_str (args, len) - arg_list *args; - int len; +make_arg_str (arg_list *args, int len) { char *temp; - char sval[20]; + char sval[30]; /* Recursive call. */ if (args != NULL) temp = make_arg_str (args->next, len+12); else { - temp = (char *) bc_malloc (len); + temp = bc_malloc (len); *temp = 0; return temp; } @@ -107,21 +98,20 @@ make_arg_str (args, len) /* Add the current number to the end of the string. */ if (args->arg_is_var) if (len != 1) - sprintf (sval, "*%d,", args->av_name); + snprintf (sval, sizeof(sval), "*%d,", args->av_name); else - sprintf (sval, "*%d", args->av_name); + snprintf (sval, sizeof(sval), "*%d", args->av_name); else if (len != 1) - sprintf (sval, "%d,", args->av_name); + snprintf (sval, sizeof(sval), "%d,", args->av_name); else - sprintf (sval, "%d", args->av_name); + snprintf (sval, sizeof(sval), "%d", args->av_name); temp = strcat (temp, sval); return (temp); } char * -arg_str (args) - arg_list *args; +arg_str (arg_list *args) { if (arglist2 != NULL) free (arglist2); @@ -131,8 +121,7 @@ arg_str (args) } char * -call_str (args) - arg_list *args; +call_str (arg_list *args) { arg_list *temp; int arg_count; @@ -145,7 +134,7 @@ call_str (args) /* Count the number of args and add the 0's and 1's. */ for (temp = args, arg_count = 0; temp != NULL; temp = temp->next) arg_count++; - arglist1 = (char *) bc_malloc(arg_count+1); + arglist1 = bc_malloc(arg_count+1); for (temp = args, ix=0; temp != NULL; temp = temp->next) arglist1[ix++] = ( temp->av_name ? '1' : '0'); arglist1[ix] = 0; @@ -156,8 +145,7 @@ call_str (args) /* free_args frees an argument list ARGS. */ void -free_args (args) - arg_list *args; +free_args (arg_list *args) { arg_list *temp; @@ -176,8 +164,7 @@ free_args (args) warnings are generated for array parameters. */ void -check_params ( params, autos ) - arg_list *params, *autos; +check_params (arg_list *params, arg_list *autos) { arg_list *tmp1, *tmp2; @@ -195,7 +182,7 @@ check_params ( params, autos ) tmp2 = tmp2->next; } if (tmp1->arg_is_var) - warn ("Variable array parameter"); + ct_warn ("Variable array parameter"); tmp1 = tmp1->next; } } @@ -237,11 +224,23 @@ check_params ( params, autos ) } } +/* genstr management to avoid buffer overflow. */ +void +set_genstr_size (int size) +{ + if (size > genlen) { + if (genstr != NULL) + free(genstr); + genstr = bc_malloc (size); + genlen = size; + } +} + /* Initialize the code generator the parser. */ void -init_gen () +init_gen (void) { /* Get things ready. */ break_label = 0; @@ -254,14 +253,14 @@ init_gen () init_load (); had_error = FALSE; did_gen = FALSE; + set_genstr_size (64); } /* generate code STR for the machine. */ void -generate (str) - char *str; +generate (const char *str) { did_gen = TRUE; if (compile_only) @@ -282,7 +281,7 @@ generate (str) /* Execute the current code as loaded. */ void -run_code() +run_code(void) { /* If no compile errors run the current code. */ if (!had_error && did_gen) @@ -309,8 +308,7 @@ run_code() break the output with a "\<cr>". Always used for numbers. */ void -out_char (ch) - int ch; +out_char (int ch) { if (ch == '\n') { @@ -320,7 +318,7 @@ out_char (ch) else { out_col++; - if (out_col == line_size-1) + if (out_col == line_size-1 && line_size != 0) { putchar ('\\'); putchar ('\n'); @@ -336,8 +334,7 @@ out_char (ch) In POSIX bc, strings are not broken across lines. */ void -out_schar (ch) - int ch; +out_schar (int ch) { if (ch == '\n') { @@ -349,7 +346,7 @@ out_schar (ch) if (!std_only) { out_col++; - if (out_col == line_size-1) + if (out_col == line_size-1 && line_size != 0) { putchar ('\\'); putchar ('\n'); @@ -367,9 +364,7 @@ out_schar (ch) ID. If there is no node in TREE with ID, NULL is returned. */ id_rec * -find_id (tree, id) - id_rec *tree; - char *id; +find_id (id_rec *tree, const char *id) { int cmp_result; @@ -393,9 +388,7 @@ find_id (tree, id) ROOT down is increased otherwise it returns FALSE. This is a recursive balanced binary tree insertion algorithm. */ -int insert_id_rec (root, new_id) - id_rec **root; - id_rec *new_id; +int insert_id_rec (id_rec **root, id_rec *new_id) { id_rec *A, *B; @@ -418,50 +411,50 @@ int insert_id_rec (root, new_id) /* The height increased. */ (*root)->balance --; - switch ((*root)->balance) - { - case 0: /* no height increase. */ - return (FALSE); - case -1: /* height increase. */ - return (FALSE); - case -2: /* we need to do a rebalancing act. */ - A = *root; - B = (*root)->left; - if (B->balance <= 0) - { - /* Single Rotate. */ - A->left = B->right; - B->right = A; - *root = B; - A->balance = 0; - B->balance = 0; - } - else + switch ((*root)->balance) { - /* Double Rotate. */ - *root = B->right; - B->right = (*root)->left; - A->left = (*root)->right; - (*root)->left = B; - (*root)->right = A; - switch ((*root)->balance) + case 0: /* no height increase. */ + return (FALSE); + case -1: /* height increase. */ + return (TRUE); + case -2: /* we need to do a rebalancing act. */ + A = *root; + B = (*root)->left; + if (B->balance <= 0) { - case -1: - A->balance = 1; - B->balance = 0; - break; - case 0: + /* Single Rotate. */ + A->left = B->right; + B->right = A; + *root = B; A->balance = 0; B->balance = 0; - break; - case 1: - A->balance = 0; - B->balance = -1; - break; } - (*root)->balance = 0; - } - } + else + { + /* Double Rotate. */ + *root = B->right; + B->right = (*root)->left; + A->left = (*root)->right; + (*root)->left = B; + (*root)->right = A; + switch ((*root)->balance) + { + case -1: + A->balance = 1; + B->balance = 0; + break; + case 0: + A->balance = 0; + B->balance = 0; + break; + case 1: + A->balance = 0; + B->balance = -1; + break; + } + (*root)->balance = 0; + } + } } } else @@ -471,12 +464,13 @@ int insert_id_rec (root, new_id) { /* The height increased. */ (*root)->balance ++; + switch ((*root)->balance) { case 0: /* no height increase. */ return (FALSE); case 1: /* height increase. */ - return (FALSE); + return (TRUE); case 2: /* we need to do a rebalancing act. */ A = *root; B = (*root)->right; @@ -526,7 +520,7 @@ int insert_id_rec (root, new_id) /* Initialize variables for the symbol table tree. */ void -init_tree() +init_tree(void) { name_tree = NULL; next_array = 1; @@ -539,22 +533,20 @@ init_tree() /* Lookup routines for symbol table names. */ int -lookup (name, namekind) - char *name; - int namekind; +lookup (char *name, int namekind) { id_rec *id; /* Warn about non-standard name. */ if (strlen(name) != 1) - warn ("multiple letter name - %s", name); + ct_warn ("multiple letter name - %s", name); /* Look for the id. */ id = find_id (name_tree, name); if (id == NULL) { /* We need to make a new item. */ - id = (id_rec *) bc_malloc (sizeof (id_rec)); + id = bc_malloc (sizeof (id_rec)); id->id = strcopyof (name); id->a_name = 0; id->f_name = 0; @@ -574,36 +566,38 @@ lookup (name, namekind) return (-id->a_name); } id->a_name = next_array++; - a_names[id->a_name] = name; if (id->a_name < MAX_STORE) { if (id->a_name >= a_count) more_arrays (); + a_names[id->a_name] = name; return (-id->a_name); } yyerror ("Too many array variables"); - exit (1); + bc_exit (1); + /*NOTREACHED*/ case FUNCT: case FUNCTDEF: if (id->f_name != 0) { - free(name); + free(name); /* Check to see if we are redefining a math lib function. */ if (use_math && namekind == FUNCTDEF && id->f_name <= 6) id->f_name = next_func++; return (id->f_name); } id->f_name = next_func++; - f_names[id->f_name] = name; if (id->f_name < MAX_STORE) { if (id->f_name >= f_count) more_functions (); + f_names[id->f_name] = name; return (id->f_name); } yyerror ("Too many functions"); - exit (1); + bc_exit (1); + /*NOTREACHED*/ case SIMPLE: if (id->v_name != 0) @@ -612,68 +606,29 @@ lookup (name, namekind) return (id->v_name); } id->v_name = next_var++; - v_names[id->v_name - 1] = name; if (id->v_name <= MAX_STORE) { if (id->v_name >= v_count) more_variables (); + v_names[id->v_name - 1] = name; return (id->v_name); } yyerror ("Too many variables"); - exit (1); + bc_exit (1); + /*NOTREACHED*/ + } yyerror ("End of util.c/lookup() reached. Please report this bug."); - exit (1); - /* not reached */ -} - - -/* Print the welcome banner. */ - -void -welcome() -{ - printf ("This is free software with ABSOLUTELY NO WARRANTY.\n"); - printf ("For details type `warranty'. \n"); -} - -/* Print out the version information. */ -void -show_bc_version() -{ - printf("%s %s\n%s\n", PACKAGE, VERSION, BC_COPYRIGHT); -} - - -/* Print out the warranty information. */ - -void -warranty(prefix) - char *prefix; -{ - printf ("\n%s", prefix); - show_bc_version (); - printf ("\n" -" This program is free software; you can redistribute it and/or modify\n" -" it under the terms of the GNU General Public License as published by\n" -" the Free Software Foundation; either version 2 of the License , or\n" -" (at your option) any later version.\n\n" -" This program is distributed in the hope that it will be useful,\n" -" but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -" GNU General Public License for more details.\n\n" -" You should have received a copy of the GNU General Public License\n" -" along with this program. If not, write to\n\n" -" The Free Software Foundation, Inc.\n" -" 59 Temple Place, Suite 330\n" -" Boston, MA 02111, USA.\n\n"); + bc_exit (1); + /*NOTREACHED*/ + return 0; } /* Print out the limits of this program. */ void -limits() +limits(void) { printf ("BC_BASE_MAX = %d\n", BC_BASE_MAX); printf ("BC_DIM_MAX = %ld\n", (long) BC_DIM_MAX); @@ -689,13 +644,12 @@ limits() /* bc_malloc will check the return value so all other places do not have to do it! SIZE is the number of bytes to allocate. */ -char * -bc_malloc (size) - int size; +void * +bc_malloc (size_t size) { - char *ptr; + void *ptr; - ptr = (char *) malloc (size); + ptr = (void *) malloc (size); if (ptr == NULL) out_of_memory (); @@ -708,10 +662,11 @@ bc_malloc (size) /* Malloc could not get enought memory. */ void -out_of_memory() +out_of_memory(void) { fprintf (stderr, "Fatal error: Out of memory for malloc.\n"); - exit (1); + bc_exit (1); + /*NOTREACHED*/ } @@ -721,19 +676,19 @@ out_of_memory() #ifndef VARARGS #ifdef __STDC__ void -yyerror (char *str, ...) +yyerror (const char *str, ...) #else void yyerror (str) - char *str; + const char *str; #endif #else void yyerror (str, va_alist) - char *str; + const char *str; #endif { - char *name; + const char *name; va_list args; #ifndef VARARGS @@ -759,19 +714,19 @@ yyerror (str, va_alist) #ifndef VARARGS #ifdef __STDC__ void -warn (char *mesg, ...) +ct_warn (const char *mesg, ...) #else void -warn (mesg) - char *mesg; +ct_warn (mesg) + const char *mesg; #endif #else void -warn (mesg, va_alist) - char *mesg; +ct_warn (mesg, va_alist) + const char *mesg; #endif { - char *name; + const char *name; va_list args; #ifndef VARARGS @@ -785,7 +740,7 @@ warn (mesg, va_alist) name = "(standard_in)"; else name = file_name; - fprintf (stderr,"%s %d: ",name,line_no); + fprintf (stderr,"%s %d: Error: ",name,line_no); vfprintf (stderr, mesg, args); fprintf (stderr, "\n"); had_error = TRUE; @@ -809,16 +764,16 @@ warn (mesg, va_alist) #ifndef VARARGS #ifdef __STDC__ void -rt_error (char *mesg, ...) +rt_error (const char *mesg, ...) #else void rt_error (mesg) - char *mesg; + const char *mesg; #endif #else void rt_error (mesg, va_alist) - char *mesg; + const char *mesg; #endif { va_list args; @@ -845,16 +800,14 @@ rt_error (mesg, va_alist) #ifndef VARARGS #ifdef __STDC__ void -rt_warn (char *mesg, ...) +rt_warn (const char *mesg, ...) #else void -rt_warn (mesg) - char *mesg; +rt_warn (const char *mesg) #endif #else void -rt_warn (mesg, va_alist) - char *mesg; +rt_warn (const char *mesg) #endif { va_list args; @@ -871,3 +824,15 @@ rt_warn (mesg, va_alist) fprintf (stderr, "\n"); } + +/* bc_exit: Make sure to reset the edit state. */ + +void bc_exit(int val) +{ +#if defined(LIBEDIT) + if (edit != NULL) + el_end(edit); +#endif + exit(val); + /*NOTREACHED*/ +} |