diff --git a/CHANGES b/CHANGES index 4237163..6299bf6 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,17 @@ The following are the changes from calc version 2.12.6.0 to date: Renamed README to README.FIRST. Added README.md for the GitHub repository. + Fixed reading from standard input (stdin) when -p is given on + the comamnd line. This now prints hello: + + echo hello | calc -p 'stdin = files(0); print fgetline(stdin);' + + Added more debugging realted to stdin when bit 4 of calc_debug + is set (e.g., running calc with -D16). + + Updated the calc(1) man page and 'help file' to explain about + reading from standard input (stdin). + The following are the changes from calc version 2.12.5.4 to 2.12.5.6: diff --git a/Makefile.ship b/Makefile.ship index cbbad87..d7a7142 100644 --- a/Makefile.ship +++ b/Makefile.ship @@ -2268,7 +2268,7 @@ calc.1: calc.man ${MAKE_FILE} -e 's,$${CUSTOMINCDIR},${CUSTOMINCDIR},g' \ -e 's,$${CUSTOMHELPDIR},${CUSTOMHELPDIR},g' \ -e 's,$${CALCRC},${CALCRC},g' < calc.man > calc.1 - ${Q} echo calc.man formed + ${Q} echo calc.1 formed calc.usage: calc.1 ${MAKE_FILE} ${RM} -f $@ diff --git a/calc.c b/calc.c index 4cfcb8d..ecd098a 100644 --- a/calc.c +++ b/calc.c @@ -110,6 +110,7 @@ main(int argc, char **argv) BOOL done = FALSE; BOOL havearg; BOOL haveendstr; + BOOL stdin_closed = FALSE; size_t len; /* @@ -483,8 +484,11 @@ main(int argc, char **argv) if (havecommands) { cmdbuf[cmdlen++] = '\n'; cmdbuf[cmdlen] = '\0'; - if (fclose(stdin)) { - perror("main(): fclose(stdin) failed:"); + if (p_flag != TRUE) { + if (fclose(stdin)) { + perror("main(): fclose(stdin) failed:"); + } + stdin_closed = TRUE; } } @@ -495,7 +499,9 @@ main(int argc, char **argv) * unbuffered mode */ if (u_flag) { - setbuf(stdin, NULL); + if (stdin_closed == FALSE) { + setbuf(stdin, NULL); + } setbuf(stdout, NULL); } @@ -504,6 +510,17 @@ main(int argc, char **argv) * initialize */ libcalc_call_me_first(); + if (u_flag) { + if (conf->calc_debug & CALCDBG_TTY) { + if (stdin_closed == FALSE) { + printf("main: stdin set to unbuffered before " + "calling libcalc_call_me_first()\n"); + } else { + printf("main: stdin closed before " + "calling libcalc_call_me_first()\n"); + } + } + } stdin_tty = isatty(0); /* assume stdin is on fd 0 */ if (conf->calc_debug & CALCDBG_TTY) printf("main: stdin_tty is %d\n", stdin_tty); diff --git a/calc.man b/calc.man index 4432fd5..c9f4f49 100644 --- a/calc.man +++ b/calc.man @@ -554,6 +554,40 @@ print 27! ^2 or print 27\!^2 .fi .in -5n +Reading from standard input when calc is part of a pipe works +as long as the \-p flag is given to calc. For example, this +will print chongo was here: +.sp 1 +.in +5n +.nf +echo chongo was here | calc \-p 'print fgetline(files(0));' +.sp 1 +.fi +.in -5n +.sp 1 +while this does not: +.sp 1 +.in +5n +.nf +echo chongo was here | calc 'print fgetline(files(0));' +.sp 1 +.fi +.in -5n +.sp 1 +nor will this print chongo was here: +.sp 1 +.in +5n +.nf +echo chongo was here | calc \-i 'print fgetline(files(0));' +.sp 1 +.fi +.in -5n +.sp 1 +This is because without \-p, the interactive parser, in an effort +to parse interactive commands, flushes data on standard input. + +.PP + \& .br CALC STARTUP FILES diff --git a/help/file b/help/file index 5ee121a..ec8e179 100644 --- a/help/file +++ b/help/file @@ -50,6 +50,15 @@ Using files stdout = files(1); + Or for example, if you wanted to assign a file value which is + equivalent to stdin, you could use: + + stdout = files(0); + + And for stderr: + + stderr = files(2); + The 'fclose' function is used to close a file which had been opened. When this is done, the file value associated with the file remains a file value, but appears 'closed', and cannot be used in further @@ -100,6 +109,36 @@ Using files single character string. It returns the null value when end of file is reached. + Reading from standard input when calc is part of a pipe works + as long as the -p flag is given to calc. For example, this + will print "chongo was here": + + echo chongo was here | calc -p 'print fgetline(files(0));' + + while this does not: + + echo chongo was here | calc 'print fgetline(files(0));' + + nor will this print "chongo was here": + + echo chongo was here | calc -i 'print fgetline(files(0));' + + This is because without -p, the interactive parser, in an effort + to parse interactive commands, flushes data on standard input. + + On the other hand, once interactive mode is entered, reading + from standard input works as expected. For example, this works: + + $ calc + C-style arbitrary precision calculator (version 2.12.6.0) + Calc is open software. For license details type: help copyright + [Type "exit" to exit, or "help" for help.] + + ; str = fgetline(files(0)) + this text was typed into stdin + ; print str + this text was typed into stdin + The 'printf' and 'fprintf' functions are used to print results to a file (which could be stdout or stderr). The 'fprintf' function accepts a file variable, whereas the 'printf' function assumes the diff --git a/input.c b/input.c index 4ab646a..166bab7 100644 --- a/input.c +++ b/input.c @@ -361,6 +361,10 @@ f_pathopen(char *name, char *mode, char *pathlist, char **openpath) } if (*openpath == NULL) { free(path); + if ((conf->calc_debug & CALCDBG_TTY) && ret == stdin) { + printf("f_pathopen: closing stdin " + "on malloc return error\n"); + } fclose(ret); math_error("cannot malloc return openpath buffer"); /*NOTREACHED*/ @@ -647,8 +651,13 @@ closeinput(void) return; if (cip->i_str) free(cip->i_str); - if (cip->i_fp) + if (cip->i_fp) { + if ((conf->calc_debug & CALCDBG_TTY) && cip->i_fp == stdin) { + printf("closeinput: closing stdin " + "at depth: %d\n", depth); + } fclose(cip->i_fp); + } if (cip->i_name) free(cip->i_name); depth--;