head	1.5;
access;
symbols
	perseant-exfatfs-base-20250801:1.5
	perseant-exfatfs-base-20240630:1.5
	cjep_sun2x:1.5.0.44
	cjep_sun2x-base:1.5
	cjep_staticlib_x-base1:1.5
	cjep_staticlib_x:1.5.0.42
	cjep_staticlib_x-base:1.5
	phil-wifi-20200421:1.5
	phil-wifi-20200411:1.5
	phil-wifi-20200406:1.5
	pgoyette-compat-merge-20190127:1.5
	pgoyette-compat-20190127:1.5
	pgoyette-compat-20190118:1.5
	pgoyette-compat-1226:1.5
	pgoyette-compat-1126:1.5
	pgoyette-compat-1020:1.5
	pgoyette-compat-0930:1.5
	pgoyette-compat-0906:1.5
	pgoyette-compat-0728:1.5
	pgoyette-compat-0625:1.5
	pgoyette-compat-0521:1.5
	pgoyette-compat-0502:1.5
	pgoyette-compat-0422:1.5
	pgoyette-compat-0415:1.5
	pgoyette-compat-0407:1.5
	pgoyette-compat-0330:1.5
	pgoyette-compat-0322:1.5
	pgoyette-compat-0315:1.5
	pgoyette-compat:1.5.0.40
	pgoyette-compat-base:1.5
	perseant-stdc-iso10646:1.5.0.38
	perseant-stdc-iso10646-base:1.5
	prg-localcount2-base3:1.5
	prg-localcount2-base2:1.5
	prg-localcount2-base1:1.5
	prg-localcount2:1.5.0.36
	prg-localcount2-base:1.5
	pgoyette-localcount-20170426:1.5
	bouyer-socketcan-base1:1.5
	pgoyette-localcount-20170320:1.5
	bouyer-socketcan:1.5.0.34
	bouyer-socketcan-base:1.5
	pgoyette-localcount-20170107:1.5
	pgoyette-localcount-20161104:1.5
	localcount-20160914:1.5
	pgoyette-localcount-20160806:1.5
	pgoyette-localcount-20160726:1.5
	pgoyette-localcount:1.5.0.32
	pgoyette-localcount-base:1.5
	netbsd-5-2-3-RELEASE:1.5
	netbsd-5-1-5-RELEASE:1.5
	yamt-pagecache-base9:1.5
	yamt-pagecache-tag8:1.5
	tls-earlyentropy:1.5.0.28
	tls-earlyentropy-base:1.5
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.5
	riastradh-drm2-base3:1.5
	netbsd-5-2-2-RELEASE:1.5
	netbsd-5-1-4-RELEASE:1.5
	netbsd-5-2-1-RELEASE:1.5
	netbsd-5-1-3-RELEASE:1.5
	agc-symver:1.5.0.30
	agc-symver-base:1.5
	tls-maxphys-base:1.5
	yamt-pagecache-base8:1.5
	netbsd-5-2:1.5.0.26
	yamt-pagecache-base7:1.5
	netbsd-5-2-RELEASE:1.5
	netbsd-5-2-RC1:1.5
	yamt-pagecache-base6:1.5
	yamt-pagecache-base5:1.5
	yamt-pagecache-base4:1.5
	netbsd-5-1-2-RELEASE:1.5
	netbsd-5-1-1-RELEASE:1.5
	yamt-pagecache-base3:1.5
	yamt-pagecache-base2:1.5
	yamt-pagecache:1.5.0.24
	yamt-pagecache-base:1.5
	bouyer-quota2-nbase:1.5
	bouyer-quota2:1.5.0.22
	bouyer-quota2-base:1.5
	matt-nb5-pq3:1.5.0.20
	matt-nb5-pq3-base:1.5
	netbsd-5-1:1.5.0.18
	netbsd-5-1-RELEASE:1.5
	netbsd-5-1-RC4:1.5
	netbsd-5-1-RC3:1.5
	netbsd-5-1-RC2:1.5
	netbsd-5-1-RC1:1.5
	netbsd-5-0-2-RELEASE:1.5
	netbsd-5-0-1-RELEASE:1.5
	jym-xensuspend-nbase:1.5
	netbsd-5-0:1.5.0.16
	netbsd-5-0-RELEASE:1.5
	netbsd-5-0-RC4:1.5
	netbsd-5-0-RC3:1.5
	netbsd-5-0-RC2:1.5
	jym-xensuspend:1.5.0.14
	jym-xensuspend-base:1.5
	netbsd-5-0-RC1:1.5
	netbsd-5:1.5.0.12
	netbsd-5-base:1.5
	mjf-devfs2:1.5.0.10
	mjf-devfs2-base:1.5
	yamt-pf42-base4:1.5
	yamt-pf42-base3:1.5
	hpcarm-cleanup-nbase:1.5
	yamt-pf42-base2:1.5
	yamt-pf42:1.5.0.8
	yamt-pf42-base:1.5
	keiichi-mipv6:1.5.0.6
	keiichi-mipv6-base:1.5
	cube-autoconf:1.5.0.4
	cube-autoconf-base:1.5
	hpcarm-cleanup:1.5.0.2
	hpcarm-cleanup-base:1.5
	netbsd-1-3-PATCH003:1.4
	netbsd-1-3-PATCH003-CANDIDATE2:1.4
	netbsd-1-3-PATCH003-CANDIDATE1:1.4
	netbsd-1-3-PATCH003-CANDIDATE0:1.4
	netbsd-1-3-PATCH002:1.4
	netbsd-1-3-PATCH001:1.4
	netbsd-1-3-RELEASE:1.4
	netbsd-1-3-BETA:1.4
	netbsd-1-3:1.4.0.2
	netbsd-1-3-base:1.4
	fsf-bc-1-04:1.1.1.2
	fsf:1.1.1
	netbsd-1-2-PATCH001:1.3
	netbsd-1-2-RELEASE:1.3
	netbsd-1-2-BETA:1.3
	netbsd-1-2-base:1.3
	netbsd-1-2:1.3.0.6
	netbsd-1-1-PATCH001:1.3
	netbsd-1-1-RELEASE:1.3
	netbsd-1-1:1.3.0.2
	netbsd-1-1-base:1.3
	bc-1-03:1.1.1.1
	GNU-bc-1-03:1.1.1
	netbsd-1-0-PATCH06:1.2
	netbsd-1-0-PATCH05:1.2
	netbsd-1-0-PATCH04:1.2
	netbsd-1-0-PATCH03:1.2
	netbsd-1-0-PATCH02:1.2
	netbsd-1-0-PATCH1:1.2
	netbsd-1-0-PATCH0:1.2
	netbsd-1-0-RELEASE:1.2
	netbsd-1-0:1.2.0.2
	netbsd-1-0-base:1.2
	netbsd-0-9-RELEASE:1.1
	netbsd-0-9-BETA:1.1
	netbsd-0-9-ALPHA2:1.1
	netbsd-0-9-ALPHA:1.1
	netbsd-0-9:1.1.0.2
	netbsd-0-9-base:1.1
	netbsd-0-8:1.1
	netbsd-alpha-1:1.1;
