Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updating to version 1.04.

  • Loading branch information...
commit 287b2c6a0f4f1f7827439e3cf9f4f3a6b1650815 1 parent 0ec25f8
phil authored
View
14 gnu/usr.bin/bc/Makefile
@@ -1,13 +1,19 @@
-# $Id: Makefile,v 1.1.1.1 1994/12/01 04:24:14 phil Exp $
+# $NetBSD: Makefile,v 1.1.1.2 1997/04/29 00:11:10 phil Exp $
PROG= bc
-CFLAGS+=-D_POSIX_SOURCE -DDOT_IS_LAST -I. -I${.CURDIR}
+CFLAGS+=-D_POSIX_SOURCE -I. -I${.CURDIR}
LFLAGS+=-I8
-SRCS= bc.c scan.c util.c main.c number.c storage.c load.c execute.c global.c
+SRCS= bc.c scan.c util.c main.c number.c storage.c load.c execute.c \
+ global.c getopt.c getopt1.c
LDADD+= -ll
DPADD+= ${LIBL}
-CLEANFILES+= bc.c scan.c y.tab.h
+CLEANFILES+= bc.c scan.c bc.h
+
+bc.c bc.h: bc.y
+ $(YACC) -d bc.y
+ mv y.tab.c bc.c
+ mv y.tab.h bc.h
.include <bsd.prog.mk>
View
15 gnu/usr.bin/bc/README.NetBSD
@@ -1,8 +1,13 @@
-This is GNU bc 1.03.
+This is GNU bc 1.04.
+
+The full distribution of GNU bc-1.04 may be found at any GNU software
+archive. The master copy is at ftp://prep.ai.mit.edu/pub/gnu/bc-1.04.tar.gz.
+
+Not everything included in the full bc-1.04 distribution is included.
+The files included here are only the needed files for building bc on
+NetBSD. Their location in the NetBSD tree are different than in the
+original bc-1.04 source tree.
+
-The original GNU distribution included GNU dc in the same distribution.
-GNU dc part is found in the NetBSD source tree in /usr/src/gnu/usr.bin/dc.
-With all the files located in the bc and dc directories, an "original"
-bc-1.03 distribution could be regenerated. (It require GNU autoconf 2.0.)
View
82 gnu/usr.bin/bc/bc.1
@@ -1,8 +1,8 @@
.\"
.\" bc.1 - the *roff document processor source for the bc manual
.\"
-.\" This file is part of bc written initially for MINIX.
-.\" Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+.\" 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
@@ -26,13 +26,13 @@
.\" Bellingham, WA 98226-9062
.\"
.\"
-.TH bc 1 .\" "Command Manual" v1.03 "Nov 2, 1994"
+.TH bc 1 .\" "Command Manual" v1.04 "June 22, 1995"
.SH NAME
bc - An arbitrary precision calculator language
.SH SYNTAX
-\fBbc\fR [ \fB-lws\fR ] [ \fI file ...\fR ]
+\fBbc\fR [ \fB-lwsqv\fR ] [long-options] [ \fI file ...\fR ]
.SH VERSION
-This man page documents GNU bc version 1.03.
+This man page documents GNU bc version 1.04.
.SH DESCRIPTION
\fBbc\fR is a language that supports arbitrary precision numbers
with interactive execution of statements. There are some similarities
@@ -58,6 +58,20 @@ Define the standard math library.
Give warnings for extensions to POSIX \fBbc\fR.
.IP -s
Process exactly the POSIX \fBbc\fR language.
+.IP -q
+Do not print the normal GNU bc welcome.
+.IP -v
+Print the version number and copyright and quit.
+.IP --mathlib
+Define the standard math library.
+.IP --warn
+Give warnings for extensions to POSIX \fBbc\fR.
+.IP --standard
+Process exactly the POSIX \fBbc\fR language.
+.IP --quiet
+Do not print the normal GNU bc welcome.
+.IP --version
+Print the version number and copyright and quit.
.SS NUMBERS
The most basic element in \fBbc\fR is the number. Numbers are
arbitrary precision numbers. This precision is both in the integer
@@ -99,6 +113,11 @@ single space in the input. (This causes comments to delimit other
input items. For example, a comment can not be found in the middle of
a variable name.) Comments include any newlines (end of line) between
the start and the end of the comment.
+.PP
+To support the use of scripts for \fBbc\fR, a single line comment has been
+added as an extension. A single line comment starts at a \fB#\fR
+character and continues to the next end of the line. The end of line
+character is not part of the comment and is processed normally.
.SS EXPRESSIONS
The numbers are manipulated by expressions and statements. Since
the language was designed to be interactive, statements and expressions
@@ -109,7 +128,7 @@ detail later, are defined when encountered.)
A simple expression is just a constant. \fBbc\fR converts constants
into internal decimal numbers using the current input base, specified
by the variable \fBibase\fR. (There is an exception in functions.)
-The legal values of \fBibase\fR are 2 through 16 (F). Assigning a
+The legal values of \fBibase\fR are 2 through 16. Assigning a
value outside this range to \fBibase\fR will result in a value of 2
or 16. Input numbers may contain the characters 0-9 and A-F. (Note:
They must be capitals. Lower case letters are variable names.)
@@ -339,7 +358,7 @@ Any other character following the backslash will be ignored.
.IP "{ statement_list }"
This is the compound statement. It allows multiple statements to be
grouped together for execution.
-.IP "\fBif\fR ( expression ) \fBthen\fR statement1 [\fBelse\fR statement2]"
+.IP "\fBif\fR ( expression ) statement1 [\fBelse\fR statement2]"
The if statement evaluates the expression and executes statement1 or
statement2 depending on the value of the expression. If the expression
is non-zero, statement1 is executed. If statement2 is present and
@@ -431,7 +450,7 @@ A runtime error will also occur for the call to an undefined function.
.PP
The \fIauto_list\fR is an optional list of variables that are for
"local" use. The syntax of the auto list (if present) is "\fBauto
-\fIname \fR, ... ;". (The semicolon is optional.) Each \fIname\fR is
+\fIname\fR, ... ;". (The semicolon is optional.) Each \fIname\fR is
the name of an auto variable. Arrays may be specified by using the
same notation as used in parameters. These variables have their
values pushed onto a stack at the start of the function. The
@@ -468,11 +487,11 @@ and the default scale is set to 20. The math functions will calculate their
results to the scale set at the time of their call.
The math library defines the following functions:
.IP "s (\fIx\fR)"
-The sine of x in radians.
+The sine of x, x is in radians.
.IP "c (\fIx\fR)"
-The cosine of x in radians.
+The cosine of x, x is in radians.
.IP "a (\fIx\fR)"
-The arctangent of x.
+The arctangent of x, arctangent returns radians.
.IP "l (\fIx\fR)"
The natural logarithm of x.
.IP "e (\fIx\fR)"
@@ -575,6 +594,19 @@ define f (x) {
\fR
.RE
.fi
+.SS READLINE OPTION
+GNU \fBbc\fR can be compiled (via a configure option) to use the
+GNU \fBreadline\fR input editor library. This allows the user
+to do more editing of lines before sending them to \fBbc\fR.
+It also allows for a history of previous lines typed. When this
+option is selected, \fBbc\fR has one more special variable.
+This special variable, \fBhistory\fR is the number of lines of
+history retained. A value of -1 means that an unlimited number
+of history lines are retained. This is the default value.
+Setting the value of \fBhistory\fR to a positive number restricts
+the number of history lines to the number given. The value of
+0 disables the history feature. For more information, read the
+user manuals for the GNU \fBreadline\fR and \fBhistory\fR libraries.
.SS DIFFERENCES
This version of
.B bc
@@ -626,8 +658,11 @@ POSIX \fBbc\fR does not have a print statement .
.IP "continue statement"
POSIX \fBbc\fR does not have a continue statement.
.IP "array parameters"
-POSIX \fBbc\fR does not have array parameters. Other implementations
-of \fBbc\fR may have call by value array parameters.
+POSIX \fBbc\fR does not (currently) support array parameters in full.
+The POSIX grammar allows for arrays in function definitions, but does
+not provide a method to specify an array as an actual parameter. (This
+is most likely an oversight in the grammar.) Traditional implementations
+of \fBbc\fR have only call by value array parameters.
.IP "=+, =-, =*, =/, =%, =^"
POSIX \fBbc\fR does not require these "old style" assignment operators to
be defined. This version may allow these "old style" assignments. Use
@@ -708,6 +743,23 @@ to have more than 16 segments of 1024 bytes.
.IP "variable names"
The current limit on the number of unique names is 32767 for each of
simple variables, arrays and functions.
+.SH ENVIRONMENT VARIABLES
+The following environment variables are processed by \fBbc\fR:
+.IP "POSIXLY_CORRECT"
+This is the same as the \fB-s\fR option.
+.IP "BC_ENV_ARGS"
+This is another mechanism to get arguments to \fBbc\fR. The
+format is the same as the command line arguments. These arguments
+are processed first, so any files listed in the environent arguments
+are processed before any command line argument files. This allows
+the user to set up "standard" options and files to be processed
+at every invocation of \fBbc\fR. The files in the environment
+variables would typically contain function definitions for functions
+the user wants defined every time \fBbc\fR is run.
+.IP "BC_LINE_LENGTH"
+This should be an integer specifing the number of characters in an
+output line for numbers. This includes the backslash and newline characters
+for long numbers.
.SH FILES
In most installations, \fBbc\fR is completely self-contained.
Where executable size is of importance or the C compiler does
@@ -720,6 +772,10 @@ that the file is unavailable and terminate. Also, there are compile
and run time diagnostics that should be self-explanatory.
.SH BUGS
Error recovery is not very good yet.
+.PP
+Email bug reports to
+.BR bug-gnu-utils@prep.ai.mit.edu .
+Be sure to include the word ``bc'' somewhere in the ``Subject:'' field.
.SH AUTHOR
.nf
Philip A. Nelson
View
94 gnu/usr.bin/bc/bc.y
@@ -2,8 +2,8 @@
/* bc.y: The grammar for a POSIX compatable bc processor with some
extensions to the language. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -64,26 +64,26 @@
%token <i_value> NEWLINE AND OR NOT
%token <s_value> STRING NAME NUMBER
/* '-', '+' are tokens themselves */
-%token <c_value> MUL_OP
-/* '*', '/', '%' */
-%token <c_value> ASSIGN_OP
/* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
-%token <s_value> REL_OP
+%token <c_value> ASSIGN_OP
/* '==', '<=', '>=', '!=', '<', '>' */
-%token <c_value> INCR_DECR
+%token <s_value> REL_OP
/* '++', '--' */
-%token <i_value> Define Break Quit Length
+%token <c_value> INCR_DECR
/* 'define', 'break', 'quit', 'length' */
-%token <i_value> Return For If While Sqrt Else
+%token <i_value> Define Break Quit Length
/* 'return', 'for', 'if', 'while', 'sqrt', 'else' */
-%token <i_value> Scale Ibase Obase Auto Read
+%token <i_value> Return For If While Sqrt Else
/* 'scale', 'ibase', 'obase', 'auto', 'read' */
-%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
+%token <i_value> Scale Ibase Obase Auto Read
/* 'warranty', 'halt', 'last', 'continue', 'print', 'limits' */
+%token <i_value> Warranty, Halt, Last, Continue, Print, Limits
+/* 'history' */
+%token <i_value> UNARY_MINUS History
/* Types of all other things. */
%type <i_value> expression return_expression named_expression opt_expression
-%type <c_value> '+' '-'
+%type <c_value> '+' '-' '*' '/' '%'
%type <a_value> opt_parameter_list opt_auto_define_list define_list
%type <a_value> opt_argument_list argument_list
%type <i_value> program input_item semicolon_list statement_list
@@ -96,7 +96,7 @@
%left REL_OP
%right ASSIGN_OP
%left '+' '-'
-%left MUL_OP
+%left '*' '/' '%'
%right '^'
%nonassoc UNARY_MINUS
%nonassoc INCR_DECR
@@ -105,7 +105,7 @@
program : /* empty */
{
$$ = 0;
- if (interactive)
+ if (interactive && !quiet)
{
printf ("%s\n", BC_VERSION);
welcome ();
@@ -123,6 +123,10 @@ input_item : semicolon_list NEWLINE
init_gen ();
}
;
+opt_newline : /* empty */
+ | NEWLINE
+ { warn ("newline not allowed"); }
+ ;
semicolon_list : /* empty */
{ $$ = 0; }
| statement_or_error
@@ -227,7 +231,7 @@ statement : Warranty
sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
generate (genstr);
}
- statement
+ opt_newline statement
{
sprintf (genstr, "J%1d:N%1d:",
continue_label, break_label);
@@ -242,7 +246,7 @@ statement : Warranty
sprintf (genstr, "Z%1d:", if_label);
generate (genstr);
}
- statement opt_else
+ opt_newline statement opt_else
{
sprintf (genstr, "N%1d:", if_label);
generate (genstr);
@@ -261,7 +265,7 @@ statement : Warranty
sprintf (genstr, "Z%1d:", break_label);
generate (genstr);
}
- ')' statement
+ ')' opt_newline statement
{
sprintf (genstr, "J%1d:N%1d:", $1, break_label);
generate (genstr);
@@ -294,18 +298,18 @@ opt_else : /* nothing */
generate (genstr);
if_label = $1;
}
- statement
-function : Define NAME '(' opt_parameter_list ')' '{'
- NEWLINE opt_auto_define_list
+ opt_newline statement
+function : Define NAME '(' opt_parameter_list ')' opt_newline
+ '{' NEWLINE opt_auto_define_list
{
/* Check auto list against parameter list? */
- check_params ($4,$8);
+ check_params ($4,$9);
sprintf (genstr, "F%d,%s.%s[",
lookup($2,FUNCTDEF),
- arg_str ($4), arg_str ($8));
+ arg_str ($4), arg_str ($9));
generate (genstr);
free_args ($4);
- free_args ($8);
+ free_args ($9);
$1 = next_label;
next_label = 1;
}
@@ -327,13 +331,17 @@ opt_auto_define_list : /* empty */
{ $$ = $2; }
;
define_list : NAME
- { $$ = nextarg (NULL, lookup ($1,SIMPLE)); }
+ { $$ = nextarg (NULL, lookup ($1,SIMPLE), FALSE);}
| NAME '[' ']'
- { $$ = nextarg (NULL, lookup ($1,ARRAY)); }
+ { $$ = nextarg (NULL, lookup ($1,ARRAY), FALSE); }
+ | '*' NAME '[' ']'
+ { $$ = nextarg (NULL, lookup ($2,ARRAY), TRUE); }
| define_list ',' NAME
- { $$ = nextarg ($1, lookup ($3,SIMPLE)); }
+ { $$ = nextarg ($1, lookup ($3,SIMPLE), FALSE); }
| define_list ',' NAME '[' ']'
- { $$ = nextarg ($1, lookup ($3,ARRAY)); }
+ { $$ = nextarg ($1, lookup ($3,ARRAY), FALSE); }
+ | define_list ',' '*' NAME '[' ']'
+ { $$ = nextarg ($1, lookup ($4,ARRAY), TRUE); }
;
opt_argument_list : /* empty */
{ $$ = NULL; }
@@ -342,24 +350,24 @@ opt_argument_list : /* empty */
argument_list : expression
{
if ($1 > 1) warn ("comparison in argument");
- $$ = nextarg (NULL,0);
+ $$ = nextarg (NULL,0,FALSE);
}
| NAME '[' ']'
{
sprintf (genstr, "K%d:", -lookup ($1,ARRAY));
generate (genstr);
- $$ = nextarg (NULL,1);
+ $$ = nextarg (NULL,1,FALSE);
}
| argument_list ',' expression
{
if ($3 > 1) warn ("comparison in argument");
- $$ = nextarg ($1,0);
+ $$ = nextarg ($1,0,FALSE);
}
| argument_list ',' NAME '[' ']'
{
sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
generate (genstr);
- $$ = nextarg ($1,1);
+ $$ = nextarg ($1,1,FALSE);
}
;
opt_expression : /* empty */
@@ -480,11 +488,19 @@ expression : named_expression ASSIGN_OP
generate ("-");
$$ = $1 | $3;
}
- | expression MUL_OP expression
+ | expression '*' expression
{
- genstr[0] = $2;
- genstr[1] = 0;
- generate (genstr);
+ generate ("*");
+ $$ = $1 | $3;
+ }
+ | expression '/' expression
+ {
+ generate ("/");
+ $$ = $1 | $3;
+ }
+ | expression '%' expression
+ {
+ generate ("%");
$$ = $1 | $3;
}
| expression '^' expression
@@ -607,9 +623,15 @@ named_expression : NAME
{ $$ = 1; }
| Scale
{ $$ = 2; }
- | Last
+ | History
{ $$ = 3;
+ warn ("History variable");
+ }
+ | Last
+ { $$ = 4;
warn ("Last variable");
}
;
+
%%
+
View
24 gnu/usr.bin/bc/bcdefs.h
@@ -1,7 +1,7 @@
/* bcdefs.h: The single file to include all constants and type definitions. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -38,7 +38,7 @@
#else
#include <string.h>
#endif
-#ifndef NO_LIMITS
+#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -64,16 +64,19 @@ typedef struct bc_label_group
struct bc_label_group *l_next;
} bc_label_group;
-
-/* Each function has its own code segments and labels. There can be
- no jumps between functions so labels are unique to a function. */
+/* Argument list. Recorded in the function so arguments can
+ be checked at call time. */
typedef struct arg_list
{
int av_name;
+ int arg_is_var; /* Extension ... variable parameters. */
struct arg_list *next;
} arg_list;
+/* Each function has its own code segments and labels. There can be
+ no jumps between functions so labels are unique to a function. */
+
typedef struct
{
char f_defined; /* Is this function defined yet. */
@@ -152,3 +155,12 @@ typedef struct id_rec {
short balance; /* For the balanced tree. */
struct id_rec *left, *right; /* Tree pointers. */
} id_rec;
+
+
+/* A list of files to process. */
+
+typedef struct file_node {
+ char *name;
+ struct file_node *next;
+} file_node;
+
View
26 gnu/usr.bin/bc/config.h
@@ -4,6 +4,12 @@
/* Define to empty if the keyword does not work. */
/* #undef const */
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
/* Define if on MINIX. */
/* #undef _MINIX */
@@ -20,11 +26,29 @@
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* PACKAGE name */
+#define PACKAGE "bc"
+
+/* Package VERSION number */
+#define VERSION "1.04"
+
/* define if the math lib is to be loaded from a file. */
/* #undef BC_MATH_FILE */
+/* Define to use the readline library. */
+/* #undef READLINE */
+
+/* Define to `size_t' if <sys/types.h> and <stddef.h> don't define. */
+/* #undef ptrdiff_t */
+
/* Define if you have the isgraph function. */
-/* #undef HAVE_ISGRAPH */
+#define HAVE_ISGRAPH 1
+
+/* Define if you have the <lib.h> header file. */
+/* #undef HAVE_LIB_H */
/* Define if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
View
16 gnu/usr.bin/bc/const.h
@@ -1,7 +1,7 @@
/* const.h: Constants for bc. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -29,8 +29,10 @@
/* Define INT_MAX and LONG_MAX if not defined. Assuming 32 bits... */
-#ifdef NO_LIMITS
+#ifndef INT_MAX
#define INT_MAX 0x7FFFFFFF
+#endif
+#ifndef LONG_MAX
#define LONG_MAX 0x7FFFFFFF
#endif
@@ -38,6 +40,14 @@
/* Define constants in some reasonable size. The next 4 constants are
POSIX constants. */
+#ifdef BC_BASE_MAX
+ /* <limits.h> on a POSIX.2 system may have defined these. Override. */
+# undef BC_BASE_MAX
+# undef BC_SCALE_MAX
+# undef BC_STRING_MAX
+# undef BC_DIM_MAX
+#endif
+
#define BC_BASE_MAX INT_MAX
#define BC_SCALE_MAX INT_MAX
#define BC_STRING_MAX INT_MAX
View
47 gnu/usr.bin/bc/execute.c
@@ -1,7 +1,7 @@
/* execute.c - run a bc program. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -206,25 +206,25 @@ execute ()
case 'O' : /* Write a string to the output with processing. */
while ((ch = byte(&pc)) != '"')
if (ch != '\\')
- out_char (ch);
+ out_schar (ch);
else
{
ch = byte(&pc);
if (ch == '"') break;
switch (ch)
{
- case 'a': out_char (007); break;
- case 'b': out_char ('\b'); break;
- case 'f': out_char ('\f'); break;
- case 'n': out_char ('\n'); break;
- case 'q': out_char ('"'); break;
- case 'r': out_char ('\r'); break;
- case 't': out_char ('\t'); break;
- case '\\': out_char ('\\'); break;
+ case 'a': out_schar (007); break;
+ case 'b': out_schar ('\b'); break;
+ case 'f': out_schar ('\f'); break;
+ case 'n': out_schar ('\n'); break;
+ case 'q': out_schar ('"'); break;
+ case 'r': out_schar ('\r'); break;
+ case 't': out_schar ('\t'); break;
+ case '\\': out_schar ('\\'); break;
default: break;
}
}
- if (interactive) fflush (stdout);
+ fflush (stdout);
break;
case 'R' : /* Return from function */
@@ -258,8 +258,9 @@ execute ()
case 'P' : /* Write the value on the top of the stack. No newline. */
out_num (ex_stack->s_num, o_base, out_char);
if (inst == 'W') out_char ('\n');
- store_var (3); /* Special variable "last". */
- if (interactive) fflush (stdout);
+ store_var (4); /* Special variable "last". */
+ fflush (stdout);
+ pop ();
break;
case 'c' : /* Call special function. */
@@ -318,7 +319,7 @@ execute ()
break;
case 'n' : /* Negate top of stack. */
- bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num);
+ bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num, 0);
break;
case 'p' : /* Pop the execution stack. */
@@ -333,8 +334,8 @@ execute ()
break;
case 'w' : /* Write a string to the output. */
- while ((ch = byte(&pc)) != '"') out_char (ch);
- if (interactive) fflush (stdout);
+ while ((ch = byte(&pc)) != '"') out_schar (ch);
+ fflush (stdout);
break;
case 'x' : /* Exchange Top of Stack with the one under the tos. */
@@ -381,7 +382,7 @@ execute ()
case '+' : /* add */
if (check_stack(2))
{
- bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num);
+ bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
pop();
pop();
push_num (temp_num);
@@ -392,7 +393,7 @@ execute ()
case '-' : /* subtract */
if (check_stack(2))
{
- bc_sub (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num);
+ bc_sub (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num, 0);
pop();
pop();
push_num (temp_num);
@@ -646,7 +647,7 @@ push_constant (in_char, conv_base)
if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
bc_multiply (build, mult, &result, 0);
int2num (&temp, (int) in_ch);
- bc_add (result, temp, &build);
+ bc_add (result, temp, &build, 0);
in_ch = in_char();
}
if (in_ch == '.')
@@ -662,19 +663,19 @@ push_constant (in_char, conv_base)
{
bc_multiply (result, mult, &result, 0);
int2num (&temp, (int) in_ch);
- bc_add (result, temp, &result);
+ bc_add (result, temp, &result, 0);
bc_multiply (divisor, mult, &divisor, 0);
digits++;
in_ch = in_char();
if (in_ch < 16 && in_ch >= conv_base) in_ch = conv_base-1;
}
bc_divide (result, divisor, &result, digits);
- bc_add (build, result, &build);
+ bc_add (build, result, &build, 0);
}
/* Final work. */
if (negative)
- bc_sub (_zero_, build, &build);
+ bc_sub (_zero_, build, &build, 0);
push_num (build);
free_num (&temp);
View
4 gnu/usr.bin/bc/global.c
@@ -1,7 +1,7 @@
/* global.c: This defines the global variables. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
View
48 gnu/usr.bin/bc/global.h
@@ -1,7 +1,7 @@
/* global.h: The global variables for bc. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -53,16 +53,28 @@ EXTERN char did_gen;
EXTERN char interactive;
/* Just generate the byte code. -c flag. */
-EXTERN char compile_only;
+EXTERN int compile_only;
/* Load the standard math functions. -l flag. */
-EXTERN char use_math;
+EXTERN int use_math;
/* Give a warning on use of any non-standard feature (non-POSIX). -w flag. */
-EXTERN char warn_not_std;
+EXTERN int warn_not_std;
/* Accept POSIX bc only! -s flag. */
-EXTERN char std_only;
+EXTERN int std_only;
+
+/* Don't print the banner at start up. -q flag. */
+EXTERN int quiet;
+
+/* The list of file names to process. */
+EXTERN file_node *file_names;
+
+/* The name of the current file being processed. */
+EXTERN char *file_name;
+
+/* Is the current file a named file or standard input? */
+EXTERN char is_std_in;
/* global variables for the bc machine. All will be dynamic in size.*/
/* Function storage. main is (0) and functions (1-f_count) */
@@ -89,15 +101,30 @@ EXTERN estack_rec *ex_stack;
/* Function return stack. */
EXTERN fstack_rec *fn_stack;
-/* Other "storage". */
+/* Current ibase, obase, scale, and n_history (if needed). */
EXTERN int i_base;
EXTERN int o_base;
EXTERN int scale;
+#ifdef READLINE
+EXTERN int n_history;
+#endif
+
+/* "Condition code" -- false (0) or true (1) */
EXTERN char c_code;
-EXTERN int out_col;
+
+/* Records the number of the runtime error. */
EXTERN char runtime_error;
+
+/* Holds the current location of execution. */
EXTERN program_counter pc;
+/* For POSIX bc, this is just for number output, not strings. */
+EXTERN int out_col;
+
+/* Keeps track of the current number of characters per output line.
+ This includes the \n at the end of the line. */
+EXTERN int line_size;
+
/* Input Line numbers and other error information. */
EXTERN int line_no;
EXTERN int had_error;
@@ -111,11 +138,6 @@ EXTERN int next_var;
EXTERN id_rec *name_tree;
-/* For error message production */
-EXTERN char **g_argv;
-EXTERN int g_argc;
-EXTERN char is_std_in;
-
/* defined in number.c */
extern bc_num _zero_;
extern bc_num _one_;
View
8 gnu/usr.bin/bc/libmath.b
@@ -1,7 +1,7 @@
-/* libmath.b for bc for minix. */
+/* libmath.b for GNU bc. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+/* This file is part of GNU bc.
+ Copyright (C) 1991, 1992, 1993, 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
@@ -90,7 +90,7 @@ define l(x) {
auto e, f, i, m, n, v, z
/* return something for the special case. */
- if (x <= 0) return (1 - 10^scale)
+ if (x <= 0) return ((1 - 10^scale)/1)
/* Precondition x to make .5 < x < 2.0. */
z = scale;
View
74 gnu/usr.bin/bc/libmath.h
@@ -1,40 +1,40 @@
"@iK20:s2:p@r\
-@iF1,4.5,6,7,8,9,10,11,12,13[l4:0<Z1:1s10:pl4:ns4:pN1:l2:s13:\
-pK6:l13:+K.44:l4:*+s11:pl4:cS1+s2:pN2:l4:1>Z3:l8:1+s8:pl4:K2:\
-/s4:pl2:1+s2:pJ2:N3:l11:s2:p1l4:+s12:pl4:s5:p1s6:pK2:s9:pN5:1\
-B6:J4:N7:l9:i9:pJ5:N6:l5:l4:*s5:l6:l9:*s6:/s7:pl7:0=Z8:l8:0>Z9:\
-N10:l8:d8:Z11:l12:l12:*s12:pJ10:N11:N9:l13:s2:pl10:Z12:1l12:/\
-RN12:l12:1/RN8:l12:l7:+s12:pJ7:N4:0R]@r\
-@iF2,4.7,8,9,10,11,12,13[l4:0{Z1:1K10:l2:^-RN1:l2:s13:pK6:l2:\
-+s2:pK2:s8:p0s9:pN2:l4:K2:}Z3:l8:K2:*s8:pl4:cRs4:pJ2:N3:N4:l4:\
-K.5:{Z5:l8:K2:*s8:pl4:cRs4:pJ4:N5:l4:1-l4:1+/s11:s12:pl11:l11:\
-*s10:pK3:s9:pN7:1B8:J6:N9:l9:K2:+s9:pJ7:N8:l11:l10:*s11:l9:/s7:\
-pl7:0=Z10:l8:l12:*s12:pl13:s2:pl12:1/RN10:l12:l7:+s12:pJ9:N6:\
-0R]@r\
-@iF3,4.7,9,10,11,14,12,13[l2:s13:pK1.1:l13:*K2:+s2:p1C4,0:s12:\
-pl4:0<Z1:1s10:pl4:ns4:pN1:0s2:pl4:l12:/K2:+K4:/s11:pl4:K4:l11:\
-*l12:*-s4:pl11:K2:%Z2:l4:ns4:pN2:l13:K2:+s2:pl4:s7:s12:pl4:nl4:\
-*s14:pK3:s9:pN4:1B5:J3:N6:l9:K2:+s9:pJ4:N5:l7:l14:l9:l9:1-*/*\
-s7:pl7:0=Z7:l13:s2:pl10:Z8:l12:n1/RN8:l12:1/RN7:l12:l7:+s12:p\
-J6:N3:0R]@r\
-@iF5,4.12[l2:1+s2:pl4:1C4,0:K2:*+C3,0:s12:pl2:1-s2:pl12:1/R0R]\
+@iF1,5.6,7,8,9,10,11,12,13,14[l5:0<Z1:1s11:pl5:ns5:pN1:l2:s14:\
+pK6:l14:+K.44:l5:*+s12:pl5:cS1+s2:pN2:l5:1>Z3:l9:1+s9:pl5:K2:\
+/s5:pl2:1+s2:pJ2:N3:l12:s2:p1l5:+s13:pl5:s6:p1s7:pK2:s10:pN5:\
+1B6:J4:N7:l10:i10:pJ5:N6:l6:l5:*s6:l7:l10:*s7:/s8:pl8:0=Z8:l9:\
+0>Z9:N10:l9:d9:Z11:l13:l13:*s13:pJ10:N11:N9:l14:s2:pl11:Z12:1\
+l13:/RN12:l13:1/RN8:l13:l8:+s13:pJ7:N4:0R]@r\
+@iF2,5.8,9,10,11,12,13,14[l5:0{Z1:1K10:l2:^-1/RN1:l2:s14:pK6:\
+l2:+s2:pK2:s9:p0s10:pN2:l5:K2:}Z3:l9:K2:*s9:pl5:cRs5:pJ2:N3:N4:\
+l5:K.5:{Z5:l9:K2:*s9:pl5:cRs5:pJ4:N5:l5:1-l5:1+/s12:s13:pl12:\
+l12:*s11:pK3:s10:pN7:1B8:J6:N9:l10:K2:+s10:pJ7:N8:l12:l11:*s12:\
+l10:/s8:pl8:0=Z10:l9:l13:*s13:pl14:s2:pl13:1/RN10:l13:l8:+s13:\
+pJ9:N6:0R]@r\
+@iF3,5.8,10,11,12,15,13,14[l2:s14:pK1.1:l14:*K2:+s2:p1C4,0:s13:\
+pl5:0<Z1:1s11:pl5:ns5:pN1:0s2:pl5:l13:/K2:+K4:/s12:pl5:K4:l12:\
+*l13:*-s5:pl12:K2:%Z2:l5:ns5:pN2:l14:K2:+s2:pl5:s8:s13:pl5:nl5:\
+*s15:pK3:s10:pN4:1B5:J3:N6:l10:K2:+s10:pJ4:N5:l8:l15:l10:l10:\
+1-*/*s8:pl8:0=Z7:l14:s2:pl11:Z8:l13:n1/RN8:l13:1/RN7:l13:l8:+\
+s13:pJ6:N3:0R]@r\
+@iF5,5.13[l2:1+s2:pl5:1C4,0:K2:*+C3,0:s13:pl2:1-s2:pl13:1/R0R]\
@r\
-@iF4,4.5,7,8,9,10,11,14,12,13[1s10:pl4:0<Z1:1ns10:pl4:ns4:pN1:\
-l4:1=Z2:l2:K25:{Z3:K.7853981633974483096156608:l10:/RN3:l2:K40\
-:{Z4:K.7853981633974483096156608458198757210492:l10:/RN4:l2:K\
+@iF4,5.6,8,9,10,11,12,15,13,14[1s11:pl5:0<Z1:1ns11:pl5:ns5:pN1:\
+l5:1=Z2:l2:K25:{Z3:K.7853981633974483096156608:l11:/RN3:l2:K40\
+:{Z4:K.7853981633974483096156608458198757210492:l11:/RN4:l2:K\
60:{Z5:K.785398163397448309615660845819875721049292349843776455243736\
-:l10:/RN5:N2:l4:K.2:=Z6:l2:K25:{Z7:K.1973955598498807583700497\
-:l10:/RN7:l2:K40:{Z8:K.1973955598498807583700497651947902934475\
-:l10:/RN8:l2:K60:{Z9:K.197395559849880758370049765194790293447585103787852101517688\
-:l10:/RN9:N6:l2:s13:pl4:K.2:>Z10:l13:K5:+s2:pK.2:C4,0:s5:pN10:\
-l13:K3:+s2:pN11:l4:K.2:>Z12:l8:1+s8:pl4:K.2:-1l4:K.2:*+/s4:pJ11:N12:\
-l4:s11:s12:pl4:nl4:*s14:pK3:s9:pN14:1B15:J13:N16:l9:K2:+s9:pJ14:N15:\
-l11:l14:*s11:l9:/s7:pl7:0=Z17:l13:s2:pl8:l5:*l12:+l10:/RN17:l12:\
-l7:+s12:pJ16:N13:0R]@r\
-@iF6,11,4.5,6,7,8,9,10,14,12,13[l2:s13:p0s2:pl11:1/s11:pl11:0\
-<Z1:l11:ns11:pl11:K2:%1=Z2:1s10:pN2:N1:1s8:pK2:s9:pN4:l9:l11:\
-{B5:J3:N6:l9:i9:pJ4:N5:l8:l9:*s8:pJ6:N3:K1.5:l13:*s2:pl4:l11:\
-^K2:l11:^/l8:/s8:p1s7:s12:pl4:nl4:*K4:/s14:pK1.5:l13:*s2:p1s9:\
-pN8:1B9:J7:N10:l9:i9:pJ8:N9:l7:l14:*l9:/l11:l9:+/s7:pl7:0=Z11:\
-l13:s2:pl10:Z12:l8:nl12:*1/RN12:l8:l12:*1/RN11:l12:l7:+s12:pJ10:N7:\
-0R]@r"
+:l11:/RN5:N2:l5:K.2:=Z6:l2:K25:{Z7:K.1973955598498807583700497\
+:l11:/RN7:l2:K40:{Z8:K.1973955598498807583700497651947902934475\
+:l11:/RN8:l2:K60:{Z9:K.197395559849880758370049765194790293447585103787852101517688\
+:l11:/RN9:N6:l2:s14:pl5:K.2:>Z10:l14:K5:+s2:pK.2:C4,0:s6:pN10:\
+l14:K3:+s2:pN11:l5:K.2:>Z12:l9:1+s9:pl5:K.2:-1l5:K.2:*+/s5:pJ11:N12:\
+l5:s12:s13:pl5:nl5:*s15:pK3:s10:pN14:1B15:J13:N16:l10:K2:+s10:\
+pJ14:N15:l12:l15:*s12:l10:/s8:pl8:0=Z17:l14:s2:pl9:l6:*l13:+l11:\
+/RN17:l13:l8:+s13:pJ16:N13:0R]@r\
+@iF6,12,5.6,7,8,9,10,11,15,13,14[l2:s14:p0s2:pl12:1/s12:pl12:\
+0<Z1:l12:ns12:pl12:K2:%1=Z2:1s11:pN2:N1:1s9:pK2:s10:pN4:l10:l12:\
+{B5:J3:N6:l10:i10:pJ4:N5:l9:l10:*s9:pJ6:N3:K1.5:l14:*s2:pl5:l12:\
+^K2:l12:^/l9:/s9:p1s8:s13:pl5:nl5:*K4:/s15:pK1.5:l14:*s2:p1s10:\
+pN8:1B9:J7:N10:l10:i10:pJ8:N9:l8:l15:*l10:/l12:l10:+/s8:pl8:0\
+=Z11:l14:s2:pl11:Z12:l9:nl13:*1/RN12:l9:l13:*1/RN11:l13:l8:+s13:\
+pJ10:N7:0R]@r"
View
29 gnu/usr.bin/bc/load.c
@@ -1,7 +1,7 @@
/* load.c: This code "loads" code into the code segments. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -235,12 +235,27 @@ load_code (code)
str++;
break;
}
- ap_name = long_val (&str);
+ if (*str == '*')
+ {
+ str++;
+ ap_name = long_val (&str);
#if DEBUG > 2
- printf ("parameter number %d\n", ap_name);
+ printf ("var parameter number %d\n", ap_name);
#endif
- functions[(int)func].f_params =
- nextarg (functions[(int)func].f_params, ap_name);
+ functions[(int)func].f_params =
+ nextarg (functions[(int)func].f_params, ap_name,
+ TRUE);
+ }
+ else
+ {
+ ap_name = long_val (&str);
+#if DEBUG > 2
+ printf ("parameter number %d\n", ap_name);
+#endif
+ functions[(int)func].f_params =
+ nextarg (functions[(int)func].f_params, ap_name,
+ FALSE);
+ }
}
/* get the auto vars */
@@ -252,7 +267,7 @@ load_code (code)
printf ("auto number %d\n", ap_name);
#endif
functions[(int)func].f_autos =
- nextarg (functions[(int)func].f_autos, ap_name);
+ nextarg (functions[(int)func].f_autos, ap_name, FALSE);
}
save_adr = load_adr;
load_adr.pc_func = func;
View
177 gnu/usr.bin/bc/main.c
@@ -1,7 +1,7 @@
/* main.c: The main program for bc. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -30,58 +30,168 @@
#include <signal.h>
#include "global.h"
#include "proto.h"
+#include "getopt.h"
+
/* Variables for processing multiple files. */
char first_file;
extern FILE *yyin;
+/* Points to the last node in the file name list for easy adding. */
+static file_node *last = NULL;
-/* The main program for bc. */
-int
-main (argc, argv)
+#ifdef READLINE
+/* Readline support. */
+extern char *rl_readline_name;
+extern FILE *rl_instream;
+#endif
+
+/* long option support */
+static struct option long_options[] =
+{
+ {"compile", 0, &compile_only, TRUE},
+ {"mathlib", 0, &use_math, TRUE},
+ {"quiet", 0, &quiet, TRUE},
+ {"standard", 0, &std_only, TRUE},
+ {"version", 0, 0, 'v'},
+ {"warn", 0, &warn_not_std, TRUE},
+
+ {0, 0, 0, 0}
+};
+
+
+void
+parse_args (argc, argv)
int argc;
- char *argv[];
+ char **argv;
{
- int ch;
-
- /* Initialize many variables. */
- compile_only = FALSE;
- use_math = FALSE;
- warn_not_std = FALSE;
- std_only = FALSE;
- if (isatty(0) && isatty(1))
- interactive = TRUE;
- else
- interactive = FALSE;
+ int optch;
+ int long_index;
+ file_node *temp;
+
+ /* Force getopt to initialize. Depends on GNU getopt. */
+ optind = 0;
/* Parse the command line */
- ch = getopt (argc, argv, "lcisvw");
- while (ch != EOF)
+ while (1)
{
- switch (ch)
+ optch = getopt_long (argc, argv, "lciqsvw", long_options, &long_index);
+
+ if (optch == EOF) /* End of arguments. */
+ break;
+
+ switch (optch)
{
case 'c': /* compile only */
compile_only = TRUE;
break;
+
case 'l': /* math lib */
use_math = TRUE;
break;
+
case 'i': /* force interactive */
interactive = TRUE;
break;
- case 'w': /* Non standard features give warnings. */
- warn_not_std = TRUE;
+
+ case 'q': /* quiet mode */
+ quiet = TRUE;
break;
+
case 's': /* Non standard features give errors. */
std_only = TRUE;
break;
+
case 'v': /* Print the version. */
printf ("%s\n", BC_VERSION);
+ exit (0);
+ break;
+
+ case 'w': /* Non standard features give warnings. */
+ warn_not_std = TRUE;
break;
}
- ch = getopt (argc, argv, "lcisvw");
}
+ /* Add file names to a list of files to process. */
+ while (optind < argc)
+ {
+ temp = (file_node *) bc_malloc(sizeof(file_node));
+ temp->name = argv[optind];
+ temp->next = NULL;
+ if (last == NULL)
+ file_names = temp;
+ else
+ last->next = temp;
+ last = temp;
+ optind++;
+ }
+}
+
+/* The main program for bc. */
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *env_value;
+ char *env_argv[30];
+ int env_argc;
+
+ /* Initialize many variables. */
+ compile_only = FALSE;
+ use_math = FALSE;
+ warn_not_std = FALSE;
+ std_only = FALSE;
+ if (isatty(0) && isatty(1))
+ interactive = TRUE;
+ else
+ interactive = FALSE;
+ quiet = FALSE;
+ file_names = NULL;
+
+ /* Environment arguments. */
+ env_value = getenv ("BC_ENV_ARGS");
+ if (env_value != NULL)
+ {
+ env_argc = 1;
+ env_argv[0] = "BC_ENV_ARGS";
+ while (*env_value != 0)
+ {
+ if (*env_value != ' ')
+ {
+ env_argv[env_argc++] = env_value;
+ while (*env_value != ' ' && *env_value != 0)
+ env_value++;
+ if (*env_value != 0)
+ {
+ *env_value = 0;
+ env_value++;
+ }
+ }
+ else
+ env_value++;
+ }
+ parse_args (env_argc, env_argv);
+ }
+
+ /* Command line arguments. */
+ parse_args (argc, argv);
+
+ /* Other environment processing. */
+ if (getenv ("POSIXLY_CORRECT") != NULL)
+ std_only = TRUE;
+
+ env_value = getenv ("BC_LINE_LENGTH");
+ if (env_value != NULL)
+ {
+ line_size = atoi (env_value);
+ if (line_size < 2)
+ line_size = 70;
+ }
+ else
+ line_size = 70;
+
/* Initialize the machine. */
init_storage();
init_load();
@@ -93,13 +203,18 @@ main (argc, argv)
/* Initialize the front end. */
init_tree();
init_gen ();
- g_argv = argv;
- g_argc = argc;
is_std_in = FALSE;
first_file = TRUE;
if (!open_new_file ())
exit (1);
+#ifdef READLINE
+ /* Readline support. Set both application name and input file. */
+ rl_readline_name = "bc";
+ rl_instream = stdin;
+ using_history ();
+#endif
+
/* Do the parse. */
yyparse ();
@@ -119,6 +234,7 @@ int
open_new_file ()
{
FILE *new_file;
+ file_node *temp;
/* Set the line number. */
line_no = 1;
@@ -161,16 +277,19 @@ open_new_file ()
}
/* One of the argv values. */
- while (optind < g_argc)
+ if (file_names != NULL)
{
- new_file = fopen (g_argv[optind], "r");
+ new_file = fopen (file_names->name, "r");
if (new_file != NULL)
{
new_yy_file (new_file);
- optind++;
+ temp = file_names;
+ file_name = temp->name;
+ file_names = temp->next;
+ free (temp);
return TRUE;
}
- fprintf (stderr, "File %s is unavailable.\n", g_argv[optind++]);
+ fprintf (stderr, "File %s is unavailable.\n", file_names->name);
exit (1);
}
View
345 gnu/usr.bin/bc/number.c
@@ -1,7 +1,7 @@
/* number.c: Implements arbitrary precision numbers. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -23,11 +23,12 @@
Computer Science Department, 9062
Western Washington University
Bellingham, WA 98226-9062
-
+
*************************************************************************/
#include "bcdefs.h"
#include "proto.h"
+#include "global.h"
/* Storage used for special numbers. */
bc_num _zero_;
@@ -43,7 +44,7 @@ free_num (num)
bc_num *num;
{
if (*num == NULL) return;
- (*num)->n_refs--;
+ (*num)->n_refs--;
if ((*num)->n_refs == 0) free(*num);
*num = NULL;
}
@@ -113,32 +114,32 @@ int2num (num, val)
char *bptr, *vptr;
int ix = 1;
char neg = 0;
-
+
/* Sign. */
if (val < 0)
{
neg = 1;
val = -val;
}
-
+
/* Get things going. */
bptr = buffer;
- *bptr++ = val % 10;
- val = val / 10;
-
+ *bptr++ = val % BASE;
+ val = val / BASE;
+
/* Extract remaining digits. */
while (val != 0)
{
- *bptr++ = val % 10;
- val = val / 10;
+ *bptr++ = val % BASE;
+ val = val / BASE;
ix++; /* Count the digits. */
}
-
+
/* Make the number. */
free_num (num);
*num = new_num (ix, 0);
if (neg) (*num)->n_sign = MINUS;
-
+
/* Assign the digits. */
vptr = (*num)->n_value;
while (ix-- > 0)
@@ -146,7 +147,7 @@ int2num (num, val)
}
-/* Convert a number NUM to a long. The function returns only the integer
+/* Convert a number NUM to a long. The function returns only the integer
part of the number. For numbers that are too large to represent as
a long, this function returns a zero. This can be detected by checking
the NUM for zero after having a zero returned. */
@@ -162,13 +163,13 @@ num2long (num)
/* Extract the int value, ignore the fraction. */
val = 0;
nptr = num->n_value;
- for (index=num->n_len; (index>0) && (val<=(LONG_MAX/10)); index--)
- val = val*10 + *nptr++;
-
+ for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--)
+ val = val*BASE + *nptr++;
+
/* Check for overflow. If overflow, return zero. */
if (index>0) val = 0;
if (val < 0) val = 0;
-
+
/* Return the value. */
if (num->n_sign == PLUS)
return (val);
@@ -181,8 +182,8 @@ num2long (num)
_PROTOTYPE(static int _do_compare, (bc_num n1, bc_num n2, int use_sign,
int ignore_last));
_PROTOTYPE(static void _rm_leading_zeros, (bc_num num));
-_PROTOTYPE(static bc_num _do_add, (bc_num n1, bc_num n2));
-_PROTOTYPE(static bc_num _do_sub, (bc_num n1, bc_num n2));
+_PROTOTYPE(static bc_num _do_add, (bc_num n1, bc_num n2, int scale_min));
+_PROTOTYPE(static bc_num _do_sub, (bc_num n1, bc_num n2, int scale_min));
_PROTOTYPE(static void _one_mult, (unsigned char *num, int size, int digit,
unsigned char *result));
@@ -200,7 +201,7 @@ _do_compare (n1, n2, use_sign, ignore_last)
{
char *n1ptr, *n2ptr;
int count;
-
+
/* First, compare signs. */
if (use_sign && n1->n_sign != n2->n_sign)
{
@@ -209,7 +210,7 @@ _do_compare (n1, n2, use_sign, ignore_last)
else
return (-1); /* Negative N1 < Positive N1 */
}
-
+
/* Now compare the magnitude. */
if (n1->n_len != n2->n_len)
{
@@ -266,7 +267,7 @@ _do_compare (n1, n2, use_sign, ignore_last)
}
/* They are equal up to the last part of the equal part of the fraction. */
- if (n1->n_scale != n2->n_scale)
+ if (n1->n_scale != n2->n_scale)
if (n1->n_scale > n2->n_scale)
{
for (count = n1->n_scale-n2->n_scale; count>0; count--)
@@ -291,7 +292,7 @@ _do_compare (n1, n2, use_sign, ignore_last)
return (1);
}
}
-
+
/* They must be equal! */
return (0);
}
@@ -328,7 +329,7 @@ is_zero (num)
if (count != 0)
return FALSE;
- else
+ else
return TRUE;
}
@@ -357,8 +358,8 @@ _rm_leading_zeros (num)
/* Do a quick check to see if we need to do it. */
if (*num->n_value != 0) return;
- /* The first digit is 0, find the first non-zero digit in the 10's or
- greater place. */
+ /* The first "digit" is 0, find the first non-zero digit in the second
+ or greater "digit" to the left of the decimal place. */
bytes = num->n_len;
src = num->n_value;
while (bytes > 1 && *src == 0) src++, bytes--;
@@ -366,26 +367,37 @@ _rm_leading_zeros (num)
bytes += num->n_scale;
dst = num->n_value;
while (bytes-- > 0) *dst++ = *src++;
-
+
}
/* Perform addition: N1 is added to N2 and the value is
- returned. The signs of N1 and N2 are ignored. */
+ returned. The signs of N1 and N2 are ignored.
+ SCALE_MIN is to set the minimum scale of the result. */
static bc_num
-_do_add (n1, n2)
+_do_add (n1, n2, scale_min)
bc_num n1, n2;
+ int scale_min;
{
bc_num sum;
int sum_scale, sum_digits;
char *n1ptr, *n2ptr, *sumptr;
int carry, n1bytes, n2bytes;
+ int count;
/* Prepare sum. */
sum_scale = MAX (n1->n_scale, n2->n_scale);
sum_digits = MAX (n1->n_len, n2->n_len) + 1;
- sum = new_num (sum_digits,sum_scale);
+ sum = new_num (sum_digits, MAX(sum_scale, scale_min));
+
+ /* Zero extra digits made by scale_min. */
+ if (scale_min > sum_scale)
+ {
+ sumptr = (char *) (sum->n_value + sum_scale + sum_digits);
+ for (count = scale_min - sum_scale; count > 0; count--)
+ *sumptr++ = 0;
+ }
/* Start with the fraction part. Initialize the pointers. */
n1bytes = n1->n_scale;
@@ -412,10 +424,10 @@ _do_add (n1, n2)
while ((n1bytes > 0) && (n2bytes > 0))
{
*sumptr = *n1ptr-- + *n2ptr-- + carry;
- if (*sumptr > 9)
+ if (*sumptr > (BASE-1))
{
carry = 1;
- *sumptr -= 10;
+ *sumptr -= BASE;
}
else
carry = 0;
@@ -430,10 +442,10 @@ _do_add (n1, n2)
while (n1bytes-- > 0)
{
*sumptr = *n1ptr-- + carry;
- if (*sumptr > 9)
+ if (*sumptr > (BASE-1))
{
carry = 1;
- *sumptr -= 10;
+ *sumptr -= BASE;
}
else
carry = 0;
@@ -443,20 +455,22 @@ _do_add (n1, n2)
/* Set final carry. */
if (carry == 1)
*sumptr += 1;
-
+
/* Adjust sum and return. */
_rm_leading_zeros (sum);
- return sum;
+ return sum;
}
/* Perform subtraction: N2 is subtracted from N1 and the value is
returned. The signs of N1 and N2 are ignored. Also, N1 is
- assumed to be larger than N2. */
+ assumed to be larger than N2. SCALE_MIN is the minimum scale
+ of the result. */
static bc_num
-_do_sub (n1, n2)
+_do_sub (n1, n2, scale_min)
bc_num n1, n2;
+ int scale_min;
{
bc_num diff;
int diff_scale, diff_len;
@@ -469,7 +483,15 @@ _do_sub (n1, n2)
diff_scale = MAX (n1->n_scale, n2->n_scale);
min_len = MIN (n1->n_len, n2->n_len);
min_scale = MIN (n1->n_scale, n2->n_scale);
- diff = new_num (diff_len, diff_scale);
+ diff = new_num (diff_len, MAX(diff_scale, scale_min));
+
+ /* Zero extra digits made by scale_min. */
+ if (scale_min > diff_scale)
+ {
+ diffptr = (char *) (diff->n_value + diff_len + diff_scale);
+ for (count = scale_min - diff_scale; count > 0; count--)
+ *diffptr++ = 0;
+ }
/* Initialize the subtract. */
n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1);
@@ -478,7 +500,7 @@ _do_sub (n1, n2)
/* Subtract the numbers. */
borrow = 0;
-
+
/* Take care of the longer scaled number. */
if (n1->n_scale != min_scale)
{
@@ -494,7 +516,7 @@ _do_sub (n1, n2)
val = - *n2ptr-- - borrow;
if (val < 0)
{
- val += 10;
+ val += BASE;
borrow = 1;
}
else
@@ -502,15 +524,15 @@ _do_sub (n1, n2)
*diffptr-- = val;
}
}
-
+
/* Now do the equal length scale and integer parts. */
-
+
for (count = 0; count < min_len + min_scale; count++)
{
val = *n1ptr-- - *n2ptr-- - borrow;
if (val < 0)
{
- val += 10;
+ val += BASE;
borrow = 1;
}
else
@@ -526,7 +548,7 @@ _do_sub (n1, n2)
val = *n1ptr-- - borrow;
if (val < 0)
{
- val += 10;
+ val += BASE;
borrow = 1;
}
else
@@ -542,18 +564,21 @@ _do_sub (n1, n2)
/* Here is the full add routine that takes care of negative numbers.
- N1 is added to N2 and the result placed into RESULT. */
+ N1 is added to N2 and the result placed into RESULT. SCALE_MIN
+ is the minimum scale for the result. */
void
-bc_add ( n1, n2, result)
+bc_add (n1, n2, result, scale_min)
bc_num n1, n2, *result;
+ int scale_min;
{
bc_num sum;
int cmp_res;
+ int res_scale;
if (n1->n_sign == n2->n_sign)
{
- sum = _do_add (n1, n2);
+ sum = _do_add (n1, n2, scale_min);
sum->n_sign = n1->n_sign;
}
else
@@ -564,16 +589,18 @@ bc_add ( n1, n2, result)
{
case -1:
/* n1 is less than n2, subtract n1 from n2. */
- sum = _do_sub (n2, n1);
+ sum = _do_sub (n2, n1, scale_min);
sum->n_sign = n2->n_sign;
break;
case 0:
- /* They are equal! return zero! */
- sum = copy_num (_zero_);
+ /* They are equal! return zero with the correct scale! */
+ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
+ sum = new_num (1, res_scale);
+ memset (sum->n_value, 0, res_scale+1);
break;
case 1:
/* n2 is less than n1, subtract n2 from n1. */
- sum = _do_sub (n1, n2);
+ sum = _do_sub (n1, n2, scale_min);
sum->n_sign = n1->n_sign;
}
}
@@ -585,18 +612,21 @@ bc_add ( n1, n2, result)
/* Here is the full subtract routine that takes care of negative numbers.
- N2 is subtracted from N1 and the result placed in RESULT. */
+ N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN
+ is the minimum scale for the result. */
void
-bc_sub ( n1, n2, result)
+bc_sub (n1, n2, result, scale_min)
bc_num n1, n2, *result;
+ int scale_min;
{
bc_num diff;
int cmp_res;
+ int res_scale;
if (n1->n_sign != n2->n_sign)
{
- diff = _do_add (n1, n2);
+ diff = _do_add (n1, n2, scale_min);
diff->n_sign = n1->n_sign;
}
else
@@ -607,21 +637,23 @@ bc_sub ( n1, n2, result)
{
case -1:
/* n1 is less than n2, subtract n1 from n2. */
- diff = _do_sub (n2, n1);
+ diff = _do_sub (n2, n1, scale_min);
diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
break;
case 0:
/* They are equal! return zero! */
- diff = copy_num (_zero_);
+ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
+ diff = new_num (1, res_scale);
+ memset (diff->n_value, 0, res_scale+1);
break;
case 1:
/* n2 is less than n1, subtract n2 from n1. */
- diff = _do_sub (n1, n2);
+ diff = _do_sub (n1, n2, scale_min);
diff->n_sign = n1->n_sign;
break;
}
}
-
+
/* Clean up and return. */
free_num (result);
*result = diff;
@@ -668,7 +700,7 @@ bc_multiply (n1, n2, prod, scale)
n2ptr = (char *) (n2end - MIN(indx, len2-1));
while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
sum += *n1ptr-- * *n2ptr++;
- sum = sum / 10;
+ sum = sum / BASE;
}
for ( ; indx < total_digits-1; indx++)
{
@@ -676,8 +708,8 @@ bc_multiply (n1, n2, prod, scale)
n2ptr = (char *) (n2end - MIN(indx, len2-1));
while ((n1ptr >= n1->n_value) && (n2ptr <= n2end))
sum += *n1ptr-- * *n2ptr++;
- *pvptr-- = sum % 10;
- sum = sum / 10;
+ *pvptr-- = sum % BASE;
+ sum = sum / BASE;
}
*pvptr-- = sum;
@@ -685,7 +717,7 @@ bc_multiply (n1, n2, prod, scale)
free_num (prod);
*prod = pval;
_rm_leading_zeros (*prod);
- if (is_zero (*prod))
+ if (is_zero (*prod))
(*prod)->n_sign = PLUS;
}
@@ -720,10 +752,10 @@ _one_mult (num, size, digit, result)
while (size-- > 0)
{
value = *nptr-- * digit + carry;
- *rptr-- = value % 10;
- carry = value / 10;
+ *rptr-- = value % BASE;
+ carry = value / BASE;
}
-
+
if (carry != 0) *rptr = carry;
}
}
@@ -739,7 +771,7 @@ int
bc_divide (n1, n2, quot, scale)
bc_num n1, n2, *quot;
int scale;
-{
+{
bc_num qval;
unsigned char *num1, *num2;
unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
@@ -767,7 +799,7 @@ bc_divide (n1, n2, quot, scale)
*quot = qval;
}
}
-
+
/* Set up the divide. Move the decimal point on n1 by n2's scale.
Remember, zeros on the end of num2 are wasted effort for dividing. */
scale2 = n2->n_scale;
@@ -859,7 +891,7 @@ bc_divide (n1, n2, quot, scale)
+ num1[qdig+2])
qguess--;
}
-
+
/* Multiply and subtract. */
borrow = 0;
if (qguess != 0)
@@ -903,7 +935,7 @@ bc_divide (n1, n2, quot, scale)
}
if (carry == 1) *ptr1 = (*ptr1 + 1) % 10;
}
-
+
/* We now know the quotient digit. */
*qptr++ = qguess;
qdig++;
@@ -926,14 +958,17 @@ bc_divide (n1, n2, quot, scale)
}
-/* Modulo for numbers. This computes NUM1 % NUM2 and puts the
- result in RESULT. */
+/* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and
+ NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT
+ is NULL then that store will be omitted.
+ */
int
-bc_modulo (num1, num2, result, scale)
- bc_num num1, num2, *result;
+bc_divmod (num1, num2, quot, rem, scale)
+ bc_num num1, num2, *quot, *rem;
int scale;
{
+ bc_num quotient;
bc_num temp;
int rscale;
@@ -943,13 +978,90 @@ bc_modulo (num1, num2, result, scale)
/* Calculate final scale. */
rscale = MAX (num1->n_scale, num2->n_scale+scale);
init_num (&temp);
-
+
/* Calculate it. */
bc_divide (num1, num2, &temp, scale);
+ if (quot)
+ quotient = copy_num(temp);
bc_multiply (temp, num2, &temp, rscale);
- bc_sub (num1, temp, result);
+ bc_sub (num1, temp, rem, rscale);
free_num (&temp);
+ if (quot)
+ {
+ free_num (quot);
+ *quot = quotient;
+ }
+
+ return 0; /* Everything is OK. */
+}
+
+
+/* Modulo for numbers. This computes NUM1 % NUM2 and puts the
+ result in RESULT. */
+
+int
+bc_modulo (num1, num2, result, scale)
+ bc_num num1, num2, *result;
+ int scale;
+{
+ return bc_divmod (num1, num2, NULL, result, scale);
+}
+
+
+/* Raise BASE to the EXPO power, reduced modulo MOD. The result is
+ placed in RESULT. If a EXPO is not an integer,
+ only the integer part is used. */
+
+int
+bc_raisemod (base, expo, mod, result, scale)
+ bc_num base, expo, mod, *result;
+ int scale;
+{
+ bc_num power, exponent, parity, temp;
+ int rscale;
+
+ /* Check for correct numbers. */
+ if (is_zero(mod)) return -1;
+ if (is_neg(expo)) return -1;
+
+ /* Set initial values. */
+ power = copy_num (base);
+ exponent = copy_num (expo);
+ temp = copy_num (_one_);
+ init_num (&parity);
+
+ /* Check the exponent for scale digits. */
+ if (exponent->n_scale != 0)
+ {
+ rt_warn ("non-zero scale in exponent");
+ bc_divide (exponent, _one_, &exponent, 0); /*truncate */
+ }
+
+ /* Check the modulus for scale digits. */
+ if (mod->n_scale != 0)
+ rt_warn ("non-zero scale in modulus");
+
+ /* Do the calculation. */
+ rscale = MAX(scale, base->n_scale);
+ while ( !is_zero(exponent) )
+ {
+ (void) bc_divmod (exponent, _two_, &exponent, &parity, 0);
+ if ( !is_zero(parity) )
+ {
+ bc_multiply (temp, power, &temp, rscale);
+ (void) bc_modulo (temp, mod, &temp, scale);
+ }
+
+ bc_multiply (power, power, &power, rscale);
+ (void) bc_modulo (power, mod, &power, scale);
+ }
+
+ /* Assign the value. */
+ free_num (&power);
+ free_num (&exponent);
+ free_num (result);
+ *result = temp;
return 0; /* Everything is OK. */
}
@@ -998,7 +1110,7 @@ bc_raise (num1, num2, result, scale)
/* Set initial value of temp. */
power = copy_num (num1);
- while ((exponent & 1) == 0)
+ while ((exponent & 1) == 0)
{
bc_multiply (power, power, &power, rscale);
exponent = exponent >> 1;
@@ -1006,7 +1118,7 @@ bc_raise (num1, num2, result, scale)
temp = copy_num (power);
exponent = exponent >> 1;
-
+
/* Do the calculation. */
while (exponent > 0)
{
@@ -1015,7 +1127,7 @@ bc_raise (num1, num2, result, scale)
bc_multiply (temp, power, &temp, rscale);
exponent = exponent >> 1;
}
-
+
/* Assign the value. */
if (neg)
{
@@ -1030,18 +1142,40 @@ bc_raise (num1, num2, result, scale)
free_num (&power);
}
+/* In some places we need to check if the number NUM is zero. */
+
+char
+is_near_zero (num, scale)
+ bc_num num;
+ int scale;
+{
+ int count;
+ char *nptr;
+
+ /* Initialize */
+ count = num->n_len + scale;
+ nptr = num->n_value;
+
+ /* The check */
+ while ((count > 0) && (*nptr++ == 0)) count--;
+
+ if (count != 0 && (count != 1 || *--nptr != 1))
+ return FALSE;
+ else
+ return TRUE;
+}
/* Take the square root NUM and return it in NUM with SCALE digits
after the decimal place. */
-int
+int
bc_sqrt (num, scale)
bc_num *num;
int scale;
{
int rscale, cmp_res, done;
int cscale;
- bc_num guess, guess1, point5;
+ bc_num guess, guess1, point5, diff;
/* Initial checks. */
cmp_res = bc_compare (*num, _zero_);
@@ -1068,10 +1202,11 @@ bc_sqrt (num, scale)
rscale = MAX (scale, (*num)->n_scale);
init_num (&guess);
init_num (&guess1);
+ init_num (&diff);
point5 = new_num (1,1);
point5->n_value[1] = 5;
-
-
+
+
/* Calculate the initial guess. */
if (cmp_res < 0)
/* The number is between 0 and 1. Guess should start at 1. */
@@ -1080,37 +1215,39 @@ bc_sqrt (num, scale)
{
/* The number is greater than 1. Guess should start at 10^(exp/2). */
int2num (&guess,10);
+
int2num (&guess1,(*num)->n_len);
bc_multiply (guess1, point5, &guess1, 0);
guess1->n_scale = 0;
bc_raise (guess, guess1, &guess, 0);
free_num (&guess1);
}
-
+
/* Find the square root using Newton's algorithm. */
done = FALSE;
- cscale = 2;
+ cscale = 3;
while (!done)
{
free_num (&guess1);
guess1 = copy_num (guess);
- bc_divide (*num,guess,&guess,cscale);
- bc_add (guess,guess1,&guess);
- bc_multiply (guess,point5,&guess,cscale);
- cmp_res = _do_compare (guess,guess1,FALSE,TRUE);
- if (cmp_res == 0)
+ bc_divide (*num, guess, &guess, cscale);
+ bc_add (guess, guess1, &guess, 0);
+ bc_multiply (guess, point5, &guess, cscale);
+ bc_sub (guess, guess1, &diff, cscale+1);
+ if (is_near_zero (diff, cscale))
if (cscale < rscale+1)
cscale = MIN (cscale*3, rscale+1);
- else
+ else
done = TRUE;
}
-
+
/* Assign the number and clean up. */
free_num (num);
bc_divide (guess,_one_,num,rscale);
free_num (&guess);
free_num (&guess1);
free_num (&point5);
+ free_num (&diff);
return 1;
}
@@ -1192,7 +1329,10 @@ out_num (num, o_base, out_char)
(*out_char) (BCD_CHAR(*nptr++));
else
nptr++;
-
+
+ if (std_only && is_zero (num))
+ (*out_char) ('0');
+
/* Now the fraction. */
if (num->n_scale > 0)
{
@@ -1203,6 +1343,10 @@ out_num (num, o_base, out_char)
}
else
{
+ /* special case ... */
+ if (std_only && is_zero (num))
+ (*out_char) ('0');
+
/* The number is some other base. */
digits = NULL;
init_num (&int_part);
@@ -1210,7 +1354,7 @@ out_num (num, o_base, out_char)
init_num (&frac_part);
init_num (&cur_dig);
init_num (&base);
- bc_sub (num, int_part, &frac_part);
+ bc_sub (num, int_part, &frac_part, 0);
/* Make the INT_PART and FRAC_PART positive. */
int_part->n_sign = PLUS;
frac_part->n_sign = PLUS;
@@ -1239,7 +1383,7 @@ out_num (num, o_base, out_char)
{
temp = digits;
digits = digits->next;
- if (o_base <= 16)
+ if (o_base <= 16)
(*out_char) (ref_str[ (int) temp->digit]);
else
out_long (temp->digit, max_o_digit->n_len, 1, out_char);
@@ -1257,7 +1401,7 @@ out_num (num, o_base, out_char)
bc_multiply (frac_part, base, &frac_part, num->n_scale);
fdigit = num2long (frac_part);
int2num (&int_part, fdigit);
- bc_sub (frac_part, int_part, &frac_part);
+ bc_sub (frac_part, int_part, &frac_part, 0);
if (o_base <= 16)
(*out_char) (ref_str[fdigit]);
else {
@@ -1266,17 +1410,18 @@ out_num (num, o_base, out_char)
}
bc_multiply (t_num, base, &t_num, 0);
}
+ free_num (&t_num);
}
-
+
/* Clean up. */
free_num (&int_part);
free_num (&frac_part);
free_num (&base);
free_num (&cur_dig);
+ free_num (&max_o_digit);
}
}
-
#if DEBUG > 0
/* Debugging procedures. Some are just so one can call them from the
@@ -1368,7 +1513,7 @@ str2num (num, str, scale)
for (;digits > 0; digits--)
*nptr++ = CH_VAL(*ptr++);
-
+
/* Build the fractional part. */
if (strscale > 0)
{
View
15 gnu/usr.bin/bc/number.h
@@ -1,7 +1,7 @@
/* number.h: Arbitrary precision numbers header file. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -41,6 +41,11 @@ typedef struct
typedef bc_struct *bc_num;
+/* The base used in storing the numbers in n_value above.
+ Currently this MUST be 10. */
+
+#define BASE 10
+
/* Some useful macros and constants. */
#define CH_VAL(c) (c - '0')
@@ -50,9 +55,9 @@ typedef bc_struct *bc_num;
#undef MIN
#undef MAX
#endif
-#define MAX(a,b) (a>b?a:b)
-#define MIN(a,b) (a>b?b:a)
-#define ODD(a) (a&1)
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)>(b)?(b):(a))
+#define ODD(a) ((a)&1)
#ifndef TRUE
#define TRUE 1
View
29 gnu/usr.bin/bc/proto.h
@@ -1,7 +1,7 @@
/* proto.h: Prototype function definitions for "external" functions. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -38,14 +38,12 @@
#endif
/* Include the standard library header files. */
-#ifndef NO_UNISTD
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifndef NO_STDLIB
-#ifdef __STDC__
+#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#endif
/* Define the _PROTOTYPE macro if it is needed. */
@@ -69,7 +67,7 @@ _PROTOTYPE(void assign, (int c_code));
/* From util.c */
_PROTOTYPE(char *strcopyof, (char *str));
-_PROTOTYPE(arg_list *nextarg, (arg_list *args, int val));
+_PROTOTYPE(arg_list *nextarg, (arg_list *args, int val, int is_var));
_PROTOTYPE(char *arg_str, (arg_list *args));
_PROTOTYPE(char *call_str, (arg_list *args));
_PROTOTYPE(void free_args, (arg_list *args));
@@ -118,12 +116,18 @@ _PROTOTYPE(long num2long, (bc_num num));
_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2));
_PROTOTYPE(char is_zero, (bc_num num));
_PROTOTYPE(char is_neg, (bc_num num));
-_PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result));
-_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result));
+_PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
+_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
_PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale));
_PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale));
-_PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result, int scale));
-_PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result, int scale));
+_PROTOTYPE(int bc_modulo,
+ (bc_num num1, bc_num num2, bc_num *result, int scale));
+_PROTOTYPE(int bc_divmod,
+ (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale));
+_PROTOTYPE(int bc_raisemod,
+ (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale));
+_PROTOTYPE(void bc_raise,
+ (bc_num num1, bc_num num2, bc_num *result, int scale));
_PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
_PROTOTYPE(void out_long, (long val, int size, int space,
void (*out_char)(int)));
@@ -162,5 +166,6 @@ _PROTOTYPE(int yyparse, (void));
_PROTOTYPE(int yylex, (void));
/* Other things... */
+#ifndef HAVE_UNISTD_H
_PROTOTYPE (int getopt, (int, char *[], CONST char *));
-
+#endif
View
109 gnu/usr.bin/bc/scan.l
@@ -1,8 +1,8 @@
%{
/* scan.l: the (f)lex description file for the scanner. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -28,9 +28,10 @@
*************************************************************************/
#include "bcdefs.h"
-#include "y.tab.h"
+#include "bc.h"
#include "global.h"
#include "proto.h"
+#include <errno.h>
/* Using flex, we can ask for a smaller input buffer. With lex, this
does nothing! */
@@ -40,24 +41,112 @@
#define YY_READ_BUF_SIZE 512
#endif
+/* Force . as last for now. */
+#define DOT_IS_LAST
+
/* We want to define our own yywrap. */
#undef yywrap
_PROTOTYPE(int yywrap, (void));
+#ifdef READLINE
+/* Support for the readline and history libraries. This allows
+ nicer input on the interactive part of input. */
+
+/* Have input call the following function. */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ rl_input((char *)buf, &result, max_size)
+
+/* Variables to help interface readline with bc. */
+static char *rl_line = (char *)NULL;
+static char *rl_start = (char *)NULL;
+static char rl_len = 0;
+
+/* Definitions for readline access. */
+extern FILE *rl_instream;
+_PROTOTYPE(char *readline, (char *));
+
+/* Needed here? */
+extern FILE *yyin;
+
+/* rl_input puts upto MAX characters into BUF with the number put in
+ BUF placed in *RESULT. If the yy input file is the same as
+ rl_instream (stdin), use readline. Otherwise, just read it.
+*/
+
+static void
+rl_input (buf, result, max)
+ char *buf;
+ int *result;
+ int max;
+{
+ if (yyin != rl_instream)
+ {
+ while ( (*result = read( fileno(yyin), buf, max )) < 0 )
+ if (errno != EINTR)
+ {
+ yyerror( "read() in flex scanner failed" );
+ exit (1);
+ }
+ return;
+ }
+
+ /* Do we need a new string? */
+ if (rl_len == 0)
+ {
+ if (rl_line)
+ free(rl_line);
+ rl_line = readline ("");
+ if (rl_line == NULL) {
+ /* end of file */
+ *result = 0;
+ rl_len = 0;
+ return;
+ }
+ rl_len = strlen (rl_line)+1;
+ if (rl_len != 1)
+ add_history (rl_line);
+ rl_line[rl_len-1] = '\n';
+ printf ("\r");
+ fflush (stdout);
+ }
+
+ if (rl_len <= max)
+ {
+ strncpy (buf, rl_line, rl_len);
+ *result = rl_len;
+ rl_len = 0;
+ }
+ else
+ {
+ strncpy (buf, rl_line, max);
+ *result = max;
+ rl_len -= max;
+ }
+}
+#else
/* MINIX returns from read with < 0 if SIGINT is encountered.
In flex, we can redefine YY_INPUT to the following. In lex, this
does nothing! */
-#include <errno.h>
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
if (errno != EINTR) \
YY_FATAL_ERROR( "read() in flex scanner failed" );
-
+#endif
%}
DIGIT [0-9A-F]
LETTER [a-z]
+%s slcomment
%%
+"#" {
+ if (!std_only)
+ BEGIN(slcomment);
+ else
+ yyerror ("illegal character: #");
+ }
+<slcomment>[^\n]* { BEGIN(INITIAL); }
+<slcomment>"\n" { line_no++; BEGIN(INITIAL); return(NEWLINE); }
define return(Define);
break return(Break);
quit return(Quit);
@@ -75,6 +164,14 @@ else return(Else);
read return(Read);
halt return(Halt);
last return(Last);
+history {
+#ifdef READLINE
+ return(History);
+#else
+ yylval.s_value = strcopyof(yytext); return(NAME);
+#endif
+ }
+
warranty return(Warranty);
continue return(Continue);
print return(Print);
@@ -91,7 +188,7 @@ limits return(Limits);
&& { return(AND); }
\|\| { return(OR); }
"!" { return(NOT); }
-"*"|"/"|"%" { yylval.c_value = yytext[0]; return(MUL_OP); }
+"*"|"/"|"%" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
"="|\+=|-=|\*=|\/=|%=|\^= { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
=\+|=-|=\*|=\/|=%|=\^ {
#ifdef OLD_EQ_OP
View
125 gnu/usr.bin/bc/storage.c
@@ -1,7 +1,7 @@
/* storage.c: Code and data storage manipulations. This includes labels. */
-/* This file is part of bc written for MINIX.
- Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+/* 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
@@ -56,6 +56,9 @@ init_storage ()
i_base =