709 lines
19 KiB
Diff
709 lines
19 KiB
Diff
|
Description: notice read and write errors on input and output
|
|||
|
Quoting from the bug report:
|
|||
|
+bc (1.06-19ubuntu1) dapper; urgency=low
|
|||
|
+
|
|||
|
+ * Make dc notice read and write errors on its input and output.
|
|||
|
+ I grepped for mentions of the strings `putc', `print', `getc', `FILE',
|
|||
|
+ `stdin', `stdout' and `stderr' and added calls to new error-checking
|
|||
|
+ functions unless it was clear from the immediately-surrounding code
|
|||
|
+ that the program was exiting nonzero, or would exit nonzero if the
|
|||
|
+ call failed. I ignored hits in lib/getopt*, which seems to
|
|||
|
+ pervasively ignore write errors when printing usage messages, in the
|
|||
|
+ hope that these were correct. I _think_ I got them all. -iwj.
|
|||
|
+
|
|||
|
+ -- Ian Jackson <iwj@ubuntu.com> Tue, 4 Apr 2006 17:21:02 +0100
|
|||
|
Author: Ian Jackson <iwj@ubuntu.com>
|
|||
|
Origin: other
|
|||
|
Bug-Debian: http://bugs.debian.org/488735
|
|||
|
---
|
|||
|
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
|
|||
|
diff --git a/bc/execute.c b/bc/execute.c
|
|||
|
index e4e8ef7..8787048 100644
|
|||
|
--- a/bc/execute.c
|
|||
|
+++ b/bc/execute.c
|
|||
|
@@ -108,6 +108,7 @@ execute ()
|
|||
|
}
|
|||
|
out_char ('\n');
|
|||
|
}
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
@@ -222,6 +223,7 @@ execute ()
|
|||
|
}
|
|||
|
}
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
break;
|
|||
|
|
|||
|
case 'R' : /* Return from function */
|
|||
|
@@ -257,6 +259,7 @@ execute ()
|
|||
|
if (inst == 'W') out_char ('\n');
|
|||
|
store_var (4); /* Special variable "last". */
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
pop ();
|
|||
|
break;
|
|||
|
|
|||
|
@@ -338,6 +341,7 @@ execute ()
|
|||
|
case 'w' : /* Write a string to the output. */
|
|||
|
while ((ch = byte(&pc)) != '"') out_schar (ch);
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
break;
|
|||
|
|
|||
|
case 'x' : /* Exchange Top of Stack with the one under the tos. */
|
|||
|
@@ -545,7 +549,10 @@ execute ()
|
|||
|
{
|
|||
|
signal (SIGINT, use_quit);
|
|||
|
if (had_sigint)
|
|||
|
- printf ("\ninterrupted execution.\n");
|
|||
|
+ {
|
|||
|
+ printf ("\ninterrupted execution.\n");
|
|||
|
+ checkferror_output(stdout);
|
|||
|
+ }
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@@ -580,6 +587,7 @@ input_char ()
|
|||
|
out_col = 0; /* Saw a new line */
|
|||
|
}
|
|||
|
}
|
|||
|
+ checkferror_input(stdin);
|
|||
|
|
|||
|
/* Classify and preprocess the input character. */
|
|||
|
if (isdigit(in_ch))
|
|||
|
diff --git a/bc/load.c b/bc/load.c
|
|||
|
index 1035198..4039e86 100644
|
|||
|
--- a/bc/load.c
|
|||
|
+++ b/bc/load.c
|
|||
|
@@ -217,6 +217,7 @@ load_code (code)
|
|||
|
if (label_no > 65535L)
|
|||
|
{ /* Better message? */
|
|||
|
fprintf (stderr,"Program too big.\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
exit(1);
|
|||
|
}
|
|||
|
addbyte ( (char) (label_no & 0xFF));
|
|||
|
diff --git a/bc/main.c b/bc/main.c
|
|||
|
index 9a2461e..3ae427d 100644
|
|||
|
--- a/bc/main.c
|
|||
|
+++ b/bc/main.c
|
|||
|
@@ -358,6 +358,9 @@ use_quit (sig)
|
|||
|
errno = save;
|
|||
|
#else
|
|||
|
write (1, "\n(interrupt) Exiting bc.\n", 26);
|
|||
|
+#ifdef READLINE
|
|||
|
+ rl_initialize (); /* Clear readline buffer */
|
|||
|
+#endif
|
|||
|
#if defined(LIBEDIT)
|
|||
|
if (edit != NULL)
|
|||
|
el_end(edit);
|
|||
|
diff --git a/bc/sbc.y b/bc/sbc.y
|
|||
|
index 0ded29e..6fcc1fa 100644
|
|||
|
--- a/bc/sbc.y
|
|||
|
+++ b/bc/sbc.y
|
|||
|
@@ -86,7 +86,9 @@ program : /* empty */
|
|||
|
if (interactive && !quiet)
|
|||
|
{
|
|||
|
show_bc_version ();
|
|||
|
+ checkferror_output(stdout);
|
|||
|
welcome ();
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
}
|
|||
|
| program input_item
|
|||
|
diff --git a/bc/scan.c b/bc/scan.c
|
|||
|
index 1f78ec2..2b5eeb4 100644
|
|||
|
--- a/bc/scan.c
|
|||
|
+++ b/bc/scan.c
|
|||
|
@@ -799,6 +799,7 @@ bcel_input (buf, result, max)
|
|||
|
if (bcel_len != 0)
|
|||
|
history (hist, &histev, H_ENTER, bcel_line);
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
if (bcel_len <= max)
|
|||
|
@@ -874,6 +875,7 @@ rl_input (buf, result, max)
|
|||
|
add_history (rl_line);
|
|||
|
rl_line[rl_len-1] = '\n';
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
if (rl_len <= max)
|
|||
|
diff --git a/bc/scan.l b/bc/scan.l
|
|||
|
index 841c3df..16cd62e 100644
|
|||
|
--- a/bc/scan.l
|
|||
|
+++ b/bc/scan.l
|
|||
|
@@ -111,6 +111,7 @@ bcel_input (buf, result, max)
|
|||
|
if (bcel_len != 0)
|
|||
|
history (hist, &histev, H_ENTER, bcel_line);
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
if (bcel_len <= max)
|
|||
|
@@ -186,6 +187,7 @@ rl_input (buf, result, max)
|
|||
|
add_history (rl_line);
|
|||
|
rl_line[rl_len-1] = '\n';
|
|||
|
fflush (stdout);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
if (rl_len <= max)
|
|||
|
@@ -310,6 +312,7 @@ limits return(Limits);
|
|||
|
if (c == EOF)
|
|||
|
{
|
|||
|
fprintf (stderr,"EOF encountered in a comment.\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
diff --git a/bc/storage.c b/bc/storage.c
|
|||
|
index 699729a..37b4c6c 100644
|
|||
|
--- a/bc/storage.c
|
|||
|
+++ b/bc/storage.c
|
|||
|
@@ -99,6 +99,7 @@ more_functions (VOID)
|
|||
|
{
|
|||
|
f = &functions[indx];
|
|||
|
f->f_defined = FALSE;
|
|||
|
+ f->f_void = FALSE;
|
|||
|
f->f_body = (char *) bc_malloc (BC_START_SIZE);
|
|||
|
f->f_body_size = BC_START_SIZE;
|
|||
|
f->f_code_size = 0;
|
|||
|
diff --git a/bc/util.c b/bc/util.c
|
|||
|
index 30beaf9..669235f 100644
|
|||
|
--- a/bc/util.c
|
|||
|
+++ b/bc/util.c
|
|||
|
@@ -260,9 +260,10 @@ init_gen ()
|
|||
|
continue_label = 0;
|
|||
|
next_label = 1;
|
|||
|
out_count = 2;
|
|||
|
- if (compile_only)
|
|||
|
+ if (compile_only) {
|
|||
|
printf ("@i");
|
|||
|
- else
|
|||
|
+ checkferror_output(stdout);
|
|||
|
+ } else
|
|||
|
init_load ();
|
|||
|
had_error = FALSE;
|
|||
|
did_gen = FALSE;
|
|||
|
@@ -286,6 +287,7 @@ generate (str)
|
|||
|
printf ("\n");
|
|||
|
out_count = 0;
|
|||
|
}
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
else
|
|||
|
load_code (str);
|
|||
|
@@ -303,6 +305,7 @@ run_code()
|
|||
|
if (compile_only)
|
|||
|
{
|
|||
|
printf ("@r\n");
|
|||
|
+ checkferror_output(stdout);
|
|||
|
out_count = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
@@ -341,6 +344,7 @@ out_char (ch)
|
|||
|
}
|
|||
|
putchar (ch);
|
|||
|
}
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
/* Output routines: Write a character CH to the standard output.
|
|||
|
@@ -371,6 +375,7 @@ out_schar (ch)
|
|||
|
}
|
|||
|
putchar (ch);
|
|||
|
}
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@@ -657,6 +662,7 @@ limits()
|
|||
|
#ifdef OLD_EQ_OP
|
|||
|
printf ("Old assignment operatiors are valid. (=-, =+, ...)\n");
|
|||
|
#endif
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
/* bc_malloc will check the return value so all other places do not
|
|||
|
@@ -721,6 +727,7 @@ yyerror (str, va_alist)
|
|||
|
fprintf (stderr,"%s %d: ",name,line_no);
|
|||
|
vfprintf (stderr, str, args);
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
had_error = TRUE;
|
|||
|
va_end (args);
|
|||
|
}
|
|||
|
@@ -761,6 +768,7 @@ warn (mesg, va_alist)
|
|||
|
fprintf (stderr,"%s %d: Error: ",name,line_no);
|
|||
|
vfprintf (stderr, mesg, args);
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
had_error = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
@@ -773,6 +781,7 @@ warn (mesg, va_alist)
|
|||
|
fprintf (stderr,"%s %d: (Warning) ",name,line_no);
|
|||
|
vfprintf (stderr, mesg, args);
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
va_end (args);
|
|||
|
}
|
|||
|
@@ -807,6 +816,7 @@ rt_error (mesg, va_alist)
|
|||
|
va_end (args);
|
|||
|
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
runtime_error = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
@@ -843,4 +853,5 @@ rt_warn (mesg, va_alist)
|
|||
|
va_end (args);
|
|||
|
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
diff --git a/dc/dc.c b/dc/dc.c
|
|||
|
index e03f094..0faf03a 100644
|
|||
|
--- a/dc/dc.c
|
|||
|
+++ b/dc/dc.c
|
|||
|
@@ -61,6 +61,7 @@ static void
|
|||
|
bug_report_info DC_DECLVOID()
|
|||
|
{
|
|||
|
printf("Email bug reports to: bug-dc@gnu.org .\n");
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
static void
|
|||
|
@@ -71,6 +72,7 @@ show_version DC_DECLVOID()
|
|||
|
This is free software; see the source for copying conditions. There is NO\n\
|
|||
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,\n\
|
|||
|
to the extent permitted by law.\n", DC_COPYRIGHT);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
/* your generic usage function */
|
|||
|
@@ -87,6 +89,7 @@ Usage: %s [OPTION] [file ...]\n\
|
|||
|
\n\
|
|||
|
", progname);
|
|||
|
bug_report_info();
|
|||
|
+ checkferror_output(f);
|
|||
|
}
|
|||
|
|
|||
|
/* returns a pointer to one past the last occurance of c in s,
|
|||
|
diff --git a/dc/eval.c b/dc/eval.c
|
|||
|
index 4af7200..153d331 100644
|
|||
|
--- a/dc/eval.c
|
|||
|
+++ b/dc/eval.c
|
|||
|
@@ -94,12 +94,15 @@ static int input_pushback;
|
|||
|
static int
|
|||
|
input_fil DC_DECLVOID()
|
|||
|
{
|
|||
|
+ int c;
|
|||
|
if (input_pushback != EOF){
|
|||
|
- int c = input_pushback;
|
|||
|
+ c = input_pushback;
|
|||
|
input_pushback = EOF;
|
|||
|
return c;
|
|||
|
}
|
|||
|
- return getc(input_fil_fp);
|
|||
|
+ c = getc(input_fil_fp);
|
|||
|
+ checkferror_input(input_fil_fp);
|
|||
|
+ return c;
|
|||
|
}
|
|||
|
|
|||
|
/* passed as an argument to dc_getnum */
|
|||
|
@@ -298,11 +301,13 @@ dc_func DC_DECLARG((c, peekc, negcmp))
|
|||
|
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
|||
|
if (2 <= tmpint && tmpint <= DC_IBASE_MAX)
|
|||
|
dc_ibase = tmpint;
|
|||
|
- else
|
|||
|
+ else {
|
|||
|
fprintf(stderr,
|
|||
|
"%s: input base must be a number \
|
|||
|
between 2 and %d (inclusive)\n",
|
|||
|
progname, DC_IBASE_MAX);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
+ }
|
|||
|
}
|
|||
|
break;
|
|||
|
case 'k': /* set scale to value on top of stack */
|
|||
|
@@ -310,11 +315,12 @@ between 2 and %d (inclusive)\n",
|
|||
|
tmpint = -1;
|
|||
|
if (datum.dc_type == DC_NUMBER)
|
|||
|
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
|||
|
- if ( ! (tmpint >= 0) )
|
|||
|
+ if ( ! (tmpint >= 0) ) {
|
|||
|
fprintf(stderr,
|
|||
|
"%s: scale must be a nonnegative number\n",
|
|||
|
progname);
|
|||
|
- else
|
|||
|
+ checkferror_output(stderr);
|
|||
|
+ } else
|
|||
|
dc_scale = tmpint;
|
|||
|
}
|
|||
|
break;
|
|||
|
@@ -338,11 +344,12 @@ between 2 and %d (inclusive)\n",
|
|||
|
tmpint = 0;
|
|||
|
if (datum.dc_type == DC_NUMBER)
|
|||
|
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
|||
|
- if ( ! (tmpint > 1) )
|
|||
|
+ if ( ! (tmpint > 1) ) {
|
|||
|
fprintf(stderr,
|
|||
|
"%s: output base must be a number greater than 1\n",
|
|||
|
progname);
|
|||
|
- else
|
|||
|
+ checkferror_output(stderr);
|
|||
|
+ } else
|
|||
|
dc_obase = tmpint;
|
|||
|
}
|
|||
|
break;
|
|||
|
@@ -383,6 +390,7 @@ between 2 and %d (inclusive)\n",
|
|||
|
fprintf(stderr,
|
|||
|
"%s: square root of nonnumeric attempted\n",
|
|||
|
progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}else if (dc_sqrt(datum.v.number, dc_scale, &tmpnum) == DC_SUCCESS){
|
|||
|
dc_free_num(&datum.v.number);
|
|||
|
datum.v.number = tmpnum;
|
|||
|
@@ -444,6 +452,7 @@ between 2 and %d (inclusive)\n",
|
|||
|
fprintf(stderr,
|
|||
|
"%s: Q command requires a number >= 1\n",
|
|||
|
progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
break;
|
|||
|
#if 0
|
|||
|
@@ -489,11 +498,12 @@ between 2 and %d (inclusive)\n",
|
|||
|
if (datum.dc_type == DC_NUMBER)
|
|||
|
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
|||
|
if (dc_pop(&datum) == DC_SUCCESS){
|
|||
|
- if (tmpint < 0)
|
|||
|
+ if (tmpint < 0) {
|
|||
|
fprintf(stderr,
|
|||
|
"%s: array index must be a nonnegative integer\n",
|
|||
|
progname);
|
|||
|
- else
|
|||
|
+ checkferror_output(stderr);
|
|||
|
+ } else
|
|||
|
dc_array_set(peekc, tmpint, datum);
|
|||
|
}
|
|||
|
}
|
|||
|
@@ -505,17 +515,19 @@ between 2 and %d (inclusive)\n",
|
|||
|
tmpint = -1;
|
|||
|
if (datum.dc_type == DC_NUMBER)
|
|||
|
tmpint = dc_num2int(datum.v.number, DC_TOSS);
|
|||
|
- if (tmpint < 0)
|
|||
|
+ if (tmpint < 0) {
|
|||
|
fprintf(stderr,
|
|||
|
"%s: array index must be a nonnegative integer\n",
|
|||
|
progname);
|
|||
|
- else
|
|||
|
+ checkferror_output(stderr);
|
|||
|
+ } else
|
|||
|
dc_push(dc_array_get(peekc, tmpint));
|
|||
|
}
|
|||
|
return DC_EATONE;
|
|||
|
|
|||
|
default: /* What did that user mean? */
|
|||
|
fprintf(stderr, "%s: ", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
dc_show_id(stdout, c, " unimplemented\n");
|
|||
|
break;
|
|||
|
}
|
|||
|
@@ -544,6 +556,7 @@ dc_evalstr DC_DECLARG((string))
|
|||
|
fprintf(stderr,
|
|||
|
"%s: eval called with non-string argument\n",
|
|||
|
progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return DC_OKAY;
|
|||
|
}
|
|||
|
interrupt_seen = 0;
|
|||
|
@@ -640,6 +653,7 @@ dc_evalstr DC_DECLARG((string))
|
|||
|
return DC_FAIL;
|
|||
|
}
|
|||
|
fprintf(stderr, "%s: unexpected EOS\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return DC_OKAY;
|
|||
|
}
|
|||
|
}
|
|||
|
@@ -665,6 +679,7 @@ dc_evalfile DC_DECLARG((fp))
|
|||
|
stdin_lookahead = EOF;
|
|||
|
for (c=getc(fp); c!=EOF; c=peekc){
|
|||
|
peekc = getc(fp);
|
|||
|
+ checkferror_input(stdin);
|
|||
|
/*
|
|||
|
* The following if() is the only place where ``stdin_lookahead''
|
|||
|
* might be set to other than EOF:
|
|||
|
@@ -716,6 +731,7 @@ dc_evalfile DC_DECLARG((fp))
|
|||
|
return DC_SUCCESS;
|
|||
|
fprintf(stderr, "%s: Q command argument exceeded \
|
|||
|
string execution depth\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
}else{
|
|||
|
dc_garbage("at top of stack", -1);
|
|||
|
@@ -728,8 +744,11 @@ string execution depth\n", progname);
|
|||
|
fprintf(stderr,
|
|||
|
"%s: Q command argument exceeded string execution depth\n",
|
|||
|
progname);
|
|||
|
- if (stdin_lookahead != peekc && fp == stdin)
|
|||
|
+ checkferror_output(stderr);
|
|||
|
+ if (stdin_lookahead != peekc && fp == stdin) {
|
|||
|
peekc = getc(fp);
|
|||
|
+ checkferror_input(stdin);
|
|||
|
+ }
|
|||
|
break;
|
|||
|
|
|||
|
case DC_INT:
|
|||
|
@@ -771,6 +790,7 @@ string execution depth\n", progname);
|
|||
|
if (ferror(fp))
|
|||
|
goto error_fail;
|
|||
|
fprintf(stderr, "%s: unexpected EOF\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return DC_FAIL;
|
|||
|
}
|
|||
|
}
|
|||
|
diff --git a/dc/misc.c b/dc/misc.c
|
|||
|
index f2388b0..1be56fe 100644
|
|||
|
--- a/dc/misc.c
|
|||
|
+++ b/dc/misc.c
|
|||
|
@@ -91,6 +91,7 @@ dc_show_id DC_DECLARG((fp, id, suffix))
|
|||
|
fprintf(fp, "'%c' (%#o)%s", (unsigned int) id, id, suffix);
|
|||
|
else
|
|||
|
fprintf(fp, "%#o%s", (unsigned int) id, suffix);
|
|||
|
+ checkferror_output(fp);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
diff --git a/dc/numeric.c b/dc/numeric.c
|
|||
|
index 8e5e70f..c875eba 100644
|
|||
|
--- a/dc/numeric.c
|
|||
|
+++ b/dc/numeric.c
|
|||
|
@@ -134,6 +134,7 @@ dc_div DC_DECLARG((a, b, kscale, result))
|
|||
|
bc_init_num(CastNumPtr(result));
|
|||
|
if (bc_divide(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){
|
|||
|
fprintf(stderr, "%s: divide by zero\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return DC_DOMAIN_ERROR;
|
|||
|
}
|
|||
|
return DC_SUCCESS;
|
|||
|
@@ -156,6 +157,7 @@ dc_divrem DC_DECLARG((a, b, kscale, quotient, remainder))
|
|||
|
if (bc_divmod(CastNum(a), CastNum(b),
|
|||
|
CastNumPtr(quotient), CastNumPtr(remainder), kscale)){
|
|||
|
fprintf(stderr, "%s: divide by zero\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return DC_DOMAIN_ERROR;
|
|||
|
}
|
|||
|
return DC_SUCCESS;
|
|||
|
@@ -174,6 +176,7 @@ dc_rem DC_DECLARG((a, b, kscale, result))
|
|||
|
bc_init_num(CastNumPtr(result));
|
|||
|
if (bc_modulo(CastNum(a), CastNum(b), CastNumPtr(result), kscale)){
|
|||
|
fprintf(stderr, "%s: remainder by zero\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return DC_DOMAIN_ERROR;
|
|||
|
}
|
|||
|
return DC_SUCCESS;
|
|||
|
@@ -226,6 +229,7 @@ dc_sqrt DC_DECLARG((value, kscale, result))
|
|||
|
tmp = bc_copy_num(CastNum(value));
|
|||
|
if (!bc_sqrt(&tmp, kscale)){
|
|||
|
fprintf(stderr, "%s: square root of negative number\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
bc_free_num(&tmp);
|
|||
|
return DC_DOMAIN_ERROR;
|
|||
|
}
|
|||
|
@@ -429,8 +433,10 @@ dc_out_num DC_DECLARG((value, obase, newline_p, discard_p))
|
|||
|
{
|
|||
|
out_char('\0'); /* clear the column counter */
|
|||
|
bc_out_num(CastNum(value), obase, out_char, 0);
|
|||
|
- if (newline_p == DC_WITHNL)
|
|||
|
+ if (newline_p == DC_WITHNL) {
|
|||
|
putchar ('\n');
|
|||
|
+ checkferror_output(stdout);
|
|||
|
+ }
|
|||
|
if (discard_p == DC_TOSS)
|
|||
|
dc_free_num(&value);
|
|||
|
}
|
|||
|
@@ -475,6 +481,7 @@ dc_dump_num DC_DECLARG((dcvalue, discard_p))
|
|||
|
|
|||
|
for (cur=top_of_stack; cur; cur=next) {
|
|||
|
putchar(cur->digit);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
next = cur->link;
|
|||
|
free(cur);
|
|||
|
}
|
|||
|
@@ -592,6 +599,7 @@ out_char (ch)
|
|||
|
out_col = 1;
|
|||
|
}
|
|||
|
putchar(ch);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@@ -631,6 +639,7 @@ rt_error (mesg, va_alist)
|
|||
|
vfprintf (stderr, mesg, args);
|
|||
|
va_end (args);
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@@ -664,6 +673,7 @@ rt_warn (mesg, va_alist)
|
|||
|
vfprintf (stderr, mesg, args);
|
|||
|
va_end (args);
|
|||
|
fprintf (stderr, "\n");
|
|||
|
+ checkferror_output(stderr);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
diff --git a/dc/stack.c b/dc/stack.c
|
|||
|
index 0730e9c..5db3975 100644
|
|||
|
--- a/dc/stack.c
|
|||
|
+++ b/dc/stack.c
|
|||
|
@@ -38,7 +38,10 @@
|
|||
|
#include "dc-regdef.h"
|
|||
|
|
|||
|
/* an oft-used error message: */
|
|||
|
-#define Empty_Stack fprintf(stderr, "%s: stack empty\n", progname)
|
|||
|
+#define Empty_Stack do{ \
|
|||
|
+ fprintf(stderr, "%s: stack empty\n", progname); \
|
|||
|
+ checkferror_output(stderr); \
|
|||
|
+ }while(0)
|
|||
|
|
|||
|
|
|||
|
/* simple linked-list implementation suffices: */
|
|||
|
@@ -94,6 +97,7 @@ dc_binop DC_DECLARG((op, kscale))
|
|||
|
if (dc_stack->value.dc_type!=DC_NUMBER
|
|||
|
|| dc_stack->link->value.dc_type!=DC_NUMBER){
|
|||
|
fprintf(stderr, "%s: non-numeric value\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return;
|
|||
|
}
|
|||
|
(void)dc_pop(&b);
|
|||
|
@@ -134,6 +138,7 @@ dc_binop2 DC_DECLARG((op, kscale))
|
|||
|
if (dc_stack->value.dc_type!=DC_NUMBER
|
|||
|
|| dc_stack->link->value.dc_type!=DC_NUMBER){
|
|||
|
fprintf(stderr, "%s: non-numeric value\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return;
|
|||
|
}
|
|||
|
(void)dc_pop(&b);
|
|||
|
@@ -172,6 +177,7 @@ dc_cmpop DC_DECLVOID()
|
|||
|
if (dc_stack->value.dc_type!=DC_NUMBER
|
|||
|
|| dc_stack->link->value.dc_type!=DC_NUMBER){
|
|||
|
fprintf(stderr, "%s: non-numeric value\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
(void)dc_pop(&b);
|
|||
|
@@ -209,6 +215,7 @@ dc_triop DC_DECLARG((op, kscale))
|
|||
|
|| dc_stack->link->value.dc_type!=DC_NUMBER
|
|||
|
|| dc_stack->link->link->value.dc_type!=DC_NUMBER){
|
|||
|
fprintf(stderr, "%s: non-numeric value\n", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
return;
|
|||
|
}
|
|||
|
(void)dc_pop(&c);
|
|||
|
@@ -327,6 +334,7 @@ dc_register_get DC_DECLARG((regid, result))
|
|||
|
r = dc_register[regid];
|
|||
|
if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){
|
|||
|
fprintf(stderr, "%s: register ", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
dc_show_id(stderr, regid, " is empty\n");
|
|||
|
return DC_FAIL;
|
|||
|
}
|
|||
|
@@ -401,6 +409,7 @@ dc_register_pop DC_DECLARG((stackid, result))
|
|||
|
r = dc_register[stackid];
|
|||
|
if (r == NULL){
|
|||
|
fprintf(stderr, "%s: stack register ", progname);
|
|||
|
+ checkferror_output(stderr);
|
|||
|
dc_show_id(stderr, stackid, " is empty\n");
|
|||
|
return DC_FAIL;
|
|||
|
}
|
|||
|
diff --git a/dc/string.c b/dc/string.c
|
|||
|
index ff1e7f1..e24092d 100644
|
|||
|
--- a/dc/string.c
|
|||
|
+++ b/dc/string.c
|
|||
|
@@ -101,6 +101,7 @@ dc_out_str DC_DECLARG((value, newline, discard_flag))
|
|||
|
fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout);
|
|||
|
if (newline == DC_WITHNL)
|
|||
|
putchar('\n');
|
|||
|
+ checkferror_output(stdout);
|
|||
|
if (discard_flag == DC_TOSS)
|
|||
|
dc_free_str(&value);
|
|||
|
}
|
|||
|
@@ -176,6 +177,7 @@ dc_readstring DC_DECLARG((fp, ldelim, rdelim))
|
|||
|
}
|
|||
|
*p++ = c;
|
|||
|
}
|
|||
|
+ checkferror_input(fp);
|
|||
|
return dc_makestring(line_buf, (size_t)(p-line_buf));
|
|||
|
}
|
|||
|
|
|||
|
diff --git a/h/number.h b/h/number.h
|
|||
|
index 9b034b6..3a00a92 100644
|
|||
|
--- a/h/number.h
|
|||
|
+++ b/h/number.h
|
|||
|
@@ -150,4 +150,7 @@ _PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
|
|||
|
_PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
|
|||
|
int leading_zero));
|
|||
|
|
|||
|
+_PROTOTYPE(void checkferror_input, (FILE*));
|
|||
|
+_PROTOTYPE(void checkferror_output, (FILE*));
|
|||
|
+
|
|||
|
#endif
|
|||
|
diff --git a/lib/number.c b/lib/number.c
|
|||
|
index e211840..4d3ce46 100644
|
|||
|
--- a/lib/number.c
|
|||
|
+++ b/lib/number.c
|
|||
|
@@ -1776,6 +1776,7 @@ static void
|
|||
|
out_char (int c)
|
|||
|
{
|
|||
|
putchar(c);
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@@ -1785,6 +1786,7 @@ pn (num)
|
|||
|
{
|
|||
|
bc_out_num (num, 10, out_char, 0);
|
|||
|
out_char ('\n');
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
@@ -1799,6 +1801,28 @@ pv (name, num, len)
|
|||
|
printf ("%s=", name);
|
|||
|
for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));
|
|||
|
printf ("\n");
|
|||
|
+ checkferror_output(stdout);
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
+
|
|||
|
+/* check ferror() status and if so die */
|
|||
|
+void
|
|||
|
+checkferror_input (fp)
|
|||
|
+ FILE *fp;
|
|||
|
+{
|
|||
|
+ if (ferror(fp)) {
|
|||
|
+ perror("dc: could not read input file");
|
|||
|
+ exit(EXIT_FAILURE);
|
|||
|
+ }
|
|||
|
+}
|
|||
|
+
|
|||
|
+void
|
|||
|
+checkferror_output (fp)
|
|||
|
+ FILE *fp;
|
|||
|
+{
|
|||
|
+ if (ferror(fp)) {
|
|||
|
+ perror("dc: could not write output file");
|
|||
|
+ exit(EXIT_FAILURE);
|
|||
|
+ }
|
|||
|
+}
|