locks; strict;
comment	@ * @;


1.5
date	99.01.16.05.57.49;	author simonb;	state dead;
branches;
next	1.4;

1.4
date	97.04.29.00.29.20;	author phil;	state Exp;
branches;
next	1.3;

1.3
date	94.12.02.00.43.44;	author phil;	state Exp;
branches;
next	1.2;

1.2
date	93.08.02.17.25.45;	author mycroft;	state Exp;
branches;
next	1.1;

1.1
date	93.04.10.15.52.46;	author cgd;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	94.12.01.04.24.08;	author phil;	state Exp;
branches;
next	1.1.1.2;

1.1.1.2
date	97.04.29.00.11.23;	author phil;	state Exp;
branches;
next	;


desc
@@


1.5
log
@Update bc to 1.05a and dc to 1.2, which source in src/gnu/dist/bc.
@
text
@/* util.c: Utility routines for bc. */

/*  This file is part of GNU bc.
    Copyright (C) 1991, 1992, 1993, 1994, 1997 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
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    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, 675 Mass Ave, Cambridge, MA 02139, USA.

    You may contact the author by:
       e-mail:  phil@@cs.wwu.edu
      us-mail:  Philip A. Nelson
                Computer Science Department, 9062
                Western Washington University
                Bellingham, WA 98226-9062
       
*************************************************************************/


