Fixed reading from stdin with calc -p

This commit is contained in:
Landon Curt Noll
2017-05-25 17:24:57 -07:00
parent 2c659f40ff
commit 1363b58060
6 changed files with 115 additions and 5 deletions

11
CHANGES
View File

@@ -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:

View File

@@ -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 $@

23
calc.c
View File

@@ -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);

View File

@@ -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

View 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

11
input.c
View File

@@ -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--;