| From af96fb92052c307818eefa4b687f964f1e3f542e Mon Sep 17 00:00:00 2001 |
| From: Matt Weber <matthew.weber@rockwellcollins.com> |
| Date: Thu, 12 Sep 2019 15:04:35 -0500 |
| Subject: [PATCH] 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 |
| |
| Upsteam: |
| https://sources.debian.org/patches/bc/1.07.1-2/05_notice_read_write_errors.diff/ |
| |
| [Reformatted to GIT for 1.0.7.1 by Matt W] |
| Updated by Ryan Kavanagh <rak@debian.org> for 1.0.7.1 on 26 July 2017. |
| Author: Ian Jackson <iwj@ubuntu.com> |
| Origin: other |
| Bug-Debian: http://bugs.debian.org/488735 |
| |
| Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com> |
| --- |
| bc/execute.c | 10 +++++++++- |
| bc/main.c | 3 +++ |
| bc/sbc.y | 2 ++ |
| bc/scan.c | 2 ++ |
| bc/scan.l | 3 +++ |
| bc/util.c | 15 ++++++++++++-- |
| dc/dc.c | 3 +++ |
| dc/eval.c | 55 +++++++++++++++++++++++++++++++++++++++------------- |
| dc/misc.c | 1 + |
| dc/numeric.c | 9 +++++++++ |
| dc/stack.c | 11 ++++++++++- |
| dc/string.c | 2 ++ |
| h/number.h | 11 +++++++---- |
| lib/number.c | 24 +++++++++++++++++++++++ |
| 14 files changed, 129 insertions(+), 22 deletions(-) |
| |
| diff --git a/bc/execute.c b/bc/execute.c |
| index 256e4b7..50eac49 100644 |
| --- a/bc/execute.c |
| +++ b/bc/execute.c |
| @@ -104,6 +104,7 @@ execute (void) |
| } |
| out_char ('\n'); |
| } |
| + checkferror_output(stdout); |
| } |
| #endif |
| |
| @@ -224,6 +225,7 @@ execute (void) |
| } |
| } |
| fflush (stdout); |
| + checkferror_output(stdout); |
| break; |
| |
| case 'R' : /* Return from function */ |
| @@ -259,6 +261,7 @@ execute (void) |
| if (inst == 'W') out_char ('\n'); |
| store_var (4); /* Special variable "last". */ |
| fflush (stdout); |
| + checkferror_output(stdout); |
| pop (); |
| break; |
| |
| @@ -342,6 +345,7 @@ execute (void) |
| 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. */ |
| @@ -549,7 +553,10 @@ execute (void) |
| { |
| signal (SIGINT, use_quit); |
| if (had_sigint) |
| - printf ("\ninterrupted execution.\n"); |
| + { |
| + printf ("\ninterrupted execution.\n"); |
| + checkferror_output(stdout); |
| + } |
| } |
| } |
| |
| @@ -584,6 +591,7 @@ input_char (void) |
| out_col = 0; /* Saw a new line */ |
| } |
| } |
| + checkferror_input(stdin); |
| |
| /* Classify and preprocess the input character. */ |
| if (isdigit(in_ch)) |
| diff --git a/bc/main.c b/bc/main.c |
| index 012075c..c96207b 100644 |
| --- a/bc/main.c |
| +++ b/bc/main.c |
| @@ -353,6 +353,9 @@ use_quit (int sig) |
| errno = save; |
| #else |
| write (1, "\n(interrupt) Exiting bc.\n", 26); |
| +#ifdef READLINE |
| + rl_initialize (); /* Clear readline buffer */ |
| +#endif |
| bc_exit(0); |
| #endif |
| } |
| diff --git a/bc/sbc.y b/bc/sbc.y |
| index 586686b..921ab1e 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 b237f55..8dee4e9 100644 |
| --- a/bc/scan.c |
| +++ b/bc/scan.c |
| @@ -791,6 +791,7 @@ bcel_input (char *buf, yy_size_t *result, int max) |
| if (bcel_len != 0) |
| history (hist, &histev, H_ENTER, bcel_line); |
| fflush (stdout); |
| + checkferror_output(stdout); |
| } |
| |
| if (bcel_len <= max) |
| @@ -863,6 +864,7 @@ rl_input (char *buf, int *result, int 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 eb2e2dd..79186bb 100644 |
| --- a/bc/scan.l |
| +++ b/bc/scan.l |
| @@ -99,6 +99,7 @@ bcel_input (char *buf, yy_size_t *result, int max) |
| if (bcel_len != 0) |
| history (hist, &histev, H_ENTER, bcel_line); |
| fflush (stdout); |
| + checkferror_output(stdout); |
| } |
| |
| if (bcel_len <= max) |
| @@ -171,6 +172,7 @@ rl_input (char *buf, int *result, int max) |
| add_history (rl_line); |
| rl_line[rl_len-1] = '\n'; |
| fflush (stdout); |
| + checkferror_output(stdout); |
| } |
| |
| if (rl_len <= max) |
| @@ -295,6 +297,7 @@ limits return(Limits); |
| if (c == EOF) |
| { |
| fprintf (stderr,"EOF encountered in a comment.\n"); |
| + checkferror_output(stderr); |
| break; |
| } |
| } |
| diff --git a/bc/util.c b/bc/util.c |
| index 8eba093..cacd796 100644 |
| --- a/bc/util.c |
| +++ b/bc/util.c |
| @@ -247,9 +247,10 @@ init_gen (void) |
| 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; |
| @@ -272,6 +273,7 @@ generate (const char *str) |
| printf ("\n"); |
| out_count = 0; |
| } |
| + checkferror_output(stdout); |
| } |
| else |
| load_code (str); |
| @@ -289,6 +291,7 @@ run_code(void) |
| if (compile_only) |
| { |
| printf ("@r\n"); |
| + checkferror_output(stdout); |
| out_count = 0; |
| } |
| else |
| @@ -326,6 +329,7 @@ out_char (int ch) |
| } |
| putchar (ch); |
| } |
| + checkferror_output(stdout); |
| } |
| |
| /* Output routines: Write a character CH to the standard output. |
| @@ -355,6 +359,7 @@ out_schar (int ch) |
| } |
| putchar (ch); |
| } |
| + checkferror_output(stdout); |
| } |
| |
| |
| @@ -639,6 +644,7 @@ limits(void) |
| #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 |
| @@ -703,6 +709,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); |
| } |
| @@ -743,6 +750,7 @@ ct_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 |
| @@ -755,6 +763,7 @@ ct_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); |
| } |
| @@ -789,6 +798,7 @@ rt_error (mesg, va_alist) |
| va_end (args); |
| |
| fprintf (stderr, "\n"); |
| + checkferror_output(stderr); |
| runtime_error = TRUE; |
| } |
| |
| @@ -823,6 +833,7 @@ rt_warn (const char *mesg) |
| va_end (args); |
| |
| fprintf (stderr, "\n"); |
| + checkferror_output(stderr); |
| } |
| |
| /* bc_exit: Make sure to reset the edit state. */ |
| diff --git a/dc/dc.c b/dc/dc.c |
| index 6a2bb26..ccdb1c2 100644 |
| --- a/dc/dc.c |
| +++ b/dc/dc.c |
| @@ -59,6 +59,7 @@ static void |
| bug_report_info DC_DECLVOID() |
| { |
| printf("Email bug reports to: bug-dc@gnu.org .\n"); |
| + checkferror_output(stdout); |
| } |
| |
| static void |
| @@ -69,6 +70,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 */ |
| @@ -85,6 +87,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 05a3d9e..6c54e61 100644 |
| --- a/dc/eval.c |
| +++ b/dc/eval.c |
| @@ -97,12 +97,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 */ |
| @@ -301,11 +304,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 */ |
| @@ -313,11 +318,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; |
| @@ -341,11 +347,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; |
| @@ -378,6 +385,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; |
| @@ -424,6 +432,7 @@ between 2 and %d (inclusive)\n", |
| dc_garbage("at top of stack", -1); |
| } |
| fflush(stdout); |
| + checkferror_output(stdout); |
| break; |
| case 'Q': /* quit out of top-of-stack nested evals; |
| * pops value from stack; |
| @@ -440,6 +449,7 @@ between 2 and %d (inclusive)\n", |
| fprintf(stderr, |
| "%s: Q command requires a number >= 1\n", |
| progname); |
| + checkferror_output(stderr); |
| } |
| break; |
| case 'R': /* pop a value off of the evaluation stack,; |
| @@ -483,11 +493,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); |
| } |
| } |
| @@ -499,18 +510,21 @@ 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"); |
| + checkferror_output(stdout); |
| break; |
| } |
| return DC_OKAY; |
| @@ -538,6 +552,7 @@ evalstr DC_DECLARG((string)) |
| fprintf(stderr, |
| "%s: eval called with non-string argument\n", |
| progname); |
| + checkferror_output(stderr); |
| return DC_OKAY; |
| } |
| interrupt_seen = 0; |
| @@ -635,6 +650,7 @@ evalstr DC_DECLARG((string)) |
| return DC_FAIL; |
| } |
| fprintf(stderr, "%s: unexpected EOS\n", progname); |
| + checkferror_output(stderr); |
| return DC_OKAY; |
| } |
| } |
| @@ -692,6 +708,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: |
| @@ -717,24 +734,30 @@ dc_evalfile DC_DECLARG((fp)) |
| signal(SIGINT, sigint_handler); |
| switch (dc_func(c, peekc, negcmp)){ |
| case DC_OKAY: |
| - if (stdin_lookahead != peekc && fp == stdin) |
| + if (stdin_lookahead != peekc && fp == stdin) { |
| peekc = getc(fp); |
| + checkferror_input(stdin); |
| + } |
| break; |
| case DC_EATONE: |
| peekc = getc(fp); |
| + checkferror_input(fp); |
| break; |
| case DC_EVALREG: |
| /*commands which send us here shall guarantee that peekc!=EOF*/ |
| c = peekc; |
| peekc = getc(fp); |
| + checkferror_input(fp); |
| stdin_lookahead = peekc; |
| if (dc_register_get(c, &datum) != DC_SUCCESS) |
| break; |
| dc_push(datum); |
| /*@fallthrough@*/ |
| case DC_EVALTOS: |
| - if (stdin_lookahead != peekc && fp == stdin) |
| + if (stdin_lookahead != peekc && fp == stdin) { |
| peekc = getc(fp); |
| + checkferror_input(stdin); |
| + } |
| if (dc_pop(&datum) == DC_SUCCESS){ |
| if (datum.dc_type == DC_NUMBER){ |
| dc_push(datum); |
| @@ -744,6 +767,7 @@ dc_evalfile DC_DECLARG((fp)) |
| goto reset_and_exit_quit; |
| fprintf(stderr, "%s: Q command argument exceeded \ |
| string execution depth\n", progname); |
| + checkferror_output(stderr); |
| } |
| }else{ |
| dc_garbage("at top of stack", -1); |
| @@ -756,8 +780,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: |
| diff --git a/dc/misc.c b/dc/misc.c |
| index cd23602..cd910b8 100644 |
| --- a/dc/misc.c |
| +++ b/dc/misc.c |
| @@ -89,6 +89,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 37759de..60cfb85 100644 |
| --- a/dc/numeric.c |
| +++ b/dc/numeric.c |
| @@ -133,6 +133,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; |
| @@ -155,6 +156,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; |
| @@ -173,6 +175,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; |
| @@ -225,6 +228,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; |
| } |
| @@ -470,6 +474,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); |
| } |
| @@ -587,6 +592,8 @@ out_char (ch) |
| out_col = 1; |
| } |
| putchar(ch); |
| + checkferror_output(stdout); |
| + checkferror_output(stderr); |
| } |
| } |
| |
| @@ -626,6 +633,7 @@ rt_error (mesg, va_alist) |
| vfprintf (stderr, mesg, args); |
| va_end (args); |
| fprintf (stderr, "\n"); |
| + checkferror_output(stderr); |
| } |
| |
| |
| @@ -659,6 +667,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 49422df..174411d 100644 |
| --- a/dc/stack.c |
| +++ b/dc/stack.c |
| @@ -35,7 +35,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: */ |
| @@ -91,6 +94,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); |
| @@ -131,6 +135,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); |
| @@ -169,6 +174,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); |
| @@ -206,6 +212,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)) |
| *result = dc_int2data(0); |
| }else if (r->value.dc_type==DC_UNINITIALIZED){ |
| fprintf(stderr, "%s: BUG: register ", progname); |
| + checkferror_output(stderr); |
| dc_show_id(stderr, regid, " exists but is uninitialized?\n"); |
| return DC_FAIL; |
| }else{ |
| @@ -402,6 +410,7 @@ dc_register_pop DC_DECLARG((stackid, result)) |
| r = dc_register[stackid]; |
| if (r==NULL || r->value.dc_type==DC_UNINITIALIZED){ |
| 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 dee9169..389d899 100644 |
| --- a/dc/string.c |
| +++ b/dc/string.c |
| @@ -94,6 +94,7 @@ dc_out_str DC_DECLARG((value, discard_flag)) |
| dc_discard discard_flag DC_DECLEND |
| { |
| fwrite(value->s_ptr, value->s_len, sizeof *value->s_ptr, stdout); |
| + checkferror_output(stdout); |
| if (discard_flag == DC_TOSS) |
| dc_free_str(&value); |
| } |
| @@ -169,6 +170,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 abf6332..1983ab4 100644 |
| --- a/h/number.h |
| +++ b/h/number.h |
| @@ -23,10 +23,10 @@ |
| You may contact the author by: |
| e-mail: philnelson@acm.org |
| us-mail: Philip A. Nelson |
| - Computer Science Department, 9062 |
| - Western Washington University |
| - Bellingham, WA 98226-9062 |
| - |
| + Computer Science Department, 9062 |
| + Western Washington University |
| + Bellingham, WA 98226-9062 |
| + |
| *************************************************************************/ |
| |
| #ifndef _NUMBER_H_ |
| @@ -140,4 +140,7 @@ void bc_out_num (bc_num num, int o_base, void (* out_char)(int), |
| int leading_zero); |
| |
| void bc_out_long (long val, int size, int space, void (*out_char)(int)); |
| + |
| +void checkferror_input (FILE*); |
| +void checkferror_output (FILE*); |
| #endif |
| diff --git a/lib/number.c b/lib/number.c |
| index f394e92..80b33e3 100644 |
| --- a/lib/number.c |
| +++ b/lib/number.c |
| @@ -1713,6 +1713,7 @@ static void |
| out_char (int c) |
| { |
| putchar(c); |
| + checkferror_output(stdout); |
| } |
| |
| |
| @@ -1721,6 +1722,7 @@ pn (bc_num num) |
| { |
| bc_out_num (num, 10, out_char, 0); |
| out_char ('\n'); |
| + checkferror_output(stdout); |
| } |
| |
| |
| @@ -1732,6 +1734,28 @@ pv (char *name, unsigned char *num, int 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); |
| + } |
| +} |
| -- |
| 2.17.1 |
| |