summaryrefslogtreecommitdiff
path: root/bc/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'bc/util.c')
-rw-r--r--bc/util.c319
1 files changed, 142 insertions, 177 deletions
diff --git a/bc/util.c b/bc/util.c
index c305c2e..8eba093 100644
--- a/bc/util.c
+++ b/bc/util.c
@@ -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*/
+}