#include "bcdefs.h"
#ifndef VARARGS
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include "global.h"
#include "proto.h"


/* strcopyof mallocs new memory and copies a string to to the new
   memory. */

char *
strcopyof (str)
     char *str;
{
  char *temp;

  temp = (char *) bc_malloc (strlen (str)+1);
  return (strcpy (temp,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;
{ arg_list *temp;

  temp = (arg_list *) bc_malloc (sizeof (arg_list));
  temp->av_name = val;
  temp->arg_is_var = is_var;
  temp->next = args;
 
  return (temp);
}


/* For generate, we must produce a string in the form
    "val,val,...,val".  We also need a couple of static variables
   for retaining old generated strings.  It also uses a recursive
   function that builds the string. */

static char *arglist1 = NULL, *arglist2 = NULL;


/* make_arg_str does the actual construction of the argument string.
   ARGS is the pointer to the list and LEN is the maximum number of
   characters needed.  1 char is the minimum needed. 
 */

_PROTOTYPE (static char *make_arg_str, (arg_list *args, int len));

static char *
make_arg_str (args, len)
      arg_list *args;
      int len;
{
  char *temp;
  char sval[20];

  /* Recursive call. */
  if (args != NULL)
    temp = make_arg_str (args->next, len+12);
  else
    {
      temp = (char *) bc_malloc (len);
      *temp = 0;
      return temp;
    }

  /* Add the current number to the end of the string. */
  if (args->arg_is_var)
    if (len != 1) 
      sprintf (sval, "*%d,", args->av_name);
    else
      sprintf (sval, "*%d", args->av_name);
  else
    if (len != 1) 
      sprintf (sval, "%d,", args->av_name);
    else
      sprintf (sval, "%d", args->av_name);
  temp = strcat (temp, sval);
  return (temp);
}

char *
arg_str (args)
     arg_list *args;
{
  if (arglist2 != NULL) 
    free (arglist2);
  arglist2 = arglist1;
  arglist1 = make_arg_str (args, 1);
  return (arglist1);
}

char *
call_str (args)
     arg_list *args;
{
  arg_list *temp;
  int       arg_count;
  int       ix;
  
  if (arglist2 != NULL) 
    free (arglist2);
  arglist2 = arglist1;

  /* 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);
  for (temp = args, ix=0; temp != NULL; temp = temp->next)
    arglist1[ix++] = ( temp->av_name ? '1' : '0');
  arglist1[ix] = 0;
      
  return (arglist1);
}

/* free_args frees an argument list ARGS. */

void
free_args (args)
      arg_list *args;
{ 
  arg_list *temp;
 
  temp = args;
  while (temp != NULL)
    {
      args = args->next;
      free (temp);
      temp = args;
    }
}


/* Check for valid parameter (PARAMS) and auto (AUTOS) lists.
   There must be no duplicates any where.  Also, this is where
   warnings are generated for array parameters. */

void
check_params ( params, autos )
     arg_list *params, *autos;
{
  arg_list *tmp1, *tmp2;

  /* Check for duplicate parameters. */
  if (params != NULL)
    {
      tmp1 = params;
      while (tmp1 != NULL)
	{
	  tmp2 = tmp1->next;
	  while (tmp2 != NULL)
	    {
	      if (tmp2->av_name == tmp1->av_name) 
		yyerror ("duplicate parameter names");
	      tmp2 = tmp2->next;
	    }
	  if (tmp1->arg_is_var)
	    warn ("Variable array parameter");
	  tmp1 = tmp1->next;
	}
    }

  /* Check for duplicate autos. */
  if (autos != NULL)
    {
      tmp1 = autos;
      while (tmp1 != NULL)
	{
	  tmp2 = tmp1->next;
	  while (tmp2 != NULL)
	    {
	      if (tmp2->av_name == tmp1->av_name) 
		yyerror ("duplicate auto variable names");
	      tmp2 = tmp2->next;
	    }
	  if (tmp1->arg_is_var)
	    yyerror ("* not allowed here");
	  tmp1 = tmp1->next;
	}
    }

  /* Check for duplicate between parameters and autos. */
  if ((params != NULL) && (autos != NULL))
    {
      tmp1 = params;
      while (tmp1 != NULL)
	{
	  tmp2 = autos;
	  while (tmp2 != NULL)
	    {
	      if (tmp2->av_name == tmp1->av_name) 
		yyerror ("variable in both parameter and auto lists");
	      tmp2 = tmp2->next;
	    }
	  tmp1 = tmp1->next;
	}
    }
}


/* Initialize the code generator the parser. */

void
init_gen ()
{
  /* Get things ready. */
  break_label = 0;
  continue_label = 0;
  next_label  = 1;
  out_count = 2;
  if (compile_only) 
    printf ("@@i");
  else
    init_load ();
  had_error = FALSE;
  did_gen = FALSE;
}


/* generate code STR for the machine. */

void
generate (str)
      char *str;
{
  did_gen = TRUE;
  if (compile_only)
    {
      printf ("%s",str);
      out_count += strlen(str);
      if (out_count > 60)
	{
	  printf ("\n");
	  out_count = 0;
	}
    }
  else
    load_code (str);
}


/* Execute the current code as loaded. */

void
run_code()
{
  /* If no compile errors run the current code. */
  if (!had_error && did_gen)
    {
      if (compile_only)
	{
	  printf ("@@r\n"); 
	  out_count = 0;
	}
      else
	execute ();
    }

  /* Reinitialize the code generation and machine. */
  if (did_gen)
    init_gen();
  else
    had_error = FALSE;
}


/* Output routines: Write a character CH to the standard output.
   It keeps track of the number of characters output and may
   break the output with a "\<cr>".  Always used for numbers. */

void
out_char (ch)
     char ch;
{
  if (ch == '\n')
    {
      out_col = 0;
      putchar ('\n');
    }
  else
    {
      out_col++;
      if (out_col == line_size-1)
	{
	  putchar ('\\');
	  putchar ('\n');
	  out_col = 1;
	}
      putchar (ch);
    }
}

/* Output routines: Write a character CH to the standard output.
   It keeps track of the number of characters output and may
   break the output with a "\<cr>".  This one is for strings.
   In POSIX bc, strings are not broken across lines. */

void
out_schar (ch)
     char ch;
{
  if (ch == '\n')
    {
      out_col = 0;
      putchar ('\n');
    }
  else
    {
      if (!std_only)
	{
	  out_col++;
	  if (out_col == line_size-1)
	    {
	      putchar ('\\');
	      putchar ('\n');
	      out_col = 1;
	    }
	}
      putchar (ch);
    }
}


/* The following are "Symbol Table" routines for the parser. */

/*  find_id returns a pointer to node in TREE that has the correct
    ID.  If there is no node in TREE with ID, NULL is returned. */

id_rec *
find_id (tree, id)
     id_rec *tree;
     char   *id;
{
  int cmp_result;
  
  /* Check for an empty tree. */
  if (tree == NULL)
    return NULL;

  /* Recursively search the tree. */
  cmp_result = strcmp (id, tree->id);
  if (cmp_result == 0)
    return tree;  /* This is the item. */
  else if (cmp_result < 0)
    return find_id (tree->left, id);
  else
    return find_id (tree->right, id);  
}


/* insert_id_rec inserts a NEW_ID rec into the tree whose ROOT is
   provided.  insert_id_rec returns TRUE if the tree height from
   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;
{
  id_rec *A, *B;

  /* If root is NULL, this where it is to be inserted. */
  if (*root == NULL)
    {
      *root = new_id;
      new_id->left = NULL;
      new_id->right = NULL;
      new_id->balance = 0;
      return (TRUE);
    }

  /* We need to search for a leaf. */
  if (strcmp (new_id->id, (*root)->id) < 0)
    {
      /* Insert it on the left. */
      if (insert_id_rec (&((*root)->left), 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
	    {
	      /* 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
    {
      /* Insert it on the right. */
      if (insert_id_rec (&((*root)->right), 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)->right;
	      if (B->balance >= 0)
		{
		  /* Single Rotate. */
		  A->right = B->left;
		  B->left = A;
		  *root = B;
		  A->balance = 0;
		  B->balance = 0;
		}
	      else
		{
		  /* Double Rotate. */
		  *root = B->left;
		  B->left = (*root)->right;
		  A->right = (*root)->left;
		  (*root)->left = A;
		  (*root)->right = B;
		  switch ((*root)->balance)
		    {
		    case -1:
		      A->balance = 0;
		      B->balance = 1;
		      break;
		    case  0:
		      A->balance = 0;
		      B->balance = 0;
		      break;
		    case  1:
		      A->balance = -1;
		      B->balance = 0;
		      break;
		    }
		  (*root)->balance = 0;
		}
	    }     
	} 
    }
  
  /* If we fall through to here, the tree did not grow in height. */
  return (FALSE);
}


/* Initialize variables for the symbol table tree. */

void
init_tree()
{
  name_tree  = NULL;
  next_array = 1;
  next_func  = 1;
  /* 0 => ibase, 1 => obase, 2 => scale, 3 => history, 4 => last. */
  next_var   = 5;
}


/* Lookup routines for symbol table names. */

int
lookup (name, namekind)
     char *name;
     int  namekind;
{
  id_rec *id;

  /* Warn about non-standard name. */
  if (strlen(name) != 1)
    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->id = strcopyof (name);
      id->a_name = 0;
      id->f_name = 0;
      id->v_name = 0;
      insert_id_rec (&name_tree, id);
    }

  /* Return the correct value. */
  switch (namekind)
    {
      
    case ARRAY:
      /* ARRAY variable numbers are returned as negative numbers. */
      if (id->a_name != 0)
	{
	  free (name);
	  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 ();
	  return (-id->a_name);
	}
      yyerror ("Too many array variables");
      exit (1);

    case FUNCT:
    case FUNCTDEF:
      if (id->f_name != 0)
	{
	  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 ();
	  return (id->f_name);
	}
      yyerror ("Too many functions");
      exit (1);

    case SIMPLE:
      if (id->v_name != 0)
	{
	  free(name);
	  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 ();
	  return (id->v_name);
	}
      yyerror ("Too many variables");
      exit (1);
    }
}


/* 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 warranty information. */

void 
warranty(prefix)
     char *prefix;
{
  printf ("\n%s%s\n\n", prefix, BC_VERSION);
  printf ("%s%s%s%s%s%s%s%s%s%s%s",
"    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 the Free Software\n",
"    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
}

/* Print out the limits of this program. */

void
limits()
{
  printf ("BC_BASE_MAX     = %d\n",  BC_BASE_MAX);
  printf ("BC_DIM_MAX      = %ld\n", (long) BC_DIM_MAX);
  printf ("BC_SCALE_MAX    = %d\n",  BC_SCALE_MAX);
  printf ("BC_STRING_MAX   = %d\n",  BC_STRING_MAX);
  printf ("MAX Exponent    = %ld\n", (long) LONG_MAX);
  printf ("MAX code        = %ld\n", (long) BC_MAX_SEGS * (long) BC_SEG_SIZE);
  printf ("multiply digits = %ld\n", (long) LONG_MAX / (long) 90);
  printf ("Number of vars  = %ld\n", (long) MAX_STORE);
#ifdef OLD_EQ_OP
  printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
#endif 
}

/* 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;
{
  char *ptr;

  ptr = (char *) malloc (size);
  if (ptr == NULL)
    out_of_memory ();

  return ptr;
}


/* The following routines are error routines for various problems. */

/* Malloc could not get enought memory. */

void
out_of_memory()
{
  fprintf (stderr, "Fatal error: Out of memory for malloc.\n");
  exit (1);
}



/* The standard yyerror routine.  Built with variable number of argumnets. */

#ifndef VARARGS
#ifdef __STDC__
void
yyerror (char *str, ...)
#else
void
yyerror (str)
     char *str;
#endif
#else
void
yyerror (str, va_alist)
     char *str;
#endif
{
  char *name;
  va_list args;

#ifndef VARARGS   
   va_start (args, str);
#else
   va_start (args);
#endif
  if (is_std_in)
    name = "(standard_in)";
  else
    name = file_name;
  fprintf (stderr,"%s %d: ",name,line_no);
  vfprintf (stderr, str, args);
  fprintf (stderr, "\n");
  had_error = TRUE;
  va_end (args);
}


/* The routine to produce warnings about non-standard features
   found during parsing. */

#ifndef VARARGS
#ifdef __STDC__
void 
warn (char *mesg, ...)
#else
void
warn (mesg)
     char *mesg;
#endif
#else
void
warn (mesg, va_alist)
     char *mesg;
#endif
{
  char *name;
  va_list args;

#ifndef VARARGS   
  va_start (args, mesg);
#else
  va_start (args);
#endif
  if (std_only)
    {
      if (is_std_in)
	name = "(standard_in)";
      else
	name = file_name;
      fprintf (stderr,"%s %d: ",name,line_no);
      vfprintf (stderr, mesg, args);
      fprintf (stderr, "\n");
      had_error = TRUE;
    }
  else
    if (warn_not_std)
      {
	if (is_std_in)
	  name = "(standard_in)";
	else
	  name = file_name;
	fprintf (stderr,"%s %d: (Warning) ",name,line_no);
	vfprintf (stderr, mesg, args);
	fprintf (stderr, "\n");
      }
  va_end (args);
}

/* Runtime error will  print a message and stop the machine. */

#ifndef VARARGS
#ifdef __STDC__
void
rt_error (char *mesg, ...)
#else
void
rt_error (mesg)
     char *mesg;
#endif
#else
void
rt_error (mesg, va_alist)
     char *mesg;
#endif
{
  va_list args;
  char error_mesg [255];

#ifndef VARARGS   
  va_start (args, mesg);
#else
  va_start (args);
#endif
  vsprintf (error_mesg, mesg, args);
  va_end (args);
  
  fprintf (stderr, "Runtime error (func=%s, adr=%d): %s\n",
	   f_names[pc.pc_func], pc.pc_addr, error_mesg);
  runtime_error = TRUE;
}


/* A runtime warning tells of some action taken by the processor that
   may change the program execution but was not enough of a problem
   to stop the execution. */

#ifndef VARARGS
#ifdef __STDC__
void
rt_warn (char *mesg, ...)
#else
void
rt_warn (mesg)
     char *mesg;
#endif
#else
void
rt_warn (mesg, va_alist)
     char *mesg;
#endif
{
  va_list args;
  char error_mesg [255];

#ifndef VARARGS   
  va_start (args, mesg);
#else
  va_start (args);
#endif
  vsprintf (error_mesg, mesg, args);
  va_end (args);

  fprintf (stderr, "Runtime warning (func=%s, adr=%d): %s\n",
	   f_names[pc.pc_func], pc.pc_addr, error_mesg);
}
@


1.4
log
@Cleanup for import of bc-1.04.  Removing many files not needed for bc-1.04.
Cleanup here due to a major reorganization of fsf tree and the desire
to keep the NetBSD tree as clean as possible.
@
text
@@


1.3
log
@Updating to 1.03 with RCS added to most .[chyl] files
@
text
@a0 2
/* 	$NetBSD: $  */

d3 2
a4 2
/*  This file is part of bc written for MINIX.
    Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
d57 1
a57 1
nextarg (args, val)
d60 1
d65 1
d97 1
a97 1
    temp = make_arg_str (args->next, len+11);
d106 5
a110 2
  if (len != 1) 
    sprintf (sval, "%d,", args->av_name);
d112 4
a115 1
    sprintf (sval, "%d", args->av_name);
d195 2
a196 2
	  if (tmp1->av_name < 0)
	    warn ("Array parameter");
d214 2
d307 1
a307 1
   break the output with a "\<cr>". */
d321 1
a321 1
      if (out_col == 70)
d331 30
d532 2
a533 1
  next_var   = 4;  /* 0 => ibase, 1 => obase, 2 => scale, 3 => last. */
d676 1
a676 1
   have to do it!  SIZE is the number of types to allocate. */
d733 1
a733 1
    name = g_argv[optind-1];
d773 1
a773 1
	name = g_argv[optind-1];
d785 1
a785 1
	  name = g_argv[optind-1];
@


1.2
log
@Add RCS identifiers, remove some completely useless RCS logs and patchkit
headers, and a few other insignificant changes.
@
text
@d1 2
d6 1
a6 1
    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
a30 3
#ifndef lint
static char rcsid[] = "$Id: $";
#endif /* not lint */
d61 1
a61 1
     char val;
d82 2
a83 2
   characters needed.  1 char is the minimum needed. COMMAS tells
   if each number should be seperated by commas.*/
d85 1
a85 1
_PROTOTYPE (static char *make_arg_str, (arg_list *args, int len, int commas));
d88 1
a88 1
make_arg_str (args, len, commas)
a90 1
      int commas;
d97 1
a97 1
    temp = make_arg_str (args->next, len+11, commas);
d106 1
a106 1
  if (len != 1 && commas) 
d115 1
a115 1
arg_str (args, commas)
a116 1
     int commas;
d121 1
a121 1
  arglist1 = make_arg_str (args, 1, commas);
d125 22
d547 1
d551 3
@


1.1
log
@gnu bc.  necessary to compile the distribution
@
text
@d29 3
@


1.1.1.1
log
@Import of GNU bc-1.03
@
text
@d4 1
a4 1
    Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
d59 1
a59 1
     int val;
d80 2
a81 2
   characters needed.  1 char is the minimum needed. 
 */
d83 1
a83 1
_PROTOTYPE (static char *make_arg_str, (arg_list *args, int len));
d86 1
a86 1
make_arg_str (args, len)
d89 1
d96 1
a96 1
    temp = make_arg_str (args->next, len+11);
d105 1
a105 1
  if (len != 1) 
d114 1
a114 1
arg_str (args)
d116 1
d121 1
a121 1
  arglist1 = make_arg_str (args, 1);
a124 22
char *
call_str (args)
     arg_list *args;
{
  arg_list *temp;
  int       arg_count;
  int       ix;
  
  if (arglist2 != NULL) 
    free (arglist2);
  arglist2 = arglist1;

  /* 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);
  for (temp = args, ix=0; temp != NULL; temp = temp->next)
    arglist1[ix++] = ( temp->av_name ? '1' : '0');
  arglist1[ix] = 0;
      
  return (arglist1);
}
a524 1
    case FUNCTDEF:
a527 3
	  /* 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++;
@


1.1.1.2
log
@Updating to version 1.04.
@
text
@d3 2
a4 2
/*  This file is part of GNU bc.
    Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
d57 1
a57 1
nextarg (args, val, is_var)
a59 1
     int is_var;
a63 1
  temp->arg_is_var = is_var;
d95 1
a95 1
    temp = make_arg_str (args->next, len+12);
d104 2
a105 5
  if (args->arg_is_var)
    if (len != 1) 
      sprintf (sval, "*%d,", args->av_name);
    else
      sprintf (sval, "*%d", args->av_name);
d107 1
a107 4
    if (len != 1) 
      sprintf (sval, "%d,", args->av_name);
    else
      sprintf (sval, "%d", args->av_name);
d187 2
a188 2
	  if (tmp1->arg_is_var)
	    warn ("Variable array parameter");
a205 2
	  if (tmp1->arg_is_var)
	    yyerror ("* not allowed here");
d297 1
a297 1
   break the output with a "\<cr>".  Always used for numbers. */
d311 1
a311 1
      if (out_col == line_size-1)
a320 30
/* Output routines: Write a character CH to the standard output.
   It keeps track of the number of characters output and may
   break the output with a "\<cr>".  This one is for strings.
   In POSIX bc, strings are not broken across lines. */

void
out_schar (ch)
     char ch;
{
  if (ch == '\n')
    {
      out_col = 0;
      putchar ('\n');
    }
  else
    {
      if (!std_only)
	{
	  out_col++;
	  if (out_col == line_size-1)
	    {
	      putchar ('\\');
	      putchar ('\n');
	      out_col = 1;
	    }
	}
      putchar (ch);
    }
}

d492 1
a492 2
  /* 0 => ibase, 1 => obase, 2 => scale, 3 => history, 4 => last. */
  next_var   = 5;
d635 1
a635 1
   have to do it!  SIZE is the number of bytes to allocate. */
d692 1
a692 1
    name = file_name;
d732 1
a732 1
	name = file_name;
d744 1
a744 1
	  name = file_name;
@
