Using files

    The calculator provides some functions which allow the program to
    read or write text files.  These functions use stdio internally,
    and the functions appear similar to some of the stdio functions.
    Some differences do occur, as will be explained here.

    Names of files are subject to ~ expansion just like the C or
    Korn shell.	 For example, the file name:

	    ~/.rc.cal

    refers to the file '.rc.cal' under your home directory.  The
    file name:

	    ~chongo/.rc.cal

    refers to the a file 'rc.cal' under the home directory of 'chongo'.

    A file can be opened for either reading, writing, or appending.
    To do this, the 'fopen' function is used, which accepts a filename
    and an open mode, both as strings.	You use 'r' for reading, 'w'
    for writing, and 'a' for appending.	 For example, to open the file
    'foo' for reading, the following could be used:

	    fd = fopen('foo', 'r');

    If the open is unsuccessful, the numeric value of errno is returned.
    If the open is successful, a value of type 'file' will be returned.
    You can use the 'isfile' function to test the return value to see
    if the open succeeded.  You should assign the return value of fopen
    to a variable for later use.  File values can be copied to more than
    one variable, and using any of the variables with the same file value
    will produce the same results.

    If you overwrite a variable containing a file value or don't save the
    result of an 'fopen', the opened file still remains open.  Such 'lost'
    files can be recovered by using the 'files' function.  This function
    either takes no arguments or else takes one integer argument.  If no
    arguments are given, then 'files' returns the maximum number of opened
    files.  If an argument is given, then the 'files' function uses it as
    an index into an internal table of open files, and returns a value
    referring to one the open files.  If that entry in the table is not
    in use, then the null value is returned instead.  Index 0 always
    refers to standard input, index 1 always refers to standard output,
    and index 2 always refers to standard error.  These three files are
    already open by the calculator and cannot be closed.  As an example
    of using 'files', if you wanted to assign a file value which is
    equivalent to stdout, you could use:

	    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
    file-related calls (except fclose) without causing errors.	This same
    action occurs to all copies of the file value.  You do not need to
    explicitly close all the copies of a file value.  The 'fclose'
    function returns the numeric value of errno if there had been an
    error using the file, or the null value if there was no error.

    The builtin 'strerror' can be use to convert an errno number into
    a slightly more meaningful error message:

	    badfile = fopen("not_a_file", "r");
	    if (!isfile(badfile)) {
		print "error #" : badfile : ":", strerror(badfile);
	    }

    File values can be printed.	 When this is done, the filename of the
    opened file is printed inside of quote marks.  If the file value had
    been closed, then the null string is printed.  If a file value is the
    result of a top-level expression, then in addition to the filename,
    the open mode, file position, and possible EOF, error, and closed
    status is also displayed.

    File values can be used inside of 'if' tests.  When this is done,
    an opened file is TRUE, and a closed file is FALSE.	 As an example
    of this, the following loop will print the names of all the currently
    opened non-standard files with their indexes, and then close them:

	    for (i = 3; i < files(); i++) {
		    if (files(i)) {
			    print i, files(i);
			    fclose(files(i));
		    }
	    }

    The functions to read from files are 'fgetline' and 'fgetc'.
    The 'fgetline' function accepts a file value, and returns the next
    input line from a file.  The line is returned as a string value, and
    does not contain the end of line character.	 Empty lines return the
    null string.  When the end of file is reached, fgetline returns the
    null value.	 (Note the distinction between a null string and a null
    value.)  If the line contained a numeric value, then the 'eval'
    function can then be used to convert the string to a numeric value.
    Care should be used when doing this, however, since eval will
    generate an error if the string doesn't represent a valid expression.
    The 'fgetc' function returns the next character from a file as a
    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
    use of 'files(1)' (stdout).	 They both require a format string, which
    is used in almost the same way as in normal C.  The differences come
    in the interpretation of values to be printed for various formats.
    Unlike in C, where an unmatched format type and value will cause
    problems, in the calculator nothing bad will happen.  This is because
    the calculator knows the types of all values, and will handle them
    all reasonably.  What this means is that you can (for example), always
    use %s or %d in your format strings, even if you are printing a non-
    string or non-numeric value.  For example, the following is valid:

	    printf("Two values are %d and %s\n", "fred", 4567);

    and will print "Two values are fred and 4567".

    Using particular format characters, however, is still useful if
    you wish to use width or precision arguments in the format, or if
    you wish to print numbers in a particular format.  The following
    is a list of the possible numeric formats:

	    %d		print in currently defined numeric format
	    %f		print as floating point
	    %e		print as exponential
	    %r		print as decimal fractions
	    %x		print as hex fractions
	    %o		print as octal fractions
	    %b		print as binary fractions

    Note then, that using %d in the format makes the output configurable
    by using the 'config' function to change the output mode, whereas
    the other formats override the mode and force the output to be in
    the specified format.

    Using the precision argument will override the 'config' function
    to set the number of decimal places printed.  For example:

	    printf("The number is %.100f\n", 1/3);

    will print 100 decimal places no matter what the display configuration
    value is set to.

    The %s and %c formats are identical, and will print out the string
    representation of the value.  In these cases, the precision argument
    will truncate the output the same way as in standard C.

    If a matrix or list is printed, then the output mode and precision
    affects the printing of each individual element.  However, field
    widths are ignored since these values print using multiple lines.
    Field widths are also ignored if an object value prints on multiple
    lines.

    The functions 'fputc' and 'fputs' write a character and string to
    a file respectively.

    The final file-related functions are 'fflush', 'ferror', and 'feof'.
    The 'fflush' function forces buffered output to a file.  The 'ferror'
    function returns nonzero if an error had occurred to a file.  The
    'feof' function returns nonzero if end of file has been reached
    while reading a file.

    The 'strprintf' function formats output similarly to 'printf',
    but the output is returned as a string value instead of being
    printed.

## Copyright (C) 1999-2006  Landon Curt Noll
##
## Calc is open software; you can redistribute it and/or modify it under
## the terms of the version 2.1 of the GNU Lesser General Public License
## as published by the Free Software Foundation.
##
## Calc is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
## or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
## Public License for more details.
##
## A copy of version 2.1 of the GNU Lesser General Public License is
## distributed with calc under the filename COPYING-LGPL.  You should have
## received a copy with calc; if not, write to Free Software Foundation, Inc.
## 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
##
## Under source code control:	1991/07/21 04:37:19
## File existed as early as:	1991
##
## chongo <was here> /\oo/\	http://www.isthe.com/chongo/
## Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
