aboutsummaryrefslogtreecommitdiff
path: root/sys/libc
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /sys/libc
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'sys/libc')
-rw-r--r--sys/libc/Libc.hlp559
-rw-r--r--sys/libc/README208
-rw-r--r--sys/libc/atof.c24
-rw-r--r--sys/libc/atoi.c48
-rw-r--r--sys/libc/atol.c49
-rw-r--r--sys/libc/caccess.c22
-rw-r--r--sys/libc/calloc.c27
-rw-r--r--sys/libc/callocate.c80
-rw-r--r--sys/libc/cclktime.c35
-rw-r--r--sys/libc/cclose.c23
-rw-r--r--sys/libc/ccnvdate.c25
-rw-r--r--sys/libc/ccnvtime.c25
-rw-r--r--sys/libc/cdelete.c20
-rw-r--r--sys/libc/cenvget.c143
-rw-r--r--sys/libc/cenvlist.c32
-rw-r--r--sys/libc/cenvmark.c54
-rw-r--r--sys/libc/cenvscan.c32
-rw-r--r--sys/libc/cerract.c21
-rw-r--r--sys/libc/cerrcode.c15
-rw-r--r--sys/libc/cerrget.c27
-rw-r--r--sys/libc/cerror.c20
-rw-r--r--sys/libc/cfchdir.c19
-rw-r--r--sys/libc/cfilbuf.c36
-rw-r--r--sys/libc/cfinfo.c30
-rw-r--r--sys/libc/cflsbuf.c43
-rw-r--r--sys/libc/cflush.c20
-rw-r--r--sys/libc/cfmapfn.c36
-rw-r--r--sys/libc/cfmkdir.c20
-rw-r--r--sys/libc/cfnextn.c26
-rw-r--r--sys/libc/cfnldir.c26
-rw-r--r--sys/libc/cfnroot.c25
-rw-r--r--sys/libc/cfpath.c34
-rw-r--r--sys/libc/cfredir.c46
-rw-r--r--sys/libc/cfseti.c22
-rw-r--r--sys/libc/cfstati.c21
-rw-r--r--sys/libc/cgetpid.c15
-rw-r--r--sys/libc/cgetuid.c24
-rw-r--r--sys/libc/cgflush.c20
-rw-r--r--sys/libc/cimaccess.c28
-rw-r--r--sys/libc/cimdrcur.c39
-rw-r--r--sys/libc/ckimapc.c28
-rw-r--r--sys/libc/clexnum.c54
-rw-r--r--sys/libc/cmktemp.c27
-rw-r--r--sys/libc/cndopen.c25
-rw-r--r--sys/libc/cnote.c29
-rw-r--r--sys/libc/copen.c26
-rw-r--r--sys/libc/coscmd.c33
-rw-r--r--sys/libc/cpoll.c150
-rw-r--r--sys/libc/cprcon.c198
-rw-r--r--sys/libc/cprdet.c109
-rw-r--r--sys/libc/cprintf.c53
-rw-r--r--sys/libc/crcursor.c28
-rw-r--r--sys/libc/crdukey.c28
-rw-r--r--sys/libc/cread.c70
-rw-r--r--sys/libc/crename.c26
-rw-r--r--sys/libc/creopen.c27
-rw-r--r--sys/libc/csalloc.c80
-rw-r--r--sys/libc/cseek.c42
-rw-r--r--sys/libc/csppstr.c31
-rw-r--r--sys/libc/cstropen.c26
-rw-r--r--sys/libc/cstrpak.c35
-rw-r--r--sys/libc/cstrupk.c41
-rw-r--r--sys/libc/ctsleep.c18
-rw-r--r--sys/libc/cttset.c88
-rw-r--r--sys/libc/cttycdes.c19
-rw-r--r--sys/libc/cttyclear.c21
-rw-r--r--sys/libc/cttyclln.c22
-rw-r--r--sys/libc/cttyctrl.c27
-rw-r--r--sys/libc/cttygetb.c24
-rw-r--r--sys/libc/cttygeti.c23
-rw-r--r--sys/libc/cttygetr.c22
-rw-r--r--sys/libc/cttygets.c34
-rw-r--r--sys/libc/cttygoto.c23
-rw-r--r--sys/libc/cttyinit.c22
-rw-r--r--sys/libc/cttyodes.c89
-rw-r--r--sys/libc/cttyputl.c28
-rw-r--r--sys/libc/cttyputs.c29
-rw-r--r--sys/libc/cttyseti.c22
-rw-r--r--sys/libc/cttyso.c23
-rw-r--r--sys/libc/cttystati.c21
-rw-r--r--sys/libc/ctype.c31
-rw-r--r--sys/libc/cungetc.c28
-rw-r--r--sys/libc/cungetl.c31
-rw-r--r--sys/libc/cvfnbrk.c30
-rw-r--r--sys/libc/cwmsec.c20
-rw-r--r--sys/libc/cwrite.c51
-rw-r--r--sys/libc/cxgmes.c29
-rw-r--r--sys/libc/cxonerr.c19
-rw-r--r--sys/libc/cxttysize.c25
-rw-r--r--sys/libc/cxwhen.c63
-rw-r--r--sys/libc/eprintf.c25
-rw-r--r--sys/libc/fclose.c23
-rw-r--r--sys/libc/fdopen.c76
-rw-r--r--sys/libc/fflush.c24
-rw-r--r--sys/libc/fgetc.c19
-rw-r--r--sys/libc/fgets.c43
-rw-r--r--sys/libc/fopen.c61
-rw-r--r--sys/libc/fputc.c20
-rw-r--r--sys/libc/fputs.c22
-rw-r--r--sys/libc/fread.c55
-rw-r--r--sys/libc/freadline.c34
-rw-r--r--sys/libc/free.c22
-rw-r--r--sys/libc/freopen.c56
-rw-r--r--sys/libc/fseek.c93
-rw-r--r--sys/libc/ftell.c21
-rw-r--r--sys/libc/fwrite.c36
-rw-r--r--sys/libc/gets.c34
-rw-r--r--sys/libc/getw.c28
-rw-r--r--sys/libc/index.c26
-rw-r--r--sys/libc/isatty.c20
-rw-r--r--sys/libc/libc_proto.h326
-rw-r--r--sys/libc/malloc.c24
-rw-r--r--sys/libc/mathf.f75
-rw-r--r--sys/libc/mkpkg168
-rw-r--r--sys/libc/mktemp.c24
-rw-r--r--sys/libc/perror.c36
-rw-r--r--sys/libc/printf.c245
-rw-r--r--sys/libc/puts.c25
-rw-r--r--sys/libc/putw.c27
-rw-r--r--sys/libc/qsort.c221
-rw-r--r--sys/libc/realloc.c28
-rw-r--r--sys/libc/rewind.c19
-rw-r--r--sys/libc/rindex.c27
-rw-r--r--sys/libc/scanf.c558
-rw-r--r--sys/libc/setbuf.c68
-rw-r--r--sys/libc/spf.c65
-rw-r--r--sys/libc/sprintf.c58
-rw-r--r--sys/libc/stgio.c60
-rw-r--r--sys/libc/strcat.c24
-rw-r--r--sys/libc/strcmp.c22
-rw-r--r--sys/libc/strcpy.c21
-rw-r--r--sys/libc/strdup.c22
-rw-r--r--sys/libc/strlen.c21
-rw-r--r--sys/libc/strncat.c26
-rw-r--r--sys/libc/strncmp.c22
-rw-r--r--sys/libc/strncpy.c27
-rw-r--r--sys/libc/system.c26
-rw-r--r--sys/libc/ungetc.c29
-rw-r--r--sys/libc/zzdebug.x7
-rw-r--r--sys/libc/zztest.c98
140 files changed, 7204 insertions, 0 deletions
diff --git a/sys/libc/Libc.hlp b/sys/libc/Libc.hlp
new file mode 100644
index 00000000..e13faeea
--- /dev/null
+++ b/sys/libc/Libc.hlp
@@ -0,0 +1,559 @@
+.help LIBC Sep84 "C Runtime Library"
+.sp 2
+.ce
+\fBIRAF Runtime Library for the C Language\fR
+.ce
+CL Interface to IRAF
+.sp 3
+.nh
+Introduction
+
+ The IRAF runtime library for the C language was developed to port the
+IRAF command language (CL) from UNIX to IRAF. The C runtime library (LIBC)
+consists of two parts: an emulation of the standard i/o library provided
+for the C language on an UNIX host, and a library of "system calls", i.e.,
+the C interface to the IRAF virtual operating system.
+
+.nh
+Naming Conventions
+
+ Providing familiar and predictable procedure names in C is complicated
+by the possibility of name collisions with external names in the program
+interface libraries. To solve this problem while maintaining compatibility
+with UNIX the external names of all UNIX emulation procedures are assigned
+in C \fIdefine\fR statements. The external name is simply the UNIX name
+preceded by the prefix "u_", e.g.,
+
+ fopen()
+
+compiles as
+
+ u_fopen()
+
+The names of the "system calls" are not compatible with those of the UNIX
+system calls. Each system call maps directly to an IRAF program interface
+procedure. The name of the C version is the IRAF name preceded by the
+prefix "c_", e.g.,
+
+ open()
+
+is called in C as
+
+ c_open()
+
+The "c_" names are not redefined except where necessary to produce an
+external identifier unique in the first seven characters. When an external
+name is redefined to make it unique in the first seven characters this
+is done by application of the 4+1 rule, leaving the "c_" prefix as is.
+The calling sequences of the C system calls have been kept as compatible
+with the "crib sheet" versions as possible, even when a more convenient
+syntax could have been used for C.
+
+.nh
+Include Files
+
+ C style global include files pose a problem in a portable system since
+machine dependent filenames cannot be used. This problem is sidestepped
+for LIBC by using the C language preprocessor to indirectly reference the
+global include files via a single master include file installed in the
+C system include file directory. The master include file is referenced
+as <iraf.h>. The actual include files reside in the IRAF directory system
+(as does a copy of <iraf.h>) and hence are automatically ported with the
+system. The pathname to the LIBC global include files is arbitrary, but
+currently these files are stored in lib$libc.
+
+The technique used to access LIBC global include files in perhaps best
+explained by use of a simple example from the CL:
+
+
+.ks
+.nf
+ #define import_spp global includes
+ #define import_libc
+ #define import_stdio
+ #include <iraf.h>
+
+ #include "config.h" local includes
+ #include "operand.h"
+ #include "param.h"
+ #include "task.h"
+.fi
+.ke
+
+
+The include file <iraf.h> contains preprocessor control lines which load
+the include files referenced by "#define import_packagename" statements.
+In addition to being portable, this technique has the benefits of ensuring
+that the include files are loaded in the correct order and are not loaded
+more than once.
+
+The include file referenced by \fIimport_libc\fR should be included in
+every C source file which uses LIBC. In addition to loading the referenced
+include files, <iraf.h> also includes definitions for the IRAF root
+directory IRAFDIR, the default image storage directory IMAGEDIR, and the
+name of the host operating system (e.g. "UNIX" or "VMS").
+
+.nh
+UNIX Emulation
+
+ All procedures in the UNIX standard i/o (stdio) package are emulated
+in libc. A listing of the calling sequences of all currently implemented
+procedures is given as an appendix. The syntax and semantics of these
+procedures have been kept as close to those of the V7 UNIX procedures as
+possible.
+
+.nh
+IRAF Program Interface Routines
+
+ All i/o in the CL is implemented ultimately by calls to procedures in
+the IRAF program interface libraries. The UNIX emulation procedures
+discussed in the previous sections, for example, are reasonably portable
+C language packages which call C versions of the IRAF program interface
+routines. With few exceptions the C version of each procedure maps trivially
+to the corresponding program interface procedure. The main complication
+arises from the need to pack and unpack character strings when calling an
+SPP (Fortran) procedure from C. Read only arguments are passed by value
+for the convenience of the C language progammer.
+
+The full program interface contains on the order of a thousand procedures
+(including generics) and it would be prohibitively difficult to make them
+all available in C. We have therefore included only the packages actually
+used by the CL in the interface, and then only the most commonly used
+procedures in each package. All files which directly reference program
+interface procedures should include a reference to the C language include
+file \fBirafio.h\fR.
+
+.nh 2
+File I/O (FIO)
+
+ The fundamental unit of storage in both C and SPP is the \fBchar\fR,
+but unfortunately a char is not necessarily the same size in both languages.
+In the C version of FIO data is referenced in units of C chars (bytes),
+subject to the restriction that only an \fIintegral\fR number of SPP chars
+can be read and written at a time, and seeks must be aligned on a char
+boundary. If a nonintegral number of SPP chars are read or written,
+the interface will silently move the extra bytes necessary to fill out
+an SPP char, possibly writing beyond the end of the input buffer on a read.
+These problems are less serious than it might seem, however, since CL level
+i/o is predominantly text only (binary file i/o is not currently used in
+the CL).
+
+In keeping with the C language tradition, all FIO offsets are \fIzero\fR
+indexed, and all integer valued procedures return ERR as the function value
+in the event of an error. Pointer valued functions return NULL in the
+event of an error. Although only "significant" function values are shown in the
+calling sequences below, all procedures return a function value.
+
+
+.ks
+.nf
+High Level FIO:
+
+ fd = c_open (vfn, mode, type)
+ c_close (fd)
+ c_flush (fd)
+
+ c_fseti (fd, param, value)
+ int = c_fstati (fd, param)
+
+ stat = c_finfo (vfn, &fi)
+ y/n = c_access (vfn, mode, type)
+ c_delete (vfn)
+ c_rename (old_vfn, new_vfn)
+ c_mktemp (root, &fname, maxch)
+.fi
+.ke
+
+
+The "low level" FIO procedures perform binary file i/o and fill and flush
+the internal FIO file buffer. These procedures are called by the STDIO
+package and are not intended to be called directly by general CL code.
+Seeking is not implemented in STDIO due to the difficulty of implementing
+\fBfseek\fR in a portable system, but is not currently required anywhere
+in the CL. STDIO directly accesses the internal FIO buffer pointers
+via a data structure defined in \fBirafio.h\fR.
+
+
+.ks
+.nf
+Low Level FIO:
+
+ nchars = c_read (fd, &buf, maxch)
+ c_write (fd, &buf, nchars)
+ c_seek (fd, loffset)
+ loffset = c_note (fd)
+
+ ch = c_filbuf (fd)
+ ch = c_flsbuf (fd, ch)
+ FILE = c_fioptr (fd)
+.fi
+.ke
+
+
+The file access modes and types are specified as in SPP, i.e., via predefined
+integer constants defined in \fIirafio.h\fR (READ_ONLY, NEW_FILE, etc.).
+Only a few \fBfset\fR options are implemented; these are likewise defined
+in \fIirafio.h\fR. The integer constants STDIN, STDOUT, etc. refer to
+FIO file descriptors, and should not be confused with \fBstdin\fR,
+\fBstdout\fR, etc., which reference STDIO file pointers.
+
+.nh 2
+Environment Facilities
+
+ The environment list is managed entirely by the program interface via
+the ENV package. The CL calls ENV procedures to create, modify, and access
+the environment list. The \fBc_propen\fR procedure in the program interface
+passes the environment list on to a connected child process at process
+creation time.
+
+
+.ks
+.nf
+ nchars = c_envgets (name, &value, maxch)
+ redef = c_envputs (name, &value)
+ c_envmark (&sp)
+ nredefs = c_envfree (sp)
+
+ bool = c_envgetb (name)
+ int = c_envgeti (name)
+ c_envlist (out_fd, prefix, show_redefs)
+ nscan = c_envscan (input_source)
+.fi
+.ke
+
+The following (non program interface) procedure is defined and used internally
+by the CL to lookup names in the environment list:
+
+ strp = envget (name)
+
+.nh 3
+Implementation Notes
+
+ The environment list is maintained as a multi-threaded linked list. This
+provides the searching efficiency of a hash table plus stack like semantics
+for redefinitions and for freeing blocks of variables. There are two primary
+data structures internally, an array of pointers to the heads of the threads,
+and a buffer containing the list elements. These data structures are
+dynamically allocated and will be automatically reallocated at runtime if
+overflow occurs. The number of threads determines the hashing efficiency and
+is a compile time parameter.
+
+The \fBenvmark\fR and \fBenvfree\fR procedures
+mark and free storage on the environment list stack.
+All environment variables defined or redefined after a call to \fBenvmark\fR
+will be deleted and storage freed by a call to \fBenvfree\fR. If a redef
+is freed the next most recent definition becomes current. \fBEnvfree\fR returns
+as its function value the number of redefined variables uncovered by the free
+operation. The calling program must mark and free in the correct order or the
+environment list may be trashed.
+
+The \fBenvlist\fR procedure prints the environment list on a file.
+Redefined values will be printed only if so indicated.
+The environment list is printed as a list of
+\fBset\fR statements in most recent first order, i.e.,
+
+
+.ks
+.nf
+ set nameN=valueN
+ set nameM=valueM
+ ...
+ set name1=value1
+.fi
+.ke
+
+
+The \fBenvlist\fR function is used both to inspect the environment list
+and to pass the list on to a child process.
+Redefined variables are omitted when passing
+the list on to a child process, hence the order of definition does not matter.
+The output format is "prefix name=value", where the prefix string is supplied
+by the user.
+
+The \fBenvscan\fR function parses one or more \fBset\fR statements,
+calling \fBenvputs\fR to enter the SET declarations into the environment list.
+The argument is either a \fBset\fR declaration or a string of the form
+"set @filename", where "filename" is the name of a file containing \fBset\fR
+declarations.
+
+.nh 2
+Process Control
+
+ Separate facilities are provided for \fBconnected\fR and \fBdetached\fR
+processes. Virtually all process control is concerned with connected
+subprocesses, i.e., subprocesses running synchronously with the CL and
+communicating with the CL via bidirectional IPC channels. The only detached
+process in the system is the CL itself, when spawned as a background job
+by another (usually interactive) CL process.
+
+.nh 3
+Connected Subprocesses
+
+ A connected subprocess is connected with \fBpropen\fR and disconnected
+with \fBprclose\fR. The \fBpropen\fR procedure spawns the named process,
+connects the IPC channels to FIO file descriptors, then sends commands to
+the child process to initialize the environment and current working directory.
+Once connected the \fIin\fR and \fIout\fR file descriptors may be reopened
+with \fBfdopen\fR for UNIX style i/o to the subprocess. The \fBprclose\fR
+procedure sends the "bye" (shutdown) command to the child, waits for the
+child to terminate, and then returns the process termination status as the
+function value. Normal exit status is OK, otherwise a positive integer
+error code is returned.
+
+
+.ks
+.nf
+ pid = c_propen (process, in, out)
+ stat = c_prclose (pid)
+ c_prsignal (pid, signal)
+ c_prredir (pid, stream, new_fd)
+ c_prupdate (message)
+.fi
+.ke
+
+
+To execute a task in a connected child process the CL writes a command to
+the \fIout\fR channel with a conventional \fBfputs\fR or other STDIO call.
+After starting the task the CL redirects its command input to the \fIin\fR
+channel of the task; conventional \fBfgets\fR or \fBgetc\fR calls are made
+to read commands from the task, until "bye" is received, signaling task
+termination.
+
+New \fBset\fR or \fBchdir\fR statements may be broadcast to all connected
+subprocesses at any time (except while actually executing a task resident
+in a connected subprocess) by a call to \fBprupdate\fR. While there is no
+way the CL can free space on the environment stack in a child process, it is
+possible to broadcast new redefinitions to all child processes if redefinitions
+should be uncovered by an \fBenvfree\fR call in the CL.
+
+The \fBprsignal\fR procedure is used to raise the interrupt exception X_INT
+in a connected child process. When the user types interrupt (e.g. ctrl/c)
+at the CL level, the CL interrupt exception handler signals the child
+process containing the external task currently in execution (if any),
+and then resumes processing of commands from the child. If a special exception
+handler is not posted in the child it will go through error restart,
+eventually sending the \fBerror\fR statement to the CL indicating abnormal
+termination of the task. Note that it is permissible for a child process
+to ignore the interrupt exception, or take special recovery actions if
+interrupt occurs.
+
+.nh 4
+I/O Redirection
+
+ Pseudofile i/o (\fBxmit\fR and \fBxfer\fR directives for the task's STDIN,
+STDOUT, etc.) is handled by the program interface transparently to the CL.
+By default the standard i/o streams of the child are connected to the
+identical streams of the parent (the CL). If redirection of a stream
+is desired the stream may be redirected in either of two ways:
+.ls
+.ls [1]
+A stdio stream may be redirected directly at the task level in the child
+process by including redirection information on the command line sent to
+the child to execute the task. This is the most efficient technique, and
+it should be used when appropriate, e.g., for pipes or whenever an output
+stream of an external task is explicitly redirected on the CL command line.
+The syntax of the task statement recognized by the IRAF Main is documented
+in the \fISystem Interface Reference Manual\fR. For example, to run a task
+with the standard output redirected to a pipe file:
+
+.ks
+.nf
+ fprintf (out_fp, "%s %d > %s\n",
+ taskname, STDOUT, pipefilename);
+.fi
+.ke
+
+Pipe files, by the way, are implemented as binary files for maximum flexibility
+and efficiency. This is acceptable since they are read and written only by
+the system. Very high i/o bandwidths are possible using direct i/o to a binary
+file.
+.le
+
+.ls [2]
+A stdio stream may be redirected at the CL level to any previously opened
+FIO file, e.g., to one of the CL's standard streams, to a text or binary
+file opened explicitly by the CL, or to another child process (e.g. redirection
+of the standard graphics output of the child to a graphics subprocess).
+This type of redirection requires the following steps by the CL:
+.ls
+.ls o
+Open local stream to which child's stream is to be redirected.
+.le
+.ls o
+Call \fBprredir\fR to map the child's stream to the local stream.
+.le
+.ls o
+When the task is run, include an argument of the form "N >" on the task
+command line, indicating that stream N has been redirected by the parent
+process (the file name is omitted).
+.le
+.ls o
+When the task terminates, or when the next task is run in the same process,
+restore the original i/o connection with another call to \fBprredir\fR.
+The default connection is established by the system only at \fBpropen\fR time.
+.le
+.le
+.le
+.le
+
+
+The I/O redirection mechanism permits messages to be shuffled from a child
+process deep in the process tree to a device owned by the CL, or from a child
+process in one branch of the process tree to a process in another branch of
+the tree. If raw mode is set on the STDIN stream in the child it will
+automatically be passed on to the process which physically reads the raw mode
+device. Asynchronous execution is possible so long as messages pass only
+one way. Synchronization occurs whenever a process waits on a read. The most
+complex example of the IPC i/o redirection mechanism in the current system
+occurs when a science or utility task sends graphics commands via the CL to a
+separate graphics task. Ignoring GKS inquires, this process is fully
+asynchronous and should be acceptably efficient provided the IPC buffer size
+is reasonable (1-4 Kb) and large amounts of bulk data do not have to be passed.
+
+.nh 3
+Detached Processes
+
+ The CL executes commands in the background, i.e., asynchronously, by
+dumping the entire run time context of the CL into a binary background
+file, then spawning a detached CL process to execute the already compiled
+command in the context of the parent. The run time context consists of
+the dictionary and stack areas, the environment list, and various other
+internal state parameters which are copied into the header area of the
+bkgfile. This is a potential problem area if dynamic memory is used,
+since it may not be possible to duplicate the virtual addresses of the
+parent's data area in the child.
+
+
+.ks
+.nf
+ job = c_propdpr (process, bkgfile)
+ stat = c_prcldpr (job)
+ y/n = c_prdone (job)
+ c_prkill (job)
+
+ exit = c_onentry (prytpe, bkgfile)
+ c_onexit (epa)
+.fi
+.ke
+
+
+The CL process uses the same IRAF Main as a normal IRAF process, except that
+a special \fBonentry\fR procedure is linked which serves as the CL main.
+The \fBonentry\fR procedure is called by the IRAF Main during
+process startup with the arguments shown; the function value returned by
+\fBonentry\fR determines whether or not the interpreter in the IRAF Main
+is entered. Since we do not want IRAF Main prompts from the CL process
+the CL version of \fBonentry\fR always returns CL_EXIT, causing process
+shutdown following execution of any procedures posted with \fBonexit\fR
+during execution of \fBonentry\fR.
+
+A detached process opened with \fBpropdpr\fR should always be closed with
+\fBprcldpr\fR if it terminates while the parent is still executing.
+The \fBprdone\fR procedure may be called to determine if a background job
+has terminated. A background job may be aborted with \fBprkill\fR.
+
+.nh 2
+Terminal Control
+
+ The TTY interface is provided at the CL level to support screen editing.
+TTY is the IRAF interface to the \fBtermcap\fR terminal capability database,
+originally developed at Berkeley for UNIX by Bill Joy.
+
+
+.ks
+.nf
+ tty = c_ttyodes (ttyname)
+ c_ttycdes (tty)
+ c_ttyseti (tty, parameter, value)
+ int = c_ttystati (tty, parameter)
+
+ bool = c_ttygetb (tty, cap)
+ int = c_ttygeti (tty, cap)
+ float = c_ttygetr (tty, cap)
+ nchars = c_ttygets (tty, cap, &outstr, maxch)
+ c_ttyctrl (fd, tty, cap, afflncnt)
+ c_ttyputs (fd, tty, ctrlstr, afflncnt)
+
+ c_ttyclear (fd, tty)
+ c_ttyclearln (fd, tty)
+ c_ttygoto (fd, tty, col, line)
+ c_ttyinit (fd, tty)
+ c_ttyputline (fd, tty, text, map_cc)
+ c_ttyso (fd, tty, onflag)
+.fi
+.ke
+
+
+Complete descriptions of TTY and \fBtermcap\fR are given elsewhere.
+Briefly, the device descriptor for a particular terminal is opened
+with \fBttyodes\fR, which returns a IRAF pointer (C integer) to the
+binary TTY descriptor.
+The terminal name may be given as "terminal", in which case \fBttyodes\fR
+will look up the name of the default terminal in the environment and search
+the termcap database for the entry for the named device.
+
+The \fBttyget\fR functions are used to read the capabilities.
+Capabilities are specified by two character mnemonics (character strings),
+shown as the \fIcap\fR arguments in the calling sequences above.
+Control sequences may be output with \fBttyctrl\fR or with \fBttyputs\fR,
+depending on whether you are willing to do a binary search for a
+particular capability at run time.
+The remaining high level functions make it easy to perform the more common
+control functions.
+
+Raw mode output to a terminal device is provided by the system interface
+(the newline and tab characters are exceptions). Raw mode input is
+provided as an \fBfseti\fR option in FIO. To set raw mode on STDIN:
+
+ c_fseti (STDIN, F_RAW, YES);
+
+While raw mode is in effect input characters are read as they are typed,
+few or no control characters are recognized, and no echoing is performed.
+
+.nh 2
+Memory Management
+
+ Both heap and stack storage facilities are available in the program
+interface, and we have made both types of facilities available in the CL.
+Note, however, that the CL does not currently use dynamic memory allocation
+directly due to the difficulties such use would cause when passing the
+context of the CL to a background CL (used to execute commands in the
+background). The CL currently makes heavy use of pointers in the dictionary
+data structures, and since the dictionary is passed to the background CL
+as a binary array, it must be restored to the same base memory address or
+the pointers will be meaningless. This led to the implementation of the
+dictionary and stack areas as fixed size, statically allocated arrays.
+
+The use of a fixed size dictionary is restrictive and wasteful of storage;
+a future implementation based on \fBsalloc\fR (the stack facilities) is
+desirable provided the context passing problem can be solved. Note that
+the environment facilities do use dynamic storage and that it is nonetheless
+possible to pass the environment to a background CL, despite the internal
+use of pointers in the environment management package.
+
+
+.ks
+.nf
+Heap Storage (UNIX compatible):
+
+ buf = malloc (nchars) u_malloc
+ buf = calloc (nchars) u_calloc
+ mfree (buf) u_mfree
+
+
+Stack Storage:
+
+ c_smark (&sp)
+ buf = c_salloc (nchars)
+ c_sfree (sp)
+.fi
+.ke
+
+
+Note that the C callable versions of \fBmalloc\fR, \fBcalloc\fR, and
+\fBmfree\fR emulate the comparable UNIX procedures. The storage units
+are C chars, i.e., bytes. Promotion to an integral number of SPP chars
+is automatic. The \fIbuf\fR argument is a C pointer. The \fIsp\fR
+argument, used to mark the position of the stack pointer, is an integer.
+The stack is implemented in segments allocated on the heap, hence there
+is no builtin limit on the size of the stack.
diff --git a/sys/libc/README b/sys/libc/README
new file mode 100644
index 00000000..4801a369
--- /dev/null
+++ b/sys/libc/README
@@ -0,0 +1,208 @@
+LIBC -- C language binding for a portion of the IRAF VOS
+ UNIX emulator
+
+This directory contains
+
+ [1] A subset of the routines from the UNIX stdio library. These routines
+ emulate the equivalent UNIX routines but are interfaced to the IRAF
+ program interface.
+
+ [2] C-callable versions of a subset of the routines from the IRAF program
+ interface. Included are portions of the following packages:
+
+ file i/o
+ formatted i/o
+ environment
+ process control
+ terminal control
+ memory management
+ exception handling
+
+The header files "irafio.h" and "names.h" should be included in all C files
+which reference the C library. The include files "stdio.h" and "ctype.h"
+should be used wherever they would be used in a UNIX/C system.
+
+
+IMPORTANT NOTE:
+
+ Routines marked VARARGS are machine dependent in that they assume a
+certain ordering (left to right) for the argument list. On some machines
+the ordering may be the opposite.
+
+TODO: Rewrite these procedures to use the UNIX <varargs.h> macros.
+
+
+1. LIBC Emulation of UNIX C-Library Procedures
+
+ syntax err eof
+
+ double = asin (x)
+ double = acos (x)
+ double = atan (x)
+ double = atan2 (x, y)
+ double = atof (str) 0.
+ int = atoi (str) 0
+ long = atol (str) 0
+ charp = calloc (nelems, elsize) NULL
+ clearerr (fp)
+ double = cos (x)
+ double = exp (x)
+ fclose (fp) EOF
+ FILE = fdopen (fd, modestr) NULL
+ bool = feof (fp)
+ bool = ferror (fp)
+ fflush (fp) EOF
+ ch = fgetc (fp) EOF
+ charp = fgets (buf, maxch, fp) NULL
+ fd = fileno (fp)
+ FILE = fopen (fname, modestr) NULL
+ fputc (ch, fp) EOF
+ fputs (str, fp)
+ nelem = fread (bp, szelem, nelem, fp) 0 0
+ free (buf)
+ FILE = freopen (fname, modestr, fp) NULL
+ fseek (fp, offset, origin) EOF
+ long = ftell (fp)
+ nelem = fwrite (bp, szelem, nelem, fp) 0 0
+ ch = getc (fp) EOF EOF
+ ch = getchar () EOF EOF
+ charp = getenv (envvar) NULL
+ charp = gets (buf) NULL NULL
+ word = getw (fp) EOF EOF
+ charp = index (str, ch) NULL
+ double = log (x)
+ double = log10 (x)
+ int = nint (x)
+ charp = malloc (nbytes) NULL
+ charp = mktemp (template) NULL
+ perror (prefix)
+ double = pow (x, y)
+ printf (format, argp)
+ fprintf (fp, format, argp)
+ sprintf (str, format, argp)
+ eprintf (format, argp)
+ ch = putc (ch, fp) EOF
+ ch = putchar (ch) EOF
+ puts (str)
+ word = putw (word, fp) EOF
+ qsort (array, len, isize, compar)
+ charp = realloc (buf, newsize) NULL
+ rewind (fp) EOF
+ charp = rindex (str, ch)
+ nscan = scanf (format, argp) EOF EOF
+ nscan = fscanf (fp, format, argp) EOF EOF
+ nscan = sscanf (str, format, argp) EOF EOF
+ setbuf (fp, buf)
+ setbuffer (fp, buf, size)
+ setlinebuf (fp)
+ double = sin (x)
+ double = sqrt (x)
+ charp = strcat (s1, s2)
+ charp = strcmp (s1, s2)
+ charp = strcpy (s1, s2)
+ int = strlen (str)
+ charp = strncat (s1, s2, n)
+ charp = strncmp (s1, s2, n)
+ charp = strncpy (s1, s2, n)
+ stat = system (cmd)
+ ch = ungetc (ch, fp) EOF
+
+
+
+2. System Calls
+
+All output parameters are shown as "&name" regardless of whether the actual
+parameter is a pointer. If no ERR or EOF type is shown it is inapplicable to
+the procedure. The error type "*" denotes an error action which will lead to
+error recovery if not caught by calling the procedure inside an "iferr". In
+general, error actions are permitted only where errors are not expected and
+where we suspect that the programmer would ignore an error return code if one
+were used. Fatal errors cannot be caught but "cannot happen".
+
+
+ syntax err eof
+
+ bool = c_access (fname, mode, type) *
+ longsec = c_clktime (reftime)
+ c_close (fd) *
+ charp = c_cnvdate (clktime, &outstr, maxch)
+ charp = c_cnvtime (clktime, &outstr, maxch)
+ longmsec = c_cputime (reftime)
+ c_delete (fname) ERR
+ nchars = c_envfind (var, &outstr, maxch) 0
+ nchars = c_envgets (var, &outstr, maxch) 0
+ bool = c_envgetb (var) no=0
+ ival = c_envgeti (var) *
+ c_envputs (var, value) *
+ c_envlist (fd, prefix, show_redefs) *
+ c_envmark (&envp)
+ nredefs = c_envfree (envp)
+ nscan = c_envscan (input_source) *
+ c_error (errcode, errmsg) *
+ c_erract (action) *
+ errcode = c_errget (&outstr, maxch)
+ c_fchdir (newdir) ERR
+ ch = c_filbuf (fp) EOF EOF
+ c_finfo (fname, fi) ERR
+ ch = c_flsbuf (ch, fp) EOF
+ c_flush (fd) *
+ nchars = c_fmapfn (vfn, &osfn, maxch) 0
+ stat = c_fmkdir (newdir) ERR
+ nchars = c_fnldir (vfn, &ldir, maxch)
+ nchars = c_fnroot (vfn, &root, maxch)
+ nchars = c_fnextn (vfn, &extn, maxch)
+ nchars = c_fpath (vfn, &osfn, maxch) 0
+ fd = c_fredir (fd, fname, mode, type) ERR
+ c_fseti (fd, param, value) *
+ ival = c_fstati (fd, param) *
+ int = c_getpid ()
+ c_getuid (&outstr, maxch) *
+ os_chan = c_kimapchan (ki_chan, nodename, maxch)
+ token = c_lexnum (str, &toklen)
+ nchars = c_mktemp (root, &temp_filename, maxch) 0
+ long = c_note (fd) *
+ fd = c_open (fname, mode, type) ERR
+ exit_stat = c_oscmd (cmd, infile, outfile, errfile) *
+ c_prchdir (pid, newdir) ERR
+ exit_stat = c_prcldpr (job) *
+ c_prclose (pid) *
+ bool = c_prdone (job) *
+ c_prenvset (pid, envvar, valuestr) ERR
+ c_prkill (job) ERR
+ pid = c_propdpr (process, bkgfile) NULL
+ pid = c_propen (process, &in, &out) NULL
+ c_prredir (pid, stream, new_fd) ERR
+ c_prsignal (pid, signal) ERR
+ nbytes = c_read (fd, &buf, maxbytes) * EOF
+ c_rename (old_fname, new_fname) ERR
+ charp = c_salloc (nbytes) fatal
+ c_smark (&sp) fatal
+ c_sfree (sp) fatal
+ bool = c_stkcmp (p1, p2) *
+ c_seek (fd, offset) ERR
+ xcharp = c_sppstr (xstr)
+ cstr = c_strpak (sppstr, &cstr, maxch)
+ xcharp = c_strupk (str, &xoutstr, maxch)
+ c_tsleep (nseconds)
+ tty(int) = c_ttyodes (ttyname) ERR
+ c_ttycdes (tty) *
+ c_ttyseti (tty, param, value) *
+ ival = c_ttystati (tty, param) *
+ bool = c_ttygetb (tty, cap) no=0
+ ival = c_ttygeti (tty, cap) 0
+ fval = c_ttygetr (tty, cap) 0.
+ nchars = c_ttygets (tty, cap, &outstr, maxch) 0
+ c_ttyputs (fd, tty, cap, afflncnt) ERR
+ c_ttyctrl (fd, tty, cap, afflncnt) ERR
+ c_ttyclear (fd, tty) *
+ c_ttyclearln (fd, tty) *
+ c_ttygoto (fd, tty, col, line) *
+ c_ttyinit (fd, tty) *
+ c_ttyputline (fd, tty, line, map_cc) *
+ c_ttyso (fd, tty, onoff) *
+ c_ungetc (fd, ch) ERR
+ c_ungetline (fd, str) ERR
+ c_vfnbrk (vfn, root, extn)
+ nbytes = c_write (fd, buf, nbytes) *
+ c_xwhen (vex, new_handler, old_handler) *
+ c_xgmes (oscode, oserrmsg, maxch)
diff --git a/sys/libc/atof.c b/sys/libc/atof.c
new file mode 100644
index 00000000..df0ec7d9
--- /dev/null
+++ b/sys/libc/atof.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_ctype
+#include <iraf.h>
+
+
+/* ATOF -- Ascii to double floating. Convert any legal floating point number
+** into a binary double precision floating value.
+*/
+double
+atof (char *str)
+{
+ XINT ip = 1;
+ XDOUBLE dval;
+
+ if (CTOD (c_sppstr(str), &ip, &dval) == 0)
+ return ( (double) 0);
+ else
+ return ( (double) dval);
+}
diff --git a/sys/libc/atoi.c b/sys/libc/atoi.c
new file mode 100644
index 00000000..6df13153
--- /dev/null
+++ b/sys/libc/atoi.c
@@ -0,0 +1,48 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_ctype
+#include <iraf.h>
+
+
+/* ATOI -- Ascii to integer. Convert a simple integer in decimal radix to
+** a binary integer value.
+*/
+int
+atoi (char *str)
+{
+ register char *ip = str;
+ register int ch, ival;
+ int neg;
+
+
+ if (*str == EOS)
+ return (0);
+
+ /* Skip leading whitespace. */
+ while (isspace (*ip))
+ ip++;
+
+ /* Check for indefinite. */
+ if ((ch = *ip) == 'I')
+ if (strncmp (ip, "INDEF", 5) == 0)
+ if (! (isalnum (ch = *(ip+5)) || ch == '_'))
+ return (INDEFI);
+
+ /* Check for leading + or - sign. */
+ neg = 0;
+ if (ch == '-') {
+ neg++;
+ ip++;
+ } else if (ch == '+')
+ ip++;
+
+ /* Accumulate sequence of digits. */
+ ival = 0;
+ while (isdigit (ch = *ip++))
+ ival = ival * 10 + tointeg(ch);
+
+ return (neg ? -ival : ival);
+}
diff --git a/sys/libc/atol.c b/sys/libc/atol.c
new file mode 100644
index 00000000..f5780583
--- /dev/null
+++ b/sys/libc/atol.c
@@ -0,0 +1,49 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_ctype
+#include <iraf.h>
+
+
+/* ATOL -- Ascii to long integer. Convert a simple integer in decimal radix to
+** a binary long integer value.
+*/
+long
+atol (char *str)
+{
+ register char *ip = str;
+ register int ch;
+ register long lval;
+ int neg;
+
+
+ if (*str == EOS)
+ return (0);
+
+ /* Skip leading whitespace. */
+ while (isspace (*ip))
+ ip++;
+
+ /* Check for indefinite. */
+ if ((ch = *--ip) == 'I')
+ if (strncmp (ip, "INDEF", 5) == 0)
+ if (! (isalnum (ch = *(ip+5)) || ch == '_'))
+ return (INDEFL);
+
+ /* Check for leading + or - sign. */
+ neg = 0;
+ if (ch == '-') {
+ neg++;
+ ip++;
+ } else if (ch == '+')
+ ip++;
+
+ /* Accumulate sequence of digits. */
+ lval = 0;
+ while (isdigit (ch = *ip++))
+ lval = lval * 10 + tointeg(ch);
+
+ return (neg ? -lval : lval);
+}
diff --git a/sys/libc/caccess.c b/sys/libc/caccess.c
new file mode 100644
index 00000000..13b6f52e
--- /dev/null
+++ b/sys/libc/caccess.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ACCESS -- FIO file access.
+*/
+int
+c_access (
+ char *fname, /* name of file to be accessed */
+ int mode, /* access mode */
+ int type /* file type */
+)
+{
+ XINT x_mode = mode, x_type = type;
+
+ return (ACCESS (c_sppstr(fname), &x_mode, &x_type));
+}
diff --git a/sys/libc/calloc.c b/sys/libc/calloc.c
new file mode 100644
index 00000000..f9a4f044
--- /dev/null
+++ b/sys/libc/calloc.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* CALLOC -- Allocate memory for NELEM elements of size ELSIZE bytes per
+** element. The space is initialized to all zeros.
+*/
+char *
+calloc (
+ unsigned int nelems,
+ unsigned int elsize
+)
+{
+ XINT nchars = (nelems*elsize + sizeof(XCHAR)-1) / sizeof(XCHAR);
+ XINT ptr, dtype = TY_CHAR;
+
+
+ iferr (CALLOC (&ptr, &nchars, &dtype))
+ return (NULL);
+ else
+ return ((char *)&Memc[ptr]);
+}
diff --git a/sys/libc/callocate.c b/sys/libc/callocate.c
new file mode 100644
index 00000000..303896c3
--- /dev/null
+++ b/sys/libc/callocate.c
@@ -0,0 +1,80 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ALLOCATE -- Allocate a device (and mount it, if necessary).
+*/
+int
+c_allocate (
+ char *device /* device to be allocated */
+)
+{
+ int status;
+
+ iferr (status = XALLOCATE (c_sppstr(device)))
+ return (ERR);
+ else
+ return (status);
+}
+
+
+/* C_DEALLOCATE -- Deallocate a device.
+*/
+int
+c_deallocate (
+ char *device, /* device to be allocated */
+ int rewind /* rewind flag, if magtape */
+)
+{
+ int status;
+ XINT x_rewind = rewind;
+
+ iferr (status = (int) XDEALLOCATE (c_sppstr(device), &x_rewind))
+ return (ERR);
+ else
+ return (status);
+}
+
+
+/* C_DEVSTATUS -- Print the current status of the named device.
+*/
+void
+c_devstatus (
+ char *device, /* device name */
+ int out /* output file */
+)
+{
+ XINT x_out = out;
+
+ XDEVSTATUS (c_sppstr(device), &x_out);
+}
+
+
+/* C_DEVOWNER -- Determine if a device is allocated, and if so return
+** the name of the owner.
+*/
+int
+c_devowner (
+ char *device, /* device to be allocated */
+ char *owner, /* receives owner name string */
+ int maxch
+)
+{
+ PKCHAR x_owner[SZ_FNAME+1];
+ XINT x_maxch = SZ_FNAME;
+ int status;
+
+
+ iferr (status = (int) XDEVOWNER(c_sppstr(device), x_owner, &x_maxch)) {
+ owner[0] = EOS;
+ return (ERR);
+ } else {
+ c_strpak (x_owner, owner, maxch);
+ return (status);
+ }
+}
diff --git a/sys/libc/cclktime.c b/sys/libc/cclktime.c
new file mode 100644
index 00000000..ca26e56e
--- /dev/null
+++ b/sys/libc/cclktime.c
@@ -0,0 +1,35 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_CLKTIME -- Return the clock time in long integer seconds since Jan. 1,
+** 1980, minus the reference argument (0 for absolute time).
+*/
+long
+c_clktime (
+ long reftime /* reference time */
+)
+{
+ XLONG x_reftime = reftime;
+
+ return (CLKTIME (&x_reftime));
+}
+
+
+/* C_CPUTIME -- Return the cpu time consumed by the current process and all
+** subprocesses, in long integer milliseconds, minus the reference time.
+*/
+long
+c_cputime (
+ long reftime /* reference time */
+)
+{
+ XLONG x_reftime = reftime;
+
+ return (CPUTIME (&x_reftime));
+}
diff --git a/sys/libc/cclose.c b/sys/libc/cclose.c
new file mode 100644
index 00000000..630f097d
--- /dev/null
+++ b/sys/libc/cclose.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_CLOSE -- FIO file close.
+*/
+int
+c_close (
+ XINT fd /* FIO file descriptor */
+)
+{
+ XINT x_fd = fd;
+
+ iferr (CLOSE (&x_fd))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/ccnvdate.c b/sys/libc/ccnvdate.c
new file mode 100644
index 00000000..ee97169f
--- /dev/null
+++ b/sys/libc/ccnvdate.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_CNVDATE -- Convert long integer time as returned by CLKTIME into a short
+** format date string.
+*/
+char *
+c_cnvdate (
+ long clktime, /* seconds since jan.1,1980 */
+ char *outstr, /* encoded time string */
+ int maxch
+)
+{
+ XCHAR buf[SZ_LINE];
+ XINT x_maxch = SZ_LINE;
+
+ CNVDATE (&clktime, buf, &x_maxch);
+ return (c_strpak (buf, outstr, maxch));
+}
diff --git a/sys/libc/ccnvtime.c b/sys/libc/ccnvtime.c
new file mode 100644
index 00000000..4923907c
--- /dev/null
+++ b/sys/libc/ccnvtime.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_CNVTIME -- Convert long integer time as returned by CLKTIME into a long
+** format date string.
+*/
+char *
+c_cnvtime (
+ long clktime, /* seconds since jan.1,1980 */
+ char *outstr, /* encoded time string */
+ int maxch
+)
+{
+ XCHAR buf[SZ_LINE];
+ XINT x_maxch = SZ_LINE;
+
+ CNVTIME (&clktime, buf, &x_maxch);
+ return (c_strpak (buf, outstr, maxch));
+}
diff --git a/sys/libc/cdelete.c b/sys/libc/cdelete.c
new file mode 100644
index 00000000..14d97926
--- /dev/null
+++ b/sys/libc/cdelete.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/* C_DELETE -- FIO delete file.
+*/
+int
+c_delete (
+ char *fname /* name of file to be opened */
+)
+{
+ iferr (DELETE (c_sppstr(fname)))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cenvget.c b/sys/libc/cenvget.c
new file mode 100644
index 00000000..2c812226
--- /dev/null
+++ b/sys/libc/cenvget.c
@@ -0,0 +1,143 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/*
+** ENVGET[SBI] -- Assorted routines for fetching the values of environment
+** variables.
+** ENVPUTS -- Set or redefine the value of an environment variable.
+** ENVRESET -- Reset (overwrite) the value of an environment variable.
+*/
+
+#define SZ_VALUESTR SZ_COMMAND
+
+static XCHAR valuestr[SZ_VALUESTR+1];
+static XINT len_valuestr = SZ_VALUESTR;
+
+
+/* ENVGET -- (Near) emulation of the UNIX getenv procedure. This is a handy
+** routine for looking up environment variables in C programs. The value is
+** fetched into an internal static array and a pointer to this array is returned
+** as the function value, else NULL if the environment variable is not found.
+** The caller is responsible for using the value string before it is overwritten
+** by the next call.
+*/
+char *
+envget (
+ char *var /* environment variable name */
+)
+{
+ if (ENVFIND (c_sppstr(var), valuestr, &len_valuestr) < 0)
+ return (NULL);
+ else
+ return (c_strpak (valuestr, (char *)valuestr, len_valuestr+1));
+}
+
+
+/* C_ENVGETS -- Fetch the string value of an environment variable into the
+** output string. Return the strlen length of the output string as the
+** function value. If the variable is not found and the process is being
+** used interactively a query is generated. If no value is given in response
+** to the query or the process is noninteractive and the variable is not
+** found, zero is returned.
+*/
+int
+c_envgets (
+ char *var, /* name of variable to be fetched */
+ char *outstr, /* output string */
+ int maxch /* length including EOS */
+)
+{
+ register int nchars;
+
+ if ((nchars = ENVGETS (c_sppstr(var), valuestr, &len_valuestr)) < 0)
+ return (nchars);
+ else {
+ c_strpak (valuestr, outstr, maxch);
+ return (nchars > maxch ? maxch : nchars);
+ }
+}
+
+
+/* C_ENVFIND -- Just like ENVGETS, except that a query will not be generated
+** even if working interactively.
+*/
+int
+c_envfind (
+ char *var, /* name of variable to be fetched */
+ char *outstr, /* output string */
+ int maxch /* length including EOS */
+)
+{
+ register int nchars;
+
+ if ((nchars = ENVFIND (c_sppstr(var), valuestr, &len_valuestr)) < 0)
+ return (nchars);
+ else {
+ c_strpak (valuestr, outstr, maxch);
+ return (nchars > maxch ? maxch : nchars);
+ }
+}
+
+
+/* C_ENVGETB -- Return the boolean value of an environment variable. An error
+** action is taken if the variable is not found or the value string cannot
+** be interpreted as a boolean value.
+*/
+int
+c_envgetb (
+ char *var /* name of variable to be fetched */
+)
+{
+ return ((int) BTOI ((XINT) ENVGETB (c_sppstr(var))));
+}
+
+
+/* C_ENVGETI -- Return the integer value of an environment variable. An error
+** action is taken if the variable is not found or the value string cannot
+** be interpreted as an integer value.
+*/
+int
+c_envgeti (
+ char *var /* name of variable to be fetched */
+)
+{
+ return ((int) ENVGETI (c_sppstr(var)));
+}
+
+
+/* C_ENVPUTS -- Set or redefine the value of an environment variable. If the
+** variable is not defined a new entry is created. If the variable is already
+** defined but has a different value it is redefined, with the new definition
+** having precedence over the former (redefinitions can be undone; see envmark
+** and envfree). If the variable is already defined and the new definition
+** has the same value, it is ignored.
+**
+** Arguments: set var = value
+*/
+void
+c_envputs (
+ char *var, /* name of variable to be set */
+ char *value /* value string */
+)
+{
+ ENVPUTS (c_sppstr(var), c_strupk (value, valuestr, SZ_VALUESTR));
+}
+
+
+/* C_ENVRESET -- Reset (overwrite) the value of an environment variable.
+** If the variable is not defined a new entry is created.
+*/
+void
+c_envreset (
+ char *var, /* name of variable to be set */
+ char *value /* value string */
+)
+{
+ ENVRESET (c_sppstr(var), c_strupk (value, valuestr, SZ_VALUESTR));
+}
diff --git a/sys/libc/cenvlist.c b/sys/libc/cenvlist.c
new file mode 100644
index 00000000..1616a4d5
--- /dev/null
+++ b/sys/libc/cenvlist.c
@@ -0,0 +1,32 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ENVLIST -- List the names and values of all environment variables on the
+** output file. Variables are listed in the reverse of the order in which
+** they were defined. If a variable is redefined all definitions or only the
+** most recent definition may be listed. Each definition appears on a separate
+** line in the following format:
+**
+** prefix var="value"
+**
+** where "prefix" is the prefix string supplied as an argument, "var" is the
+** name of the variable, and "value" is the value string.
+*/
+void
+c_envlist (
+ XINT fd, /* output file */
+ char *prefix, /* prefix string, e.g. "set " */
+ int show_redefs /* 0=hide redefs, 1=show redefs */
+)
+{
+ XINT x_fd = fd,
+ x_show_redefs = show_redefs;
+
+ ENVLIST (&x_fd, c_sppstr(prefix), &x_show_redefs);
+}
diff --git a/sys/libc/cenvmark.c b/sys/libc/cenvmark.c
new file mode 100644
index 00000000..14963844
--- /dev/null
+++ b/sys/libc/cenvmark.c
@@ -0,0 +1,54 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* ENVMARK -- Mark the position of the "stack pointer" of the environment
+** list. A subsequent call to ENVFREE will unset all set environment
+** operations since the corresponding mark.
+*/
+void
+c_envmark (
+ XINT *envp /* storage for saved stack pointer */
+)
+{
+ ENVMARK (envp);
+}
+
+
+/* ENVFREE -- Free or unset all environment variables set since the matching
+** call to ENVMARK. The number of redefined variables uncovered by the free
+** operation is returned as the function value.
+*/
+int
+c_envfree (
+ int envp, /* marker returned by envmark */
+ int userfcn /* epa of user function for redefs */
+)
+{
+ XINT x_envp = envp;
+
+ return (ENVFREE (&x_envp, (XINT *)&userfcn));
+}
+
+
+/* PRENVFREE -- Free or unset all environment variables set since the matching
+** call to ENVMARK. The number of redefined variables uncovered by the free
+** operation is returned as the function value. This call is equivalent to
+** envfree except that it also updates the values of any uncovered redefinitions
+** in the specified connected subprocesses.
+*/
+int
+c_prenvfree (
+ int pid, /* process pid, or 0 for all subprocs */
+ int envp /* marker returned by envmark */
+)
+{
+ XINT x_pid = pid, x_envp = envp;
+
+ return (PRENVFREE (&x_pid, &x_envp));
+}
diff --git a/sys/libc/cenvscan.c b/sys/libc/cenvscan.c
new file mode 100644
index 00000000..5fef48e7
--- /dev/null
+++ b/sys/libc/cenvscan.c
@@ -0,0 +1,32 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ENVSCAN -- High level command to parse and enter a SET declaration into
+** the environment list, or to parse and enter a list of SET declarations from
+** a text file. The single input string argument should be either a SET
+** declaration, i.e.,
+**
+** set var="value" (quotes optional)
+**
+** or an indirect reference to a text file containing SET declarations, e.g.,
+**
+** @filename
+**
+** If a file is specified, only lines beginning with the keyword "set" will
+** be decoded; all other lines are ignored. The number of SET declarations
+** processed is returned as the function value. There is no fixed limit on
+** the number of SET declarations for a process.
+*/
+int
+c_envscan (
+ char *input_source
+)
+{
+ return (ENVSCAN (c_sppstr(input_source)));
+}
diff --git a/sys/libc/cerract.c b/sys/libc/cerract.c
new file mode 100644
index 00000000..a9c9cb2d
--- /dev/null
+++ b/sys/libc/cerract.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ERRACT -- Take an error action. Typically called in an IFERR error
+** handler to print a warning message or initiate error recovery after
+** application specific cleanup actions have been taken. The actions are
+** defined in import_error
+*/
+void
+c_erract (int action)
+{
+ XINT x_action = action;
+
+ ERRACT (&x_action);
+}
diff --git a/sys/libc/cerrcode.c b/sys/libc/cerrcode.c
new file mode 100644
index 00000000..305ab39d
--- /dev/null
+++ b/sys/libc/cerrcode.c
@@ -0,0 +1,15 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/* C_ERRCODE -- Get the error code of the most recent error.
+*/
+int
+c_errcode ( void )
+{
+ return (ERRCODE());
+}
diff --git a/sys/libc/cerrget.c b/sys/libc/cerrget.c
new file mode 100644
index 00000000..a62a2f67
--- /dev/null
+++ b/sys/libc/cerrget.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ERRGET -- Get the error code and error message string of the most
+** recent error.
+*/
+int
+c_errget (
+ char *outstr, /* error message string */
+ int maxch /* max chars out, incl EOS */
+)
+{
+ XCHAR buf[SZ_LINE+1];
+ XINT szbuf = SZ_LINE;
+ int errcode;
+
+ errcode = (int) ERRGET (buf, &szbuf);
+ c_strpak (buf, outstr, maxch);
+
+ return (errcode);
+}
diff --git a/sys/libc/cerror.c b/sys/libc/cerror.c
new file mode 100644
index 00000000..214d54a8
--- /dev/null
+++ b/sys/libc/cerror.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_ERROR -- Post an error.
+*/
+void
+c_error (
+ int errcode, /* error code */
+ char *errmsg /* error message */
+)
+{
+ XINT x_errcode = errcode;
+ ERROR (&x_errcode, c_sppstr(errmsg));
+}
diff --git a/sys/libc/cfchdir.c b/sys/libc/cfchdir.c
new file mode 100644
index 00000000..2dc708da
--- /dev/null
+++ b/sys/libc/cfchdir.c
@@ -0,0 +1,19 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FCHDIR -- Change directory.
+*/
+int
+c_fchdir (char *newdir)
+{
+ iferr (FCHDIR (c_sppstr (newdir)))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cfilbuf.c b/sys/libc/cfilbuf.c
new file mode 100644
index 00000000..e37aec75
--- /dev/null
+++ b/sys/libc/cfilbuf.c
@@ -0,0 +1,36 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#include <iraf.h>
+
+
+/* C_FILBUF -- Fill the FIO file buffer. Called by the GETC macro to fill
+** the file buffer when the end of the buffer is reached. The function
+** value is either the first char in the refilled buffer or EOF. If the
+** file is connected to a child process the filter PRFILBUF is called to
+** handle the XMIT and XFER requests.
+*/
+int
+c_filbuf (FILE *fp)
+{
+ register int nchars;
+ XINT x_fd = fileno(fp);
+ XINT (*fillbuffer)();
+ XINT PRFILBUF(), FILBUF();
+
+
+ fillbuffer = ((fp->_fflags & _FIPC) ? PRFILBUF : FILBUF);
+
+ iferr (nchars = (int) (*fillbuffer)(&x_fd)) {
+ fp->_fflags |= _FERR;
+ return (EOF);
+ } else if (nchars == XEOF) {
+ fp->_fflags |= _FEOF;
+ return (EOF);
+ } else
+ return (Memc[fp->_iop++] & 0377);
+}
diff --git a/sys/libc/cfinfo.c b/sys/libc/cfinfo.c
new file mode 100644
index 00000000..7e69e5e0
--- /dev/null
+++ b/sys/libc/cfinfo.c
@@ -0,0 +1,30 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_xnames
+#define import_finfo
+#define import_libc
+#include <iraf.h>
+
+
+/* C_FINFO -- FIO get directory info for named file.
+*/
+int
+c_finfo (
+ char *fname, /* name of file to be opened */
+ struct _finfo *fi /* finfo structure (output) */
+)
+{
+ register int status;
+
+ iferr (status = (int) FINFO (c_sppstr(fname), (XLONG *)fi)) {
+ status = ERR;
+ } else if (status != XERR) {
+ c_strpak ((XCHAR *)fi->fi_owner, fi->fi_owner, SZ_OWNERSTR);
+ status = OK;
+ } else
+ status = ERR;
+
+ return (status);
+}
diff --git a/sys/libc/cflsbuf.c b/sys/libc/cflsbuf.c
new file mode 100644
index 00000000..9547b0c2
--- /dev/null
+++ b/sys/libc/cflsbuf.c
@@ -0,0 +1,43 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#include <iraf.h>
+
+
+/* C_FLSBUF -- Flush the FIO file buffer. Called by the PUTC macro to flush
+** the file buffer when it fills. The function value returned is either the
+** first char written to the buffer (passed as an argument) or EOF in the
+** event of an error.
+*/
+int
+c_flsbuf (
+ unsigned int ch, /* char which caused the fault */
+ FILE *fp /* output file */
+)
+{
+ register int buf_not_full;
+ XINT fd = fileno(fp);
+ XINT nreserve = 1;
+
+
+ /* If we were called due to flush on newline and there is space in
+ * the buffer, put the ch in the buffer before flushing.
+ */
+ buf_not_full = (fp->_iop < fp->_otop);
+ if (buf_not_full)
+ Memc[fp->_iop++] = (unsigned)ch;
+
+ iferr (FLSBUF (&fd, &nreserve)) {
+ fp->_fflags |= _FERR;
+ return (EOF);
+ }
+
+ if (!buf_not_full)
+ Memc[fp->_iop++] = (unsigned)ch;
+
+ return (ch);
+}
diff --git a/sys/libc/cflush.c b/sys/libc/cflush.c
new file mode 100644
index 00000000..7a7a029a
--- /dev/null
+++ b/sys/libc/cflush.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FLUSH -- FIO file flush.
+*/
+void
+c_flush (
+ XINT fd /* FIO file descriptor */
+)
+{
+ XINT x_fd = fd;
+
+ FLUSH (&x_fd);
+}
diff --git a/sys/libc/cfmapfn.c b/sys/libc/cfmapfn.c
new file mode 100644
index 00000000..0d4181a0
--- /dev/null
+++ b/sys/libc/cfmapfn.c
@@ -0,0 +1,36 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FMAPFN -- Map a VFN (virtual filename) into an OSFN (host system filename).
+*/
+int
+c_fmapfn (
+ char *vfn, /* virtual filename */
+ char *osfn, /* OS filename */
+ int maxch
+)
+{
+ XCHAR x_osfn[SZ_PATHNAME+1];
+ XINT sz_path = SZ_PATHNAME;
+
+
+ /* The OSFN is returned as a packed string in the XCHAR array x_osfn.
+ * An intermediate buffer is used to avoid char->xchar alignment
+ * problems of upward pointer coercion on some machines.
+ */
+ if (maxch)
+ iferr (FMAPFN (c_sppstr(vfn), x_osfn, &sz_path))
+ osfn[0] = EOS;
+ else {
+ (void) strncpy (osfn, (char *)x_osfn, maxch);
+ osfn[maxch-1] = EOS;
+ }
+
+ return (strlen (osfn));
+}
diff --git a/sys/libc/cfmkdir.c b/sys/libc/cfmkdir.c
new file mode 100644
index 00000000..9888461d
--- /dev/null
+++ b/sys/libc/cfmkdir.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FMKDIR -- FIO procedure to create a new directory.
+*/
+int
+c_fmkdir (newdir)
+char *newdir; /* name of the new directory */
+{
+ iferr (FMKDIR (c_sppstr(newdir)))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cfnextn.c b/sys/libc/cfnextn.c
new file mode 100644
index 00000000..9917b89f
--- /dev/null
+++ b/sys/libc/cfnextn.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FNEXTN -- Extract the filename extension substring from a filename.
+*/
+int
+c_fnextn (
+ char *vfn, /* filename */
+ char *extn, /* filename extension (output) */
+ int maxch /* max chars out */
+)
+{
+ XCHAR spp_extn[SZ_FNAME+1];
+ XINT x_maxch = SZ_FNAME, nchars;
+
+ nchars = (int) FNEXTN (c_sppstr(vfn), spp_extn, &x_maxch);
+ c_strpak (spp_extn, extn, maxch);
+
+ return (nchars);
+}
diff --git a/sys/libc/cfnldir.c b/sys/libc/cfnldir.c
new file mode 100644
index 00000000..9b8b469c
--- /dev/null
+++ b/sys/libc/cfnldir.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FNLDIR -- Extract the directory prefix substring from a filename.
+*/
+int
+c_fnldir (
+ char *vfn, /* filename */
+ char *ldir, /* directory prefix (output) */
+ int maxch /* max chars out */
+)
+{
+ XCHAR spp_ldir[SZ_FNAME+1];
+ XINT x_maxch = SZ_FNAME, nchars;
+
+ nchars = FNLDIR (c_sppstr(vfn), spp_ldir, &x_maxch);
+ c_strpak (spp_ldir, ldir, maxch);
+
+ return (nchars);
+}
diff --git a/sys/libc/cfnroot.c b/sys/libc/cfnroot.c
new file mode 100644
index 00000000..78ac72bb
--- /dev/null
+++ b/sys/libc/cfnroot.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/* C_FNROOT -- Extract the root filename substring from a filename.
+*/
+int
+c_fnroot (
+ char *vfn, /* filename */
+ char *root, /* root filename (output) */
+ int maxch /* max chars out */
+)
+{
+ XCHAR spp_root[SZ_FNAME+1];
+ XINT x_maxch = SZ_FNAME, nchars;
+
+ nchars = FNROOT (c_sppstr(vfn), spp_root, &x_maxch);
+ c_strpak (spp_root, root, maxch);
+
+ return (nchars);
+}
diff --git a/sys/libc/cfpath.c b/sys/libc/cfpath.c
new file mode 100644
index 00000000..b7820012
--- /dev/null
+++ b/sys/libc/cfpath.c
@@ -0,0 +1,34 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FPATHNAME -- Map a VFN (virtual filename) into a pathname (filename
+** specification which is independent of the current directory).
+*/
+int
+c_fpathname (
+ char *vfn, /* virtual filename */
+ char *osfn, /* OS filename */
+ int maxch
+)
+{
+ XCHAR x_osfn[SZ_PATHNAME+1];
+ XINT x_maxch = SZ_PATHNAME;
+
+
+ /* The OSFN is returned as a packed string in the XCHAR array x_osfn.
+ * An intermediate buffer is used to avoid char->xchar alignment
+ * problems of upward pointer coercion on some machines.
+ */
+ iferr (FPATHNAME (c_sppstr(vfn), x_osfn, &x_maxch))
+ osfn[0] = EOS;
+ else
+ c_strpak (x_osfn, osfn, maxch);
+
+ return (strlen (osfn));
+}
diff --git a/sys/libc/cfredir.c b/sys/libc/cfredir.c
new file mode 100644
index 00000000..2a4ae5b1
--- /dev/null
+++ b/sys/libc/cfredir.c
@@ -0,0 +1,46 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#include <iraf.h>
+
+
+/* C_FREDIR -- FIO redirect an open i/o stream to a named file. Most commonly
+** used to redirect one of the standard i/o streams to a file. The named file
+** need not be of the same type as the old stream.
+*/
+int
+c_fredir (
+ XINT fd, /* stream to be redirected */
+ char *fname, /* name of file to be opened */
+ int mode, /* access mode */
+ int type /* file type */
+)
+{
+ XINT x_fd = fd, x_type = type, x_mode = mode;
+
+ iferr (FREDIR (&x_fd, c_sppstr(fname), &x_mode, &x_type))
+ return (ERR);
+ else
+ return (fd);
+}
+
+
+/* C_FREDIRO -- FIO redirect an open i/o stream to another open stream.
+*/
+int
+c_frediro (
+ XINT fd, /* stream to be redirected */
+ XINT newfd /* where it is to be redirected */
+)
+{
+ XINT x_fd = fd, x_newfd = newfd;
+
+ iferr (FREDIRO (&x_fd, &x_newfd))
+ return (ERR);
+ else
+ return (fd);
+}
diff --git a/sys/libc/cfseti.c b/sys/libc/cfseti.c
new file mode 100644
index 00000000..7d496c33
--- /dev/null
+++ b/sys/libc/cfseti.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FSETI -- FIO set integer file parameter.
+*/
+void
+c_fseti (
+ XINT fd, /* FIO file descriptor */
+ int param, /* param to be set */
+ int value /* new value */
+)
+{
+ XINT x_fd = fd, x_param = param, x_value = value;
+
+ FSETI (&x_fd, &x_param, &x_value);
+}
diff --git a/sys/libc/cfstati.c b/sys/libc/cfstati.c
new file mode 100644
index 00000000..aacf670a
--- /dev/null
+++ b/sys/libc/cfstati.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_FSTATI -- FIO get integer file parameter.
+*/
+int
+c_fstati (
+ XINT fd, /* FIO file descriptor */
+ int param /* param to be queried */
+)
+{
+ XINT x_fd = fd, x_param = param;
+
+ return (FSTATI (&x_fd, &x_param));
+}
diff --git a/sys/libc/cgetpid.c b/sys/libc/cgetpid.c
new file mode 100644
index 00000000..69ad6133
--- /dev/null
+++ b/sys/libc/cgetpid.c
@@ -0,0 +1,15 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_GETPID -- Get the process id.
+*/
+int
+c_getpid ( void )
+{
+ return ((int) GETPID());
+}
diff --git a/sys/libc/cgetuid.c b/sys/libc/cgetuid.c
new file mode 100644
index 00000000..cb86f4a3
--- /dev/null
+++ b/sys/libc/cgetuid.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_GETUID -- Get the user identification string (user name).
+*/
+char *
+c_getuid (
+ char *outstr, /* user name, C string */
+ int maxch /* max chars out, incl EOS */
+)
+{
+ XCHAR spp_uid[SZ_FNAME+1];
+ XINT x_maxch = SZ_FNAME;
+
+
+ GETUID (spp_uid, &x_maxch);
+ return (c_strpak (spp_uid, outstr, maxch));
+}
diff --git a/sys/libc/cgflush.c b/sys/libc/cgflush.c
new file mode 100644
index 00000000..8d5fe072
--- /dev/null
+++ b/sys/libc/cgflush.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_GFLUSH -- Flush any buffered graphics output.
+*/
+void
+c_gflush (
+ int stream /* graphics stream */
+)
+{
+ XINT x_stream = stream;
+
+ GTR_GFLUSH (&x_stream);
+}
diff --git a/sys/libc/cimaccess.c b/sys/libc/cimaccess.c
new file mode 100644
index 00000000..17d2e874
--- /dev/null
+++ b/sys/libc/cimaccess.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_IMACCESS -- IMIO test if image can be accessed (exists). 1 is returned
+** if the image exists and is unique, 0 if the image does not exist, and ERR
+** if the image name ambiguous and multiple images exist matching that name.
+*/
+int
+c_imaccess (
+ char *imname, /* name of image to be accessed */
+ int mode /* access mode */
+)
+{
+ int status;
+ XINT x_mode = mode;
+
+
+ iferr (status = (int) IMACCESS (c_sppstr(imname), &x_mode))
+ return (ERR);
+ else
+ return (status);
+}
diff --git a/sys/libc/cimdrcur.c b/sys/libc/cimdrcur.c
new file mode 100644
index 00000000..1ac9f85b
--- /dev/null
+++ b/sys/libc/cimdrcur.c
@@ -0,0 +1,39 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_IMDRCUR -- Read the logical image cursor (temporary routine, will be
+** phased out in a later release).
+*/
+int
+c_imdrcur (
+ char *device, /* logical device name or "stdimage" */
+ float *x, /* cursor X coordinate (out) */
+ float *y, /* cursor Y coordinate (out) */
+ int *wcs, /* wcs of coords (out, = frame*100+d_wcs) */
+ int *key, /* keystroke which triggered read (out) */
+ char *strval, /* string value, if key=':' */
+ int maxch, /* max chars out */
+ int d_wcs, /* 0 for frame coords, 1 for image coords */
+ int pause /* true to pause for key to terminate read */
+)
+{
+ PKCHAR x_strval[SZ_LINE+1];
+ XINT x_maxch = maxch, x_d_wcs = d_wcs, x_pause = pause;
+ XINT x_wcs, x_key;
+
+
+ if (IMDRCUR (c_sppstr(device), x, y, &x_wcs, &x_key, x_strval, &x_maxch,
+ &x_d_wcs, &x_pause) >= 0)
+ c_strpak (x_strval, strval, maxch);
+
+ *wcs = x_wcs;
+ *key = x_key;
+
+ return (*key = (*key == XEOF) ? EOF : *key);
+}
diff --git a/sys/libc/ckimapc.c b/sys/libc/ckimapc.c
new file mode 100644
index 00000000..6653dd29
--- /dev/null
+++ b/sys/libc/ckimapc.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_KIMAPCHAN -- Map a KI channel number into the corresponding OS channel
+** number or pid and node name.
+*/
+int
+c_kimapchan (
+ int chan, /* KI channel number */
+ char *nodename, /* receives server node name */
+ int maxch /* maxch chars out */
+)
+{
+ XCHAR x_nodename[SZ_FNAME+1];
+ XINT ki_chan = chan, x_maxch = SZ_FNAME;
+ int os_chan;
+
+ os_chan = (int) KI_MAPCHAN (&ki_chan, x_nodename, &x_maxch);
+ c_strpak (x_nodename, nodename, SZ_FNAME);
+
+ return (os_chan);
+}
diff --git a/sys/libc/clexnum.c b/sys/libc/clexnum.c
new file mode 100644
index 00000000..6e5091bc
--- /dev/null
+++ b/sys/libc/clexnum.c
@@ -0,0 +1,54 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_ctype
+#define import_lexnum
+#define import_xnames
+#include <iraf.h>
+
+
+/* LEXNUM -- Lexically analyze a string to determine if it is a legal IRAF
+** style number. Returns one of the following tokens (lexnum.h):
+**
+** LEX_OCTAL octal number (e.g. B suffix)
+** LEX_HEX hex number (e.g. X suffix)
+** LEX_DECIMAL decimal number
+** LEX_REAL real number (incl sexagesimal)
+** LEX_NONNUM nonnumeric
+**
+** A numeric token is returned if any (prefix) portion of the field is
+** numeric. The total number of numeric characters is also returned so
+** that the application may verify that the entire field was numeric,
+** if desired.
+*/
+int
+c_lexnum (
+ char *str, /* input string */
+ int *toklen /* nchars in token */
+)
+{
+ register char *ip;
+ register XCHAR *op, ch, ndigits;
+ PKCHAR numbuf[SZ_FNAME];
+ XINT ip_start = 1, x_toklen = *toklen;
+ int status;
+
+
+ /* Convert number to XCHAR for lexnum. In the process check to see
+ * if we have a simple decimal integer constant to save a scan.
+ */
+ for (ip=str, op=numbuf, ndigits=0; (*op++ = ch = *ip++); )
+ if (isdigit (ch))
+ ndigits++;
+
+ if (ndigits == (ip - str - 1)) {
+ *toklen = ndigits;
+ return (LEX_DECIMAL);
+ } else {
+ status = LEXNUM (numbuf, &ip_start, &x_toklen);
+ *toklen = (int) x_toklen;
+ return (status);
+ }
+}
diff --git a/sys/libc/cmktemp.c b/sys/libc/cmktemp.c
new file mode 100644
index 00000000..cdc9e5a7
--- /dev/null
+++ b/sys/libc/cmktemp.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_MKTEMP -- FIO make temporary (unique) filename.
+*/
+int
+c_mktemp (
+ char *root, /* root filename */
+ char *temp_filename, /* generated filename */
+ int maxch /* max chars in output filename */
+)
+{
+ XCHAR temp[SZ_FNAME+1];
+ XINT sz_temp = SZ_FNAME;
+
+
+ iferr (MKTEMP (c_sppstr(root), temp, &sz_temp))
+ return (0);
+ else
+ return (strlen (c_strpak (temp, temp_filename, maxch)));
+}
diff --git a/sys/libc/cndopen.c b/sys/libc/cndopen.c
new file mode 100644
index 00000000..1a6920be
--- /dev/null
+++ b/sys/libc/cndopen.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_NDOPEN -- Network driver FIO file open.
+*/
+int
+c_ndopen (
+ char *fname, /* name of file to be opened */
+ int mode /* access mode */
+)
+{
+ int fd;
+ XINT x_mode = mode;
+
+ iferr (fd = NDOPEN (c_sppstr(fname), &x_mode))
+ return (ERR);
+ else
+ return (fd);
+}
diff --git a/sys/libc/cnote.c b/sys/libc/cnote.c
new file mode 100644
index 00000000..c62a0b02
--- /dev/null
+++ b/sys/libc/cnote.c
@@ -0,0 +1,29 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_fset
+#include <iraf.h>
+
+
+/* C_NOTE -- FIO note file offset. If the actual file is a text file the
+** seek offset is a magic number and is returned unchanged. If the actual
+** file is a binary file the seek offset is returned as a zero-indexed byte
+** offset.
+*/
+long
+c_note (
+ XINT fd /* FIO file descriptor */
+)
+{
+ long xchar_offset;
+ XINT x_fd = fd;
+
+ xchar_offset = (long) NOTE (&x_fd);
+ if (c_fstati (fd, F_TYPE) == BINARY_FILE)
+ return ((xchar_offset - 1) * sizeof(XCHAR));
+ else
+ return (xchar_offset);
+}
diff --git a/sys/libc/copen.c b/sys/libc/copen.c
new file mode 100644
index 00000000..144dc5d4
--- /dev/null
+++ b/sys/libc/copen.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_OPEN -- FIO file open.
+*/
+int
+c_open (
+ char *fname, /* name of file to be opened */
+ int mode, /* access mode */
+ int type /* file type */
+)
+{
+ int fd;
+ XINT x_mode = mode, x_type = type;
+
+ iferr (fd = (int) OPEN (c_sppstr(fname), &x_mode, &x_type))
+ return (ERR);
+ else
+ return (fd);
+}
diff --git a/sys/libc/coscmd.c b/sys/libc/coscmd.c
new file mode 100644
index 00000000..d6185bfe
--- /dev/null
+++ b/sys/libc/coscmd.c
@@ -0,0 +1,33 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_OSCMD -- Send a command to the host system. If the filename strings
+** are nonnull the kernel will attempt to redirect the standard i/o streams
+** to the indicated streams during execution of the command. OK is returned
+** if execution is completes successfully, otherwise a positive integer error
+** code is returned.
+*/
+int
+c_oscmd (
+ char *cmd, /* command to be executed */
+ char *infile, /* stdin file */
+ char *outfile, /* stdout file */
+ char *errfile /* stderr file */
+)
+{
+ XCHAR spp_infile[SZ_FNAME+1];
+ XCHAR spp_outfile[SZ_FNAME+1];
+ XCHAR spp_errfile[SZ_FNAME+1];
+
+ c_strupk (infile, spp_infile, SZ_FNAME);
+ c_strupk (outfile, spp_outfile, SZ_FNAME);
+ c_strupk (errfile, spp_errfile, SZ_FNAME);
+
+ return (OSCMD (c_sppstr(cmd), spp_infile, spp_outfile, spp_errfile));
+}
diff --git a/sys/libc/cpoll.c b/sys/libc/cpoll.c
new file mode 100644
index 00000000..65f05274
--- /dev/null
+++ b/sys/libc/cpoll.c
@@ -0,0 +1,150 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_fpoll
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_POLL -- LIBC binding to the FIO polling interface.
+**
+** fds = c_poll_open () # open a poll descriptor set
+** npolls = c_poll (fds, nfds, timeout) # poll the set
+** c_poll_close (fds) # free the poll descriptor set
+**
+** c_poll_zero (fds) # zero the poll array
+** c_poll_set (fds, fd, type) # set fd to poll for type
+** c_poll_clear (fds, fd, type) # unset type on fd poll
+** y/n = c_poll_test (fds, fd, type) # test fd for type event
+** c_poll_print (fds) # print the poll array
+** N = c_poll_get_nfds (fds) # get size of descriptor set
+*/
+
+
+/* C_POLL_OPEN -- Open a poll descriptor set.
+*/
+XINT
+c_poll_open ( void )
+{
+ XINT fds;
+
+ iferr ((fds = (XINT) POLL_OPEN ()))
+ return (NULL);
+ else
+ return (fds);
+}
+
+
+/* C_POLL -- Poll the descriptor set.
+*/
+int
+c_poll (
+ XINT fds, /* descriptor set ptr */
+ int nfds, /* no. descriptors */
+ int timeout /* poll timeout */
+)
+{
+ XINT x_fds = fds, x_nfds = nfds, x_timeout = timeout;
+
+ return ((int) POLL (&x_fds, &x_nfds, &x_timeout));
+}
+
+
+/* C_POLL_CLOSE -- Close and free a poll descriptor set.
+*/
+void
+c_poll_close (
+ XINT fds /* descriptor set ptr */
+)
+{
+ XINT x_fds = fds;
+
+ POLL_CLOSE (&x_fds);
+}
+
+
+/* C_POLL_ZERO -- Zero the descriptor set.
+*/
+void
+c_poll_zero (
+ XINT fds /* descriptor set ptr */
+)
+{
+ XINT x_fds = fds;
+
+ POLL_ZERO (&x_fds);
+}
+
+
+/* C_POLL_SET -- Add a descriptor to the set, and/or modify the event type.
+** The type may be a bitwise or of testable events.
+*/
+void
+c_poll_set (
+ XINT fds, /* descriptor set ptr */
+ XINT fd, /* no. descriptors */
+ int type /* event type */
+)
+{
+ XINT x_fds = fds, x_fd = fd, x_type = type;
+
+ POLL_SET (&x_fds, &x_fd, &x_type);
+}
+
+
+/* C_POLL_CLEAR -- Remove a descriptor or event type from the set. The type
+** may be a bitwise or of testable events. If the event mask becomes NULL the
+** descriptor is removed entirely from the set.
+*/
+void
+c_poll_clear (
+ XINT fds, /* descriptor set ptr */
+ XINT fd, /* no. descriptors */
+ int type /* event type */
+)
+{
+ XINT x_fds = fds, x_fd = fd, x_type = type;
+
+ POLL_CLEAR (&x_fds, &x_fd, &x_type);
+}
+
+
+/* C_POLL_TEST -- Test the descriptor for the given event type.
+*/
+int
+c_poll_test (
+ XINT fds, /* descriptor set ptr */
+ XINT fd, /* no. descriptors */
+ int type /* event type */
+)
+{
+ XINT x_fds = fds, x_fd = fd, x_type = type;
+
+ return ((int) POLL_TEST (&x_fds, &x_fd, &x_type));
+}
+
+
+/* C_POLL_GET_NFDS -- Return the size of the descriptor set.
+*/
+int
+c_poll_get_nfds (
+ XINT fds /* descriptor set ptr */
+)
+{
+ XINT x_fds = fds;
+
+ return (POLL_GET_NFDS (&x_fds));
+}
+
+
+/* C_POLL_PRINT -- Debug print utility.
+*/
+void
+c_poll_print (XINT fds)
+{
+ XINT x_fds = fds;
+
+ POLL_PRINT (&x_fds);
+}
diff --git a/sys/libc/cprcon.c b/sys/libc/cprcon.c
new file mode 100644
index 00000000..c0534a60
--- /dev/null
+++ b/sys/libc/cprcon.c
@@ -0,0 +1,198 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#define import_prstat
+#include <iraf.h>
+
+
+/* CPRCON -- Connected subprocesses. A connected subprocess is an active filter
+** which communicates with the parent process via an input stream and an output
+** stream. A connected subprocess is logically equivalent to the user terminal.
+** The set of useful operations thus far identified for connected subprocesses
+** are open and close, read and write, and signal (interrupt). The read and
+** write operations are provided by interfacing the IPC channels from the
+** subprocess to FIO. The remaining operations are peculiar to connected
+** subprocesses and are summarized below.
+**
+** pid = c_propen (process, in, out)
+** stat = c_prclose (pid)
+** stat = c_prstati (pid, param)
+** c_prsignal (pid, signal)
+** c_prredir (pid, stream, new_fd)
+** c_prchdir (pid, newdir)
+** c_prenvset (pid, envvar, valuestr)
+**
+** A connected subprocess must be opened either with c_propen or with the low
+** level procedure PROPCPR (the latter does not require that the subprocess
+** recognize the standard IPC protocol). An idle subprocess may be closed
+** with c_prclose, which not only closes the process but releases important
+** system resources. The c_prsignal procedure raises the X_INT (interrupt)
+** exception in a subprocess, generally following receipt of a user interrupt
+** by the parent process. Redirection of the child's standard i/o streams
+** is provided by c_prredir. Finally, c_prchdir and c_prenvsets are used
+** to update the current directory and environment in child processes.
+*/
+
+
+/* C_PROPEN -- Open a connected subprocess, i.e., spawn the subprocess and
+** connect the two IPC channels connecting the child and parent to FIO.
+** The FIO streams may subsequently be opened for C style STDIO by calling
+** FDOPEN, if desired. The C_PROPEN procedure sends the current environment
+** and working directory to the child as part of process startup. The process
+** id (PID) of the child process is returned as the function value. This
+** magic integer value uniquely identifies the process to the system.
+**
+** N.B.: opening a child process leaves the child in the IRAF Main interpreter
+** loop, with the child waiting for a command from the parent. A child process
+** is capabable of performing an arbitrary number of "tasks". To get the child
+** to run a task, the parent must write the name of the task to the OUT stream,
+** then read from the IN stream, responding to all queries from the child until
+** "bye" or "error" is received.
+*/
+unsigned int
+c_propen (
+ char *process, /* filename of executable process */
+ int *in, /* FD for reading from child */
+ int *out /* FD for writing to child */
+)
+{
+ register unsigned int pid;
+ XINT x_in = *in, x_out = *out;
+
+ iferr (pid = (unsigned int) PROPEN (c_sppstr(process), &x_in, &x_out))
+ return (NULL);
+ else {
+ *in = (int) x_in;
+ *out = (int) x_out;
+ FDTOFP(*in)->_fflags |= _FIPC;
+ return (pid);
+ }
+}
+
+
+/* C_PRCLOSE -- Close a connected subprocess. The "bye" command is sent to
+** the child, commanding it to shut down, and when the task terminates the
+** exit status is returned as the function value. The C_PRCLOSE procedure
+** must be called at process termination to free system resources. C_PRCLOSE
+** is automatically called by the system if error recovery takes place in
+** the parent process. Calling C_PRCLOSE is equivalent to individually
+** closing the IN and OUT streams to the subprocess (which is what happens
+** if system error recovery takes place).
+*/
+int
+c_prclose (
+ unsigned int pid /* process id returned by C_PROPEN */
+)
+{
+ XINT x_pid = pid;
+
+ return (PRCLOSE (&x_pid));
+}
+
+
+/* C_PRSTATI -- Get status on a connected subprocess. See <libc/prstat.h>
+** for a list of parameters.
+*/
+int
+c_prstati (
+ int pid, /* process id of process */
+ int param /* parameter for which value is ret */
+)
+{
+ XINT x_pid = pid, x_param = param;
+
+ return (PRSTATI (&x_pid, &x_param));
+}
+
+
+/* C_PRSIGNAL -- Send a signal, i.e., asynchronous interrupt, to a connected
+** child process. Currently only the X_INT signal is implemented, and the
+** second argument is not used. The value X_INT should nontheless be passed.
+*/
+int
+c_prsignal (
+ unsigned pid, /* process id of process */
+ int signal /* not used at present */
+)
+{
+ XINT x_pid = pid, x_signal = signal;
+
+ iferr (PRSIGNAL (&x_pid, &x_signal))
+ return (ERR);
+ else
+ return (OK);
+}
+
+
+/* C_PRREDIR -- Redirect one of the standard i/o streams of the child process.
+** By default the child inherits the standard i/o streams of the parent at
+** C_PROPEN time, i.e., the STDOUT of the child is connected to the STDOUT of
+** the parent. If the parent's STDOUT is subsequently redirected, e.g., with
+** C_FREDIR, the child's output will be redirected as well. More commonly
+** one or more of the child's streams will be explicitly redirected with
+** C_PRREDIR. Such redirection remains in effect for the life of the
+** process, i.e., until process termination via C_PRCLOSE or until another
+** call to C_PRREDIR. Note that often this is not what is desired, rather,
+** one wishes to redirect a stream for the duration of a task running within
+** the process. For this reason it is recommended that C_PRREDIR be called
+** for each standard stream (it costs almost nothing) immediately prior to
+** task execution.
+**
+** Example:
+** fp = fopen ("tmp$spoolfile", "w");
+** if (c_prredir (pid, STDOUT, fileno(fp)) == ERR)
+** ...
+*/
+int
+c_prredir (
+ unsigned pid, /* process id of child */
+ int stream, /* child's stream to be redirected */
+ int new_fd /* FD of opened file in parent */
+)
+{
+ XINT x_pid = pid, x_stream = stream, x_new_fd = new_fd;
+
+ iferr (PRREDIR (&x_pid, &x_stream, &x_new_fd))
+ return (ERR);
+ else
+ return (OK);
+}
+
+
+/* C_PRCHDIR -- Change the current working directory of a child process.
+** If pid=NULL all currently connected processes are updated. May only
+** be called when the child process is idle.
+*/
+int
+c_prchdir (
+ int pid,
+ char *newdir
+)
+{
+ XINT x_pid = pid;
+
+ return (PRCHDIR (&x_pid, c_sppstr (newdir)));
+}
+
+
+/* C_PRENVSET -- Transmit a set environment directive to the child process.
+** If pid=NULL all currently connected processes are updated. May only
+** be called when the child process is idle.
+*/
+int
+c_prenvset (
+ int pid,
+ char *envvar,
+ char *value
+)
+{
+ XCHAR spp_value[SZ_LINE];
+ XINT x_pid = pid;
+
+ c_strupk (value, spp_value, SZ_LINE);
+ return (PRENVSET (&x_pid, c_sppstr (envvar), spp_value));
+}
diff --git a/sys/libc/cprdet.c b/sys/libc/cprdet.c
new file mode 100644
index 00000000..92829723
--- /dev/null
+++ b/sys/libc/cprdet.c
@@ -0,0 +1,109 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/*
+** CPRDET -- Detached processes. A detached process is a process which runs
+** asynchronously with and independently of the parent, generally without
+** interprocess communication during execution. The primary example of a
+** detached process in IRAF is the CL process spawned by an interactive CL
+** to execute a command in the background.
+**
+** The parent communicates with the child by means of the "bkgfile", the name
+** of which is passed by the system to the child during process startup.
+** While the format and contents of the bkgfile are in general application
+** dependent, the system default action is to open the bkgfile as a text file
+** and read commands from it. The CL process does not make use of this
+** default, but rather uses its own special format binary file to communicate
+** the full runtime context of the parent to the child, partially emulating
+** the UNIX fork. The system automatically deletes the bkgfile when the
+** child process terminates.
+**
+** N.B.: The environment and cwd are not automatically passed to the child,
+** as they are for a connected subprocess. The application must see to it
+** that this information is passed in the bkgfile if needed by the child.
+*/
+
+/* C_PROPDPR -- Open a detached process. The named process is either spawned
+** or queued for delayed execution (depending on the system and other factors).
+** When the process eventually runs it reads the bkgfile passed by the parent
+** to determine what to do. When the process terminates, either normally or
+** abnormally, the system deletes the bkgfile. Deletion of the bkgfile signals
+** process termination.
+*/
+unsigned int
+c_propdpr (
+ char *process, /* filename of executable file */
+ char *bkgfile, /* filename of bkgfile */
+ char *bkgmsg /* control string for kernel */
+)
+{
+ unsigned job;
+ XCHAR spp_bkgfile[SZ_PATHNAME];
+ XCHAR spp_bkgmsg[SZ_LINE];
+
+
+ c_strupk (bkgfile, spp_bkgfile, SZ_PATHNAME);
+ c_strupk (bkgmsg, spp_bkgmsg, SZ_LINE);
+ iferr (job = PROPDPR (c_sppstr(process), spp_bkgfile, spp_bkgmsg))
+ return (NULL);
+ else
+ return (job);
+}
+
+
+/* C_PRCLDPR -- Close a detached process. Wait (indefinitely) for process
+** termination, then free all system resources allocated to the process.
+** Should be called if a detached process terminated while the parent is
+** still executing. The exit status of the child is returned as the function
+** value; the value OK (0) indicates normal termination. A positive value
+** is the error code of the error which caused abnormal process termination.
+*/
+int
+c_prcldpr (
+ unsigned job /* job code from C_PROPDPR */
+)
+{
+ XINT x_job = job;
+
+ return (PRCLDPR (&x_job));
+}
+
+
+/* C_PRDONE -- Determine if a bkg job is still executing (function return NO)
+** or has terminated (function return YES).
+*/
+int
+c_prdone (
+ unsigned job /* job code from C_PROPDPR */
+)
+{
+ XINT x_job = job;
+
+ return (PRDONE (&x_job));
+}
+
+
+/* C_PRKILL -- Kill a bkg job. If the bkg job has begun execution it is
+** killed without error recovery. If the bkg job is still sitting in a queue
+** it is dequeued. C_PRKILL returns ERR for an illegal jobcode or if sufficient
+** permission is not available to kill the job. C_PRCLDPR should subsequently
+** be called to wait for process termination and free system resources.
+*/
+int
+c_prkill (
+ unsigned job /* job code from C_PROPDPR */
+)
+{
+ XINT x_job = job;
+
+ iferr (PRKILL (&x_job))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cprintf.c b/sys/libc/cprintf.c
new file mode 100644
index 00000000..dd317f69
--- /dev/null
+++ b/sys/libc/cprintf.c
@@ -0,0 +1,53 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_PRINTF -- Formatted print to STDOUT.
+*/
+int
+c_printf (
+ char *format /* format string */
+)
+{
+ iferr (PRINTF (c_sppstr(format)))
+ return (ERR);
+ else
+ return (OK);
+}
+
+
+/* C_FPRINTF -- Formatted print to given file.
+*/
+int
+c_fprintf (
+ XINT fd, /* output file */
+ char *format /* format string */
+)
+{
+ XINT x_fd = fd;
+
+ iferr (FPRINTF (&x_fd, c_sppstr(format)))
+ return (ERR);
+ else
+ return (OK);
+}
+
+
+void c_pargb (int ival) { XINT x_ival = ival; PARGI (&x_ival); }
+void c_pargc (int ival) { XINT x_ival = ival; PARGI (&x_ival); }
+void c_pargs (short sval) { XSHORT x_sval = sval; PARGS (&x_sval); }
+void c_pargi (int ival) { XINT x_ival = ival; PARGI (&x_ival); }
+void c_pargl (long lval) { XLONG x_lval = lval; PARGL (&x_lval); }
+void c_pargr (float rval) { XREAL x_rval = rval; PARGR (&x_rval); }
+void c_pargd (double dval) { XDOUBLE x_dval = dval; PARGD (&x_dval); }
+
+
+void c_pargstr (char *strval)
+{
+ PARGSTR (c_sppstr(strval));
+}
diff --git a/sys/libc/crcursor.c b/sys/libc/crcursor.c
new file mode 100644
index 00000000..695c9668
--- /dev/null
+++ b/sys/libc/crcursor.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_RCURSOR -- Read a cursor.
+*/
+int
+c_rcursor (
+ int fd, /* FIO file descriptor */
+ char *outstr, /* output string */
+ int maxch
+)
+{
+ XCHAR buf[SZ_LINE];
+ XINT x_fd = fd, x_maxch = maxch;
+ int key;
+
+
+ key = (int) RCURSOR (&x_fd, buf, &x_maxch);
+ c_strpak (buf, outstr, maxch);
+
+ return (key == XEOF ? EOF : key);
+}
diff --git a/sys/libc/crdukey.c b/sys/libc/crdukey.c
new file mode 100644
index 00000000..a0b7042c
--- /dev/null
+++ b/sys/libc/crdukey.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_RDUKEY -- Read a user keystroke object from the terminal in raw mode.
+*/
+int
+c_rdukey (
+ char *obuf, /* output buffer */
+ int maxch /* maxc chars out */
+)
+{
+ XCHAR buf[SZ_LINE+1];
+ XINT x_maxch = SZ_LINE;
+ int status;
+
+
+ obuf[0] = EOS;
+ if ((status = (int) RDUKEY (buf, &x_maxch)) > 0)
+ c_strpak (buf, obuf, maxch);
+
+ return (status);
+}
diff --git a/sys/libc/cread.c b/sys/libc/cread.c
new file mode 100644
index 00000000..8cc727a5
--- /dev/null
+++ b/sys/libc/cread.c
@@ -0,0 +1,70 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#define import_error
+#define import_fset
+#include <iraf.h>
+
+
+/* C_READ -- FIO read from a file. Read up to maxbytes bytes from the stream
+** fd into the buffer buf. If the device associated with file fd is a record
+** structured device a single record is read, and the byte count will generally
+** be less than the maximum. If the physical record was larger than maxbytes
+** the remainder of the record is returned in successive reads. If the actual
+** file is a text file FIO XCHARs are returned as C chars. If the actual file
+** is a binary file no conversion is performed, and an integral number of XCHARs
+** are read.
+**
+** For reasons of consistency with SPP usage, EOF is returned when end of file
+** is reached (fread returns 0), and an error action is taken if a file read
+** error occurs. We cannot return ERR when an error occurs since ERR and EOF
+** have the same value in STDIO land. IFERR may be used to catch file read
+** errors.
+*/
+int
+c_read (
+ XINT fd, /* FIO file descriptor */
+ char *buf, /* output buffer */
+ int maxbytes /* max bytes to read */
+)
+{
+ XINT x_fd = fd;
+ int nchars_read;
+
+
+ if (c_fstati (fd, F_TYPE) == TEXT_FILE) {
+ register char *op = buf;
+ register int ch, n = maxbytes;
+ register FILE *fp = FDTOFP(fd);
+
+ while (--n >= 0 && (ch = getc(fp)) >= 0) {
+ *op++ = ch;
+ if (ch == '\n')
+ break;
+ }
+ if (ferror (fp))
+ c_erract (EA_ERROR);
+ if (!(nchars_read = op - buf))
+ nchars_read = XEOF;
+
+ } else {
+ XINT x_maxchars = maxbytes / sizeof(XCHAR);
+ XCHAR *bp = (XCHAR *)buf;
+
+ /* Verify that the pointer coercion char->XCHAR->char is legal,
+ * i.e., that the char pointer is aligned to an XCHAR word
+ * boundary if required on this machine.
+ */
+ if (buf != (char *)bp)
+ c_error (1, "c_read: buffer not xchar aligned");
+
+ if ((nchars_read = READ (&x_fd, bp, &x_maxchars)) > 0)
+ nchars_read *= sizeof(XCHAR);
+ }
+
+ return (nchars_read == XEOF ? EOF : nchars_read);
+}
diff --git a/sys/libc/crename.c b/sys/libc/crename.c
new file mode 100644
index 00000000..5f5b6668
--- /dev/null
+++ b/sys/libc/crename.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_RENAME -- FIO rename file.
+*/
+int
+c_rename (
+ char *old_fname, /* current name of file */
+ char *new_fname /* new file name */
+)
+{
+ XCHAR spp_new_fname[SZ_FNAME];
+ int maxch = SZ_FNAME;
+
+ c_strupk (new_fname, spp_new_fname, maxch);
+ iferr (RENAME (c_sppstr(old_fname), spp_new_fname))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/creopen.c b/sys/libc/creopen.c
new file mode 100644
index 00000000..da38703e
--- /dev/null
+++ b/sys/libc/creopen.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_REOPEN -- Reopen a binary file.
+*/
+int
+c_reopen (
+ XINT fd, /* FIO file descriptor */
+ int mode /* access mode */
+)
+{
+ XINT x_fd = fd, x_mode = mode;
+ int new_fd;
+
+
+ iferr (new_fd = (int) REOPEN (&x_fd, &x_mode))
+ return (ERR);
+ else
+ return (new_fd);
+}
+
diff --git a/sys/libc/csalloc.c b/sys/libc/csalloc.c
new file mode 100644
index 00000000..823c0bca
--- /dev/null
+++ b/sys/libc/csalloc.c
@@ -0,0 +1,80 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/*
+** CSALLOC -- Dynamic memory allocation on the SPP stack.
+**
+** c_smark (&sp)
+** c_sfree (sp)
+** ptr = c_salloc (nbytes)
+**
+** A contiguous segment of dynamic storage may be allocated with C_SALLOC,
+** much as is done with the UNIX emulation procedure MALLOC. All buffer
+** space allocated on the stack since a call to C_SMARK to mark the position
+** of the stack pointer may be freed in a single call to C_SFREE.
+**
+** The stack is implemented as a linked list of a few large buffers allocated
+** on the heap with MALLOC, each of which normally contains many small buffers
+** allocated with individual C_SALLOC calls. Stack allocation is very
+** efficient for buffers small enough to fit into a stack segment. If it is
+** necessary to add a new segment to accomodate a large buffer, the expense is
+** about the same as for a buffer allocation with MALLOC.
+*/
+
+
+/* C_SALLOC -- Allocate a contiguous segment of memory on the stack. The
+** contents of the buffer will be uninitialized. The buffer is guaranteed to
+** have at least XDOUBLE alignment with the Mem common. One extra XCHAR
+** of storage is automatically allocated for the EOS delimiter in the event
+** that the buffer is used to hold a character string (thus it is not necessary
+** to be forever adding +1 in calls to the memory allocator).
+**
+** N.B.: it is a fatal error if storage cannot be allocated on the stack,
+** hence error checking is not necessary.
+*/
+char *
+c_salloc (
+ unsigned nbytes /* nbytes of storage to be allocated */
+)
+{
+ XINT buf;
+ XINT x_nchars = nbytes, x_dtype = TY_CHAR;
+
+
+ x_nchars = (nbytes + sizeof(XCHAR)-1) / sizeof(XCHAR);
+ SALLOC (&buf, &x_nchars, &x_dtype);
+ return ((char *)&Memc[buf]);
+}
+
+
+/* C_SMARK -- Mark the position of the stack pointer.
+*/
+void
+c_smark (
+ int *sp /* stack pointer is saved here */
+)
+{
+ XINT x_sp = *sp;
+
+ SMARK (&x_sp);
+ *sp = x_sp;
+}
+
+
+/* C_SFREE -- Free all stack storage allocated since the stack pointer passed as
+** the sole argument was marked by C_SMARK.
+*/
+void
+c_sfree (
+ int sp /* saved stack pointer */
+)
+{
+ XINT x_sp = sp;
+
+ SFREE (&x_sp);
+}
diff --git a/sys/libc/cseek.c b/sys/libc/cseek.c
new file mode 100644
index 00000000..58cedcc3
--- /dev/null
+++ b/sys/libc/cseek.c
@@ -0,0 +1,42 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_fset
+#include <iraf.h>
+
+
+/* C_SEEK -- FIO seek on a file. If the actual file is a text file the
+** seek offset is assumed to have been obtained by a prior call to FTELL
+** and is passed on unchanged. If the actual file is a binary file the
+** seek offset is a zero-indexed byte offset. This offset is converted
+** to a one-indexed XCHAR offset; it is an error if the offset is not
+** aligned to an XCHAR word boundary.
+*/
+int
+c_seek (
+ XINT fd, /* FIO file descriptor */
+ long offset /* file offset */
+)
+{
+ XLONG x_char_offset = offset;
+ XINT x_fd = fd;
+ int bypass;
+
+
+ bypass = (offset == BOFL || offset == EOFL
+ || c_fstati (fd, F_TYPE) == TEXT_FILE);
+
+ if (!bypass) {
+ x_char_offset /= sizeof(XCHAR);
+ if ((x_char_offset++ * sizeof(XCHAR)) != offset)
+ return ((long) ERR);
+ }
+
+ iferr (SEEK (&x_fd, &x_char_offset))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/csppstr.c b/sys/libc/csppstr.c
new file mode 100644
index 00000000..ce7c9461
--- /dev/null
+++ b/sys/libc/csppstr.c
@@ -0,0 +1,31 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#include <iraf.h>
+
+#define SZ_UPKSTR SZ_COMMAND
+static XCHAR u_upkstr[SZ_UPKSTR+1];
+
+/* C_SPPSTR -- Unpack a C string into an SPP string. This routine is offered
+** as a convenient alternative to C_STRUPK for cases when the length of the
+** string is known to be short and the value will be used before we are again
+** called. The unpacked string is left in a static internal buffer and a
+** pointer to XCHAR is returned as the function value.
+*/
+XCHAR *
+c_sppstr (
+ char *str
+)
+{
+ register char *ip = str;
+ register XCHAR *op = u_upkstr;
+ register int n = SZ_UPKSTR;
+
+ while (--n >= 0 && (*op++ = *ip++) != XEOS)
+ ;
+ u_upkstr[SZ_UPKSTR] = XEOS;
+
+ return (u_upkstr);
+}
diff --git a/sys/libc/cstropen.c b/sys/libc/cstropen.c
new file mode 100644
index 00000000..ac7d01a8
--- /dev/null
+++ b/sys/libc/cstropen.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_STROPEN -- FIO string-file open.
+*/
+int
+c_stropen (
+ XCHAR *obuf, /* string file-buffer */
+ int maxch, /* max chars in string */
+ int mode /* file access mode */
+)
+{
+ XINT x_maxch = maxch, x_mode = mode;
+ int fd;
+
+ iferr (fd = (int) STROPEN (obuf, &x_maxch, &x_mode))
+ return (ERR);
+ else
+ return (fd);
+}
diff --git a/sys/libc/cstrpak.c b/sys/libc/cstrpak.c
new file mode 100644
index 00000000..6236aa0d
--- /dev/null
+++ b/sys/libc/cstrpak.c
@@ -0,0 +1,35 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#include <iraf.h>
+
+
+/* C_STRPAK -- Pack an SPP string (type XCHAR) into a C string in a user
+** supplied buffer. Return a pointer to the output buffer.
+**
+** N.B.: This routine should be used in preference to STRPAK in C code
+** since the output string is of type char*, rather than XCHAR*.
+*/
+char *
+c_strpak (
+ XCHAR *sppstr, /* SPP string */
+ char *cstr, /* C string */
+ int maxch /* max chars out, incl EOS */
+)
+{
+ register XCHAR *ip = sppstr;
+ register char *op = cstr;
+ register int n = maxch-1;
+
+ if (maxch) {
+ if (sizeof(XCHAR) != sizeof(char) || (char *)sppstr != cstr) {
+ while (--n >= 0 && (*op++ = *ip++) != EOS)
+ ;
+ cstr[maxch-1] = EOS;
+ }
+ }
+
+ return (cstr);
+}
diff --git a/sys/libc/cstrupk.c b/sys/libc/cstrupk.c
new file mode 100644
index 00000000..c8e26e19
--- /dev/null
+++ b/sys/libc/cstrupk.c
@@ -0,0 +1,41 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#define import_spp
+#include <iraf.h>
+
+/* C_STRUPK -- Unpack a C string into an SPP string. This procedure should
+** be called from C in preference to the SPP procedure STRUPK because the
+** input string is declared to be of type char, rather than as an XCHAR
+** array containing packed chars as in STRUPK. The output string is however
+** of type XCHAR since it is expected to be passed to an SPP procedure. A
+** pointer to the output string is returned as the function value for use
+** in argument lists.
+*/
+XCHAR *
+c_strupk (
+ char *str, /* C string */
+ XCHAR *outstr, /* SPP string */
+ int maxch /* max chars out, incl EOS */
+)
+{
+ register char *ip = str;
+ register XCHAR *op = outstr;
+ register int n = maxch-1;
+
+
+ /* Is is necessary to determine the length of the string in order to
+ * be able to unpack the string in place, i.e., from right to left.
+ */
+ if (maxch)
+ if (sizeof(char) != sizeof(XCHAR) || str != (char *)outstr) {
+ n = min (n, strlen(ip));
+ op[n] = XEOS;
+
+ for (n = n - 1; n >= 0; --n)
+ op[n] = ip[n];
+ }
+
+ return (outstr);
+}
diff --git a/sys/libc/ctsleep.c b/sys/libc/ctsleep.c
new file mode 100644
index 00000000..9b89fe08
--- /dev/null
+++ b/sys/libc/ctsleep.c
@@ -0,0 +1,18 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/* C_TSLEEP -- Suspend process execution for the specified number of seconds.
+*/
+void
+c_tsleep (
+ int nseconds
+)
+{
+ XINT x_nsec = nseconds;
+
+ TSLEEP (&x_nsec);
+}
diff --git a/sys/libc/cttset.c b/sys/libc/cttset.c
new file mode 100644
index 00000000..ab252ea2
--- /dev/null
+++ b/sys/libc/cttset.c
@@ -0,0 +1,88 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_STTYCO -- Set terminal driver options via a command string.
+*/
+void
+c_sttyco (
+ char *args,
+ XINT ttin,
+ XINT ttout,
+ XINT outfd
+)
+{
+ XCHAR x_args[SZ_COMMAND];
+ XINT x_ttin = ttin, x_ttout = ttout, x_outfd = outfd;
+
+ c_strupk (args, x_args, SZ_COMMAND);
+ STTYCO (x_args, &x_ttin, &x_ttout, &x_outfd);
+}
+
+
+/* C_TTSETI -- FIO set integer terminal driver parameter.
+*/
+void
+c_ttseti (
+ XINT fd, /* FIO file descriptor */
+ int param, /* param to be set */
+ int value /* new value */
+)
+{
+ XINT x_fd = fd, x_param = param, x_value = value;
+
+ TTSETI (&x_fd, &x_param, &x_value);
+}
+
+
+/* C_TTSTATI -- FIO stat integer terminal driver parameter.
+*/
+int
+c_ttstati (
+ XINT fd, /* FIO file descriptor */
+ int param /* param to be set */
+)
+{
+ XINT x_fd = fd, x_param = param;
+
+ return (TTSTATI (&x_fd, &x_param));
+}
+
+/* C_TTSETS -- FIO set string terminal driver parameter.
+*/
+void
+c_ttsets (
+ XINT fd, /* FIO file descriptor */
+ int param, /* param to be set */
+ char *value /* new value */
+)
+{
+ XINT x_fd = fd, x_param = param;
+
+ TTSETS (&x_fd, &x_param, c_sppstr (value));
+}
+
+
+/* C_TTSTATS -- FIO stat string terminal driver parameter.
+*/
+int
+c_ttstats (
+ XINT fd, /* FIO file descriptor */
+ int param, /* param to be set */
+ char *outstr, /* receives string value */
+ int maxch
+)
+{
+ XCHAR x_sval[SZ_LINE+1];
+ XINT x_fd = fd, x_param = param, x_maxch = SZ_LINE;
+ int nchars;
+
+ nchars = TTSTATS (&x_fd, &x_param, x_sval, &x_maxch);
+ c_strpak (x_sval, outstr, maxch);
+ return (maxch < nchars ? maxch : nchars);
+}
diff --git a/sys/libc/cttycdes.c b/sys/libc/cttycdes.c
new file mode 100644
index 00000000..1d7cfc84
--- /dev/null
+++ b/sys/libc/cttycdes.c
@@ -0,0 +1,19 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/* C_TTYCDES -- Close the TTY descriptor.
+*/
+void
+c_ttycdes (
+ XINT tty /* SPP pointer to descriptor */
+)
+{
+ XINT x_tty = tty;
+
+ TTYCDES (&x_tty);
+}
diff --git a/sys/libc/cttyclear.c b/sys/libc/cttyclear.c
new file mode 100644
index 00000000..e10c274f
--- /dev/null
+++ b/sys/libc/cttyclear.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYCLEAR -- Clear the screen.
+*/
+void
+c_ttyclear (
+ XINT fd, /* output file */
+ XINT tty /* tty descriptor */
+)
+{
+ XINT x_fd = fd, x_tty = tty;
+
+ TTYCLEAR (&x_fd, &x_tty);
+}
diff --git a/sys/libc/cttyclln.c b/sys/libc/cttyclln.c
new file mode 100644
index 00000000..7a6a20ee
--- /dev/null
+++ b/sys/libc/cttyclln.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYCLEARLN -- Clear the current line. The cursor is left positioned to
+** the left margin.
+*/
+void
+c_ttyclearln (
+ XINT fd, /* output file */
+ XINT tty /* tty descriptor */
+)
+{
+ XINT x_fd = fd, x_tty = tty;
+
+ TTYCLEARLN (&x_fd, &x_tty);
+}
diff --git a/sys/libc/cttyctrl.c b/sys/libc/cttyctrl.c
new file mode 100644
index 00000000..8143c8e4
--- /dev/null
+++ b/sys/libc/cttyctrl.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYCTRL -- Lookup a capability in the termcap entry for a device and
+** output the associated control string to the given output file. The baud
+** rate (extracted from the environment at TTYODES time or set in a C_TTYSETI
+** call) determines the number of pad characters output for delays. ERR is
+** returned if the control sequence could not be output.
+*/
+int
+c_ttyctrl (
+ XINT fd, /* output file */
+ XINT tty, /* tty descriptor */
+ char *cap, /* two char capability name */
+ int afflncnt /* number of lines affected */
+)
+{
+ XINT x_fd = fd, x_tty = tty, x_afflncnt = afflncnt;
+
+ return (TTYCTRL (&x_fd, &x_tty, c_sppstr(cap), &x_afflncnt));
+}
diff --git a/sys/libc/cttygetb.c b/sys/libc/cttygetb.c
new file mode 100644
index 00000000..cc1386bc
--- /dev/null
+++ b/sys/libc/cttygetb.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYGETB -- Determine if the named capability exists for a device.
+** Presence of the capability in the termcap entry for the device results
+** in a return value of YES (=1), regardless of the actual datatype of
+** the parameter.
+*/
+int
+c_ttygetb (
+ XINT tty, /* tty descriptor */
+ char *cap /* two char capability name */
+)
+{
+ XINT x_tty = tty;
+
+ return ((int) BTOI ((XBOOL) TTYGETB (&x_tty, c_sppstr(cap))));
+}
diff --git a/sys/libc/cttygeti.c b/sys/libc/cttygeti.c
new file mode 100644
index 00000000..1011dac5
--- /dev/null
+++ b/sys/libc/cttygeti.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYGETI -- Get the value of a termcap capability of type integer.
+** Zero is returned if the device does not have such a capability or if
+** the the value string cannot be interpreted as an integer.
+*/
+XINT
+c_ttygeti (
+ XINT tty, /* tty descriptor */
+ char *cap /* two char capability name */
+)
+{
+ XINT x_tty = tty;
+
+ return ((XINT) TTYGETI (&x_tty, c_sppstr(cap)));
+}
diff --git a/sys/libc/cttygetr.c b/sys/libc/cttygetr.c
new file mode 100644
index 00000000..195d0e87
--- /dev/null
+++ b/sys/libc/cttygetr.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+/* C_TTYGETR -- Get the value of a termcap capability of type real.
+** Zero is returned if the device does not have such a capability or if
+** the the value string cannot be interpreted as a real.
+*/
+float
+c_ttygetr (
+ XINT tty, /* tty descriptor */
+ char *cap /* two char capability name */
+)
+{
+ XINT x_tty = tty;
+
+ return ((float) TTYGETR (&x_tty, c_sppstr(cap)));
+}
diff --git a/sys/libc/cttygets.c b/sys/libc/cttygets.c
new file mode 100644
index 00000000..04aea891
--- /dev/null
+++ b/sys/libc/cttygets.c
@@ -0,0 +1,34 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+#define SZ_CAPSTR 128
+static XCHAR buf[SZ_CAPSTR];
+static XINT szbuf = 128;
+
+
+/* C_TTYGETS -- Get the value of a termcap capability as a character string,
+** suitable for subsequent output to the device with TTYPUTS (assuming the
+** capability is a control function). The number of characters in the output
+** string is returned as the function value.
+*/
+int
+c_ttygets (
+ XINT tty, /* tty descriptor */
+ char *cap, /* two char capability name */
+ char *outstr, /* output string */
+ int maxch /* max chars out, excl EOS */
+)
+{
+ XINT x_tty = tty;
+ int nchars;
+
+ nchars = TTYGETS (&x_tty, c_sppstr(cap), buf, &szbuf);
+ c_strpak (buf, outstr, maxch);
+
+ return (nchars);
+}
diff --git a/sys/libc/cttygoto.c b/sys/libc/cttygoto.c
new file mode 100644
index 00000000..eb6f8922
--- /dev/null
+++ b/sys/libc/cttygoto.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYGOTO -- Move the cursor to the indicated X,Y position (one-indexed).
+*/
+void
+c_ttygoto (
+ XINT fd, /* output file */
+ XINT tty, /* tty descriptor */
+ int col, /* x coordinate */
+ int line /* y coordinate */
+)
+{
+ XINT x_fd = fd, x_tty = tty, x_col = col, x_line = line;
+
+ TTYGOTO (&x_fd, &x_tty, &x_col, &x_line);
+}
diff --git a/sys/libc/cttyinit.c b/sys/libc/cttyinit.c
new file mode 100644
index 00000000..da7da5ab
--- /dev/null
+++ b/sys/libc/cttyinit.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYINIT -- Output the initialization sequence, if any, to the output
+** file.
+*/
+void
+c_ttyinit (
+ XINT fd, /* output file */
+ XINT tty /* tty descriptor */
+)
+{
+ XINT x_fd = fd, x_tty = tty;
+
+ TTYINIT (&x_fd, &x_tty);
+}
diff --git a/sys/libc/cttyodes.c b/sys/libc/cttyodes.c
new file mode 100644
index 00000000..2d7a5cc3
--- /dev/null
+++ b/sys/libc/cttyodes.c
@@ -0,0 +1,89 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/*
+** CTTY -- Terminal control. The TTY package is an interface to the TERMCAP
+** database, originally developed for Berkeley UNIX by Bill Joy. The termcap
+** entry for a particular terminal presents in a condensed form the
+** characteristics of the device, e.g., the number of line and columns on the
+** screen, and how to clear the screen or move the cursor. The TTY routines
+** are used to retrieve such capabilities from the database as well as to
+** send the appropriate characters to a file (terminal) to perform such control
+** functions.
+**
+** tty = c_ttyodes (ttyname)
+** c_ttycdes (tty)
+** c_ttyseti (tty, parameter, value)
+** int = c_ttystati (tty, parameter)
+**
+** bool = c_ttygetb (tty, cap)
+** int = c_ttygeti (tty, cap)
+** float = c_ttygetr (tty, cap)
+** nchars = c_ttygets (tty, cap, &outstr, maxch)
+** c_ttyctrl (fd, tty, cap, afflncnt)
+** c_ttyputs (fd, tty, ctrlstr, afflncnt)
+**
+** c_ttyclear (fd, tty)
+** c_ttyclearln (fd, tty)
+** c_ttygoto (fd, tty, col, line)
+** c_ttyinit (fd, tty)
+** c_ttyputline (fd, tty, text, map_cc)
+** c_ttyso (fd, tty, onflag)
+**
+**
+** Complete descriptions of TTY and termcap are given elsewhere. Briefly, the
+** device descriptor for a particular terminal is opened with ttyodes, which
+** returns a IRAF pointer (C integer) to the binary TTY descriptor. The
+** terminal name may be given as "terminal", in which case ttyodes will look up
+** the name of the default terminal in the environment and search the termcap
+** database for the entry for the named device.
+**
+** The ttyget functions are used to read the capabilities. Capabilities are
+** specified by two character mnemonics (character strings), shown as the cap
+** arguments in the calling sequences above. Control sequences may be output
+** with ttyctrl or with ttyputs, depending on whether you are willing to do a
+** binary search for a particular capability at run time. The remaining high
+** level functions make it easy to perform the more common control functions.
+**
+** Raw mode output to a terminal device is provided by the system interface
+** (the newline and tab characters are exceptions). Raw mode input is provided
+** as an fseti option in FIO. To set raw mode on STDIN:
+**
+** c_fseti (STDIN, F_RAW, YES);
+**
+** While raw mode is in effect input characters are read as they are typed,
+** few or no control characters are recognized, and no echoing is performed.
+** Raw mode is cleared whenever the newline character is sent to the terminal,
+** but will be reset if by the next read if F_RAW remains set.
+*/
+
+
+/* C_TTYODES -- Open the TTY descriptor for a particular terminal device.
+** An SPP pointer to the TTY descriptor is returned as the function value.
+** If the device name is given as "terminal" or "printer", the actual device
+** name is taken to be the value of the environment variable of the same name.
+** If the device name is the filename of a termcap format file, the entry
+** for the first device in the file is loaded (this gives the user a simple
+** means to supply special termcap entries). The name of the default
+** termcap file is given by the environment variable "termcap". TTY maintains
+** a cache of preloaded termcap device entries for frequently referenced
+** devices.
+*/
+XINT
+c_ttyodes (
+ char *ttyname /* termcap name of device */
+)
+{
+ XINT tty;
+
+ iferr (tty = (XINT) TTYODES (c_sppstr (ttyname)))
+ return ((XINT) ERR);
+ else
+ return (tty);
+}
diff --git a/sys/libc/cttyputl.c b/sys/libc/cttyputl.c
new file mode 100644
index 00000000..84fdf90a
--- /dev/null
+++ b/sys/libc/cttyputl.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYPUTLINE -- Put a line of text to the output device. Any device
+** independent control characters embedded in the text, e.g., tab, newline,
+** formfeed, backspace, or the special control codes SO (enter standout mode)
+** or SI (leave standout mode) are converted as necessary to drive the device.
+** Unknown control codes are converted to printable sequences (e.g. ^C) if
+** the map_cc flag is set.
+*/
+void
+c_ttyputline (
+ XINT fd, /* output file */
+ XINT tty, /* tty descriptor */
+ char *line, /* line to be output */
+ int map_cc /* map unknown ctrl chars */
+)
+{
+ XINT x_fd = fd, x_tty = tty, x_map_cc = map_cc;
+
+ TTYPUTLINE (&x_fd, &x_tty, c_sppstr(line), &x_map_cc);
+}
diff --git a/sys/libc/cttyputs.c b/sys/libc/cttyputs.c
new file mode 100644
index 00000000..4d428964
--- /dev/null
+++ b/sys/libc/cttyputs.c
@@ -0,0 +1,29 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYPUTS -- Put a control sequence obtained in a prior call to C_TTYGETS
+** to the output file. The baud rate (extracted from the environment at
+** TTYODES time or set in a C_TTYSETI call) determines the number of pad
+** characters output for delays.
+*/
+int
+c_ttyputs (
+ XINT fd, /* output file */
+ XINT tty, /* tty descriptor */
+ char *cap, /* two char capability name */
+ int afflncnt /* number of lines affected */
+)
+{
+ XINT x_fd = fd, x_tty = tty, x_afflncnt = afflncnt;
+
+ iferr (TTYPUTS (&x_fd, &x_tty, c_sppstr(cap), &x_afflncnt))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cttyseti.c b/sys/libc/cttyseti.c
new file mode 100644
index 00000000..086dd98f
--- /dev/null
+++ b/sys/libc/cttyseti.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYSETI -- Set a TTY interface parameter of type integer.
+*/
+void
+c_ttyseti (
+ XINT tty, /* tty descriptor */
+ int param, /* code of param to be set */
+ int value /* value to be set */
+)
+{
+ XINT x_tty = tty, x_param = param, x_value = value;
+
+ TTYSETI (&x_tty, &x_param, &x_value);
+}
diff --git a/sys/libc/cttyso.c b/sys/libc/cttyso.c
new file mode 100644
index 00000000..3283f83f
--- /dev/null
+++ b/sys/libc/cttyso.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYSO -- Turn standout mode (reverse video, underline, or upper case
+** depending on the device) on or off.
+*/
+void
+c_ttyso (
+ XINT fd, /* output file */
+ XINT tty, /* tty descriptor */
+ int onoff /* 1=on, 0=off */
+)
+{
+ XINT x_fd = fd, x_tty = tty, x_onoff = onoff;
+
+ TTYSO (&x_fd, &x_tty, &x_onoff);
+}
diff --git a/sys/libc/cttystati.c b/sys/libc/cttystati.c
new file mode 100644
index 00000000..9ba254c5
--- /dev/null
+++ b/sys/libc/cttystati.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_TTYSTATI -- Return the value of a TTY integer interface parameter.
+*/
+XINT
+c_ttystati (
+ XINT tty, /* tty descriptor */
+ int param /* code of param to be set */
+)
+{
+ XINT x_tty = tty, x_param = param;
+
+ return (TTYSTATI (&x_tty, &x_param));
+}
diff --git a/sys/libc/ctype.c b/sys/libc/ctype.c
new file mode 100644
index 00000000..4d52648c
--- /dev/null
+++ b/sys/libc/ctype.c
@@ -0,0 +1,31 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_ctype
+#include <iraf.h>
+
+#ifdef vms
+globaldef vms_ctype_defs; /* [MACHDEP] */
+#endif
+
+/* Character class associations for the ctype.h macros.
+*/
+char u_ctype_[] = {
+ 0,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _S, _S, _S, _S, _S, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _S, _P, _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P, _P, _P,
+ _N, _N, _N, _N, _N, _N, _N, _N,
+ _N, _N, _P, _P, _P, _P, _P, _P,
+ _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _P, _P, _P, _P, _P,
+ _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _P, _P, _P, _P, _C
+};
diff --git a/sys/libc/cungetc.c b/sys/libc/cungetc.c
new file mode 100644
index 00000000..d1f416ef
--- /dev/null
+++ b/sys/libc/cungetc.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_UNGETC -- Push a character back into the input stream. Pushback is last
+** in first out, i.e., the last character pushed back is the first one
+** read by GETC. Characters (and strings) may be pushed back until the
+** FIO pushback buffer overflows.
+*/
+int
+c_ungetc (
+ XINT fd, /* file */
+ int ch /* char to be pushed */
+)
+{
+ XINT x_fd = fd;
+ XCHAR x_ch = ch;
+
+ iferr (UNGETC (&x_fd, &x_ch))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cungetl.c b/sys/libc/cungetl.c
new file mode 100644
index 00000000..5e0fa40c
--- /dev/null
+++ b/sys/libc/cungetl.c
@@ -0,0 +1,31 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+#define MAX_STRLEN SZ_COMMAND
+
+
+/* C_UNGETLINE -- Push a string back into the input stream. Pushback is last
+** in first out, i.e., the last string pushed back is the first one read by
+** GETC. Strings (and single characters) may be pushed back until the FIO
+** pushback buffer overflows.
+*/
+int
+c_ungetline (
+ XINT fd, /* file */
+ char *str /* string to be pushed back */
+)
+{
+ XINT x_fd = fd;
+ XCHAR spp_str[MAX_STRLEN];
+
+
+ iferr (UNGETLINE (&x_fd, c_strupk (str, spp_str, MAX_STRLEN)))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/cvfnbrk.c b/sys/libc/cvfnbrk.c
new file mode 100644
index 00000000..346b07fb
--- /dev/null
+++ b/sys/libc/cvfnbrk.c
@@ -0,0 +1,30 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_knames
+#include <iraf.h>
+
+
+/* C_VFNBRK -- Break a virtual filename (or host filename) into its component
+** parts, i.e., logical directory (ldir), root, and extension. No characters
+** are actually moved, rather, the offsets to the root and extn fields are
+** returned as output arguments.
+*/
+void
+c_vfnbrk (
+ char *vfn, /* virtual filename (or osfn) */
+ int *root, /* offset of root field. */
+ int *extn /* offset of extn field. */
+)
+{
+ XCHAR sppvfn[SZ_PATHNAME];
+ XINT x_root = *root, x_extn = extn;
+
+ ZFNBRK (c_strupk(vfn,sppvfn,SZ_PATHNAME), &x_root, &x_extn);
+
+ /* Make offsets zero-indexed. */
+ *root -= 1;
+ *extn -= 1;
+}
diff --git a/sys/libc/cwmsec.c b/sys/libc/cwmsec.c
new file mode 100644
index 00000000..246285a1
--- /dev/null
+++ b/sys/libc/cwmsec.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_knames
+#include <iraf.h>
+
+
+/* C_WMSEC -- Delay for so may milliseconds.
+*/
+void
+c_wmsec (
+ int msec /* milliseconds to delay */
+)
+{
+ XINT x_msec = msec;
+
+ ZWMSEC (&x_msec);
+}
diff --git a/sys/libc/cwrite.c b/sys/libc/cwrite.c
new file mode 100644
index 00000000..5ca7dab9
--- /dev/null
+++ b/sys/libc/cwrite.c
@@ -0,0 +1,51 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_fset
+#define import_stdio
+#define import_error
+#include <iraf.h>
+
+
+/* C_WRITE -- FIO write to a file. Write exactly nbytes bytes from the buffer
+** buf to the stream fd. If the actual file is a text file C chars are output
+** as XCHARs. If the actual file is a binary file no conversion is performed,
+** but an integral number of XCHARs are always written.
+*/
+int
+c_write (
+ XINT fd, /* FIO file descriptor */
+ char *buf, /* buffer containing data to be written */
+ int nbytes /* nbytes to be written */
+)
+{
+ XINT x_fd = fd;
+
+ if (c_fstati (fd, F_TYPE) == TEXT_FILE) {
+ register FILE *fp = FDTOFP(fd);
+ register char *ip;
+ register int n = nbytes;
+
+ for (ip=buf; --n >= 0; ip++)
+ putc (*ip, fp);
+ if (ferror (fp))
+ c_erract (EA_ERROR);
+
+ } else {
+ XINT x_nchars = (nbytes + sizeof(XCHAR)-1) / sizeof(XCHAR);
+ XCHAR *bp = (XCHAR *)buf;
+
+ /* Verify that the pointer coercion char->XCHAR->char is legal,
+ * i.e., that the char pointer is aligned to an XCHAR word
+ * boundary if required on this machine.
+ */
+ if (buf != (char *) bp)
+ return (ERR);
+ WRITE (&x_fd, bp, &x_nchars);
+ }
+
+ return (nbytes);
+}
diff --git a/sys/libc/cxgmes.c b/sys/libc/cxgmes.c
new file mode 100644
index 00000000..f8384923
--- /dev/null
+++ b/sys/libc/cxgmes.c
@@ -0,0 +1,29 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_knames
+#include <iraf.h>
+
+
+/* C_XGMES -- Fetch the machine dependent integer code and message string
+** for the most recent exception. The integer code XOK is returned if
+** no exception has occurred or if C_XGMES is called more than once after
+** a single exception.
+*/
+void
+c_xgmes (
+ int *oscode, /* os integer code of exception */
+ char *oserrmsg, /* os error message string */
+ int maxch
+)
+{
+ PKCHAR x_oserrmsg[SZ_LINE+1];
+ XINT x_oscode = *oscode, x_maxch = SZ_LINE;
+
+ ZXGMES (&x_oscode, x_oserrmsg, &x_maxch);
+ (void) strncpy (oserrmsg, (char *)x_oserrmsg, maxch);
+ *oscode = x_oscode;
+}
diff --git a/sys/libc/cxonerr.c b/sys/libc/cxonerr.c
new file mode 100644
index 00000000..2154851c
--- /dev/null
+++ b/sys/libc/cxonerr.c
@@ -0,0 +1,19 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_XONERR -- Call any error handler procedures posted with ONERROR.
+*/
+void
+c_xonerr (
+ int errcode
+)
+{
+ XINT x_errcode = errcode;
+
+ XONERR (&x_errcode);
+}
diff --git a/sys/libc/cxttysize.c b/sys/libc/cxttysize.c
new file mode 100644
index 00000000..81ac4541
--- /dev/null
+++ b/sys/libc/cxttysize.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* C_XTTYSIZE -- Get the terminal screen size, dynamically querying the
+** terminal for the screen size if the terminal has this capabability (e.g.,
+** a workstation window).
+*/
+void
+c_xttysize (
+ int *ncols, /* ncols (output) */
+ int *nlines /* nlines (output) */
+)
+{
+ XINT x_ncols, x_nlines;
+
+ XTTYSIZE (&x_ncols, &x_nlines);
+ *ncols = x_ncols;
+ *nlines = x_nlines;
+}
diff --git a/sys/libc/cxwhen.c b/sys/libc/cxwhen.c
new file mode 100644
index 00000000..b3523dfe
--- /dev/null
+++ b/sys/libc/cxwhen.c
@@ -0,0 +1,63 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_xnames
+#define import_knames
+#define import_libc
+#include <iraf.h>
+
+
+/* CXWHEN -- Post an exception handler. The exception handler procedure
+** is called when an exception occurs, unless the exception has been
+** disabled. If a user exception handler has not been posted and an
+** exception has not been disabled, a system default exception handler is
+** called when the exception occurs.
+**
+** Currently only four exceptions are recognized (import_xwhen):
+**
+** X_INT interrupt
+** X_ARITH arithmetic exception (e.g. divide by zero)
+** X_ACV access violation (e.g. illegal memory reference)
+** X_IPC write to IPC with no reader
+**
+** When an exception occurs the user supplied exception handler is called
+** with the following argument list:
+**
+** handler (&exception, &next_handler)
+**
+** The first argument is the code for the virtual exception calling the user
+** handler (the same handler may be posted for more than one exception).
+** The second argument is set by the user handler before exiting, and
+** must be either the ZLOCPR entry point address of the next exception
+** handler to be called or NULL, indicating that normal execution is to
+** resume.
+**
+** For portability reasons, only the virtual exceptions should be used to
+** post exception handlers. For good diagnostic messages when an exception
+** occurs it is desirable, however, to have a more precise description of
+** the actual host system exception which occurred. This may be obtained
+** by a call to C_XGMES.
+*/
+
+#define SZ_ERRMSG 64
+typedef int (*PFI)(); /* pointer to function returning int */
+
+
+/* C_XWHEN -- Post an exception handler for an exception, or disable the
+** exception (not all exceptions can be disabled).
+*/
+void
+c_xwhen (
+ int exception, /* code for virtual exception */
+ PFI new_handler, /* new exception handler */
+ PFI *old_handler /* old exception handler (output) */
+)
+{
+ XINT excode = exception;
+ XINT epa_new_handler = (XINT)new_handler;
+ XINT epa_old_handler;
+
+ XWHEN (&excode, &epa_new_handler, &epa_old_handler);
+ *old_handler = (PFI)epa_old_handler;
+}
diff --git a/sys/libc/eprintf.c b/sys/libc/eprintf.c
new file mode 100644
index 00000000..54cb5b8f
--- /dev/null
+++ b/sys/libc/eprintf.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_stdarg
+#include <iraf.h>
+
+
+/* EPRINTF -- Formatted print to the standard error output.
+*/
+void
+eprintf (char *format, ...)
+{
+ va_list argp;
+
+ extern void u_doprnt();
+
+
+ va_start (argp, format);
+ u_doprnt (format, &argp, stderr);
+ va_end (argp);
+ (void) fflush (stderr);
+}
diff --git a/sys/libc/fclose.c b/sys/libc/fclose.c
new file mode 100644
index 00000000..969c5d50
--- /dev/null
+++ b/sys/libc/fclose.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_xnames
+#include <iraf.h>
+
+/* FCLOSE -- Close a file opened with fopen.
+*/
+int
+fclose (
+ FILE *fp
+)
+{
+ XINT x_fd = fileno(fp);
+
+ iferr (CLOSE (&x_fd))
+ return (EOF);
+ else
+ return (OK);
+}
diff --git a/sys/libc/fdopen.c b/sys/libc/fdopen.c
new file mode 100644
index 00000000..c9e2bc9f
--- /dev/null
+++ b/sys/libc/fdopen.c
@@ -0,0 +1,76 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_fset
+#include <iraf.h>
+
+
+extern int c_fstati();
+
+
+/* FDOPEN -- Reopen a file for i/o with the STDIO package, after the file
+** as already been opened by FIO. It is an error if the access modes are
+** incompatible.
+*/
+FILE *
+fdopen (
+ XINT fd, /* FIO file descriptor */
+ char *mode /* STDIO access mode */
+)
+{
+ register int fio_mode = c_fstati (fd, F_MODE);
+ register int fio_type = c_fstati (fd, F_TYPE);
+
+
+ /* Verify file access mode. No mode checking is performed for the
+ * special file types.
+ */
+ if (fio_type == TEXT_FILE || fio_type == BINARY_FILE)
+ switch (mode[0]) {
+ case 'r':
+ if (fio_mode != READ_ONLY && fio_mode != READ_WRITE)
+ return (NULL);
+ break;
+
+ case 'w':
+ switch (fio_mode) {
+ case NEW_FILE:
+ case READ_WRITE:
+ case WRITE_ONLY:
+ break;
+ default:
+ return (NULL);
+ }
+ break;
+
+ case 'a':
+ if (fio_mode != APPEND && fio_mode != NEW_FILE)
+ return (NULL);
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ /* Verify file type. No checking is performed if no type is given.
+ */
+ switch (mode[1]) {
+ case EOS:
+ break;
+ case 't':
+ if (fio_type != TEXT_FILE)
+ return (NULL);
+ break;
+ case 'b':
+ if (fio_type != BINARY_FILE)
+ return (NULL);
+ break;
+ default:
+ return (NULL);
+ }
+
+ return (FDTOFP(fd));
+}
diff --git a/sys/libc/fflush.c b/sys/libc/fflush.c
new file mode 100644
index 00000000..14a2356a
--- /dev/null
+++ b/sys/libc/fflush.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_xnames
+#include <iraf.h>
+
+
+/* FFLUSH -- Flush the output file.
+*/
+int
+fflush (
+ FILE *fp
+)
+{
+ XINT x_fd = fileno(fp);
+
+ iferr (FLUSH (&x_fd))
+ return (EOF);
+ else
+ return (OK);
+}
diff --git a/sys/libc/fgetc.c b/sys/libc/fgetc.c
new file mode 100644
index 00000000..155a1111
--- /dev/null
+++ b/sys/libc/fgetc.c
@@ -0,0 +1,19 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FGETC -- Get a character from the input file. Offered as a functionally
+** equivalent alternative to the macro GETC.
+*/
+int
+fgetc (
+ FILE *fp
+)
+{
+ return (getc (fp));
+}
diff --git a/sys/libc/fgets.c b/sys/libc/fgets.c
new file mode 100644
index 00000000..45c228c6
--- /dev/null
+++ b/sys/libc/fgets.c
@@ -0,0 +1,43 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FGETS -- Return a newline delimited string in the user buffer. If the
+** buffer fills before newline is seen the string will not be newline
+** delimited.
+*/
+char *
+fgets (
+ char *buf, /* user supplied output buffer */
+ int maxch, /* max chars out (incl EOS) */
+ FILE *fp /* input file */
+)
+{
+ register int ch = 0, lastch = 0, n = maxch - 1;
+ register char *op = buf;
+
+ while (--n >= 0 && (ch = getc (fp)) >= 0) {
+ lastch = ch;
+ if (ch == '\r') /* handle DOS-style CR-NL */
+ continue;
+ *op++ = ch;
+ if (ch == '\n')
+ break;
+ }
+
+ if (ch == EOF && op == buf)
+ return ((char *) NULL);
+ else {
+#ifdef ADD_NEWLINE
+ if (lastch != '\n') /* handle missing NL at EOF */
+ *op++ = '\n';
+#endif
+ *op = EOS;
+ return (buf);
+ }
+}
diff --git a/sys/libc/fopen.c b/sys/libc/fopen.c
new file mode 100644
index 00000000..f9fe16ae
--- /dev/null
+++ b/sys/libc/fopen.c
@@ -0,0 +1,61 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#include <iraf.h>
+
+
+/* FOPEN -- Open a file with the given access mode and file type. The file type
+** (text or binary) is specified with an optional, non UNIX standard character
+** "t" or "b" in the modestring. The default is text file if no type is given.
+*/
+FILE *
+fopen (
+ char *fname, /* vfn of file */
+ char *modestr /* access mode [and type] */
+)
+{
+ XINT x_filetype, x_filemode;
+ int fd;
+
+
+ /* Get file type.
+ */
+ switch (modestr[1]) {
+ case 't':
+ case EOS:
+ x_filetype = TEXT_FILE;
+ break;
+ case 'b':
+ x_filetype = BINARY_FILE;
+ break;
+ default:
+ return (NULL);
+ }
+
+ /* Determine file access mode.
+ */
+ switch (modestr[0]) {
+ case 'r':
+ x_filemode = READ_ONLY;
+ break;
+ case 'w':
+ x_filemode = NEW_FILE;
+ break;
+ case 'a':
+ x_filemode = APPEND;
+ break;
+ default:
+ return (NULL);
+ }
+
+ /* Open file.
+ */
+ iferr (fd = OPEN (c_sppstr(fname), &x_filemode, &x_filetype))
+ return (NULL);
+ else
+ return (FDTOFP(fd));
+}
diff --git a/sys/libc/fputc.c b/sys/libc/fputc.c
new file mode 100644
index 00000000..7d815206
--- /dev/null
+++ b/sys/libc/fputc.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FPUTC -- Put a character to the output file. Offered as a functionally
+** equivalent alternative to the macro PUTC.
+*/
+int
+fputc (
+ char ch,
+ FILE *fp
+)
+{
+ return (putc (ch, fp));
+}
diff --git a/sys/libc/fputs.c b/sys/libc/fputs.c
new file mode 100644
index 00000000..76dca159
--- /dev/null
+++ b/sys/libc/fputs.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FPUTS -- Put a null terminated string to the output file.
+*/
+void
+fputs (
+ char *str, /* input string */
+ FILE *fp /* output file */
+)
+{
+ register char *ip;
+
+ for (ip=str; *ip != EOS; ip++)
+ putc (*ip, fp);
+}
diff --git a/sys/libc/fread.c b/sys/libc/fread.c
new file mode 100644
index 00000000..28f1376c
--- /dev/null
+++ b/sys/libc/fread.c
@@ -0,0 +1,55 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FREAD -- Read a binary block of data from the input file. To be consistent
+** with UNIX we must read until nelem chars have been accumulated or until
+** EOF is seen. Hence, if reading from a record structured device such as a
+** terminal, the read will not be terminated by end of record (newline).
+** If the number of bytes (C chars) requested does not fill an integral number
+** of XCHARS additional bytes will be read to fill out the last XCHAR.
+*/
+int
+fread (
+ char *bp, /* output buffer */
+ int szelem, /* nbytes per element */
+ int nelem, /* nelems to read */
+ FILE *fp
+)
+{
+ register int nread, n;
+ int nbytes;
+ XINT fd = fileno (fp);
+ char *op = bp;
+
+
+ fd = fileno (fp);
+ nbytes = nelem * szelem;
+ nread = 0;
+
+ if (fp == stdin)
+ (void) fflush (stdout);
+ if (szelem <= 0)
+ return (0);
+
+ for (op = bp; nread < nbytes; op += n) {
+ iferr (n = c_read (fd, op, nbytes-nread)) {
+ fp->_fflags |= _FERR;
+ break;
+ } else if (n == EOF) {
+ fp->_fflags |= _FEOF;
+ break;
+ } else
+ nread += n;
+ }
+
+ if (fp->_fflags & (_FEOF|_FERR))
+ return (nread ? nread / szelem : 0);
+ else
+ return (nread / szelem);
+}
diff --git a/sys/libc/freadline.c b/sys/libc/freadline.c
new file mode 100644
index 00000000..b335ee20
--- /dev/null
+++ b/sys/libc/freadline.c
@@ -0,0 +1,34 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FREADLINE -- Get a line from a user with editing. This is a libc
+ * interface to the host readline() interface. The host readline()
+ * returns a buffer allocated which we free here, what's returned to
+ * the caller is a static buffer containing the input string.
+ */
+char *
+freadline (
+ char *prompt /* user supplied output buffer */
+)
+{
+ char *cmd = (char *) NULL;
+ static char line[SZ_LINE];
+ char *readline (char *prompt);
+
+
+ memset (line, 0, SZ_LINE);
+ if ((cmd = readline (prompt)) == (char *) NULL) {
+ return ((char *) NULL);
+ } else {
+ strcpy (line, cmd); /* save to static buffer */
+ zfree_ ((void *) cmd); /* free readline() buffer */
+ }
+
+ return ((char *) line);
+}
diff --git a/sys/libc/free.c b/sys/libc/free.c
new file mode 100644
index 00000000..4edd18c0
--- /dev/null
+++ b/sys/libc/free.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* FREE -- Free a block of storage previously allocated by malloc, calloc,
+** or realloc.
+*/
+void
+free (
+ char *buf
+)
+{
+ XINT x_ptr, x_dtype = TY_CHAR;
+
+ x_ptr = Memcptr (buf);
+ MFREE (&x_ptr, &x_dtype);
+}
diff --git a/sys/libc/freopen.c b/sys/libc/freopen.c
new file mode 100644
index 00000000..4d4ed997
--- /dev/null
+++ b/sys/libc/freopen.c
@@ -0,0 +1,56 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FREOPEN -- Close a stream and reopen it upon the named file. This is
+** commonly used to redirect one of the standard streams stdin, stdout,
+** or stderr to a named file.
+*/
+FILE *
+freopen (
+ char *fname, /* vfn of file to be opened */
+ char *modestr, /* access mode [and type] */
+ FILE *fp /* stream to be reopened */
+)
+{
+ register XINT fd = fileno(fp);
+ register int status, filetype;
+
+
+ /* Determine the file type of the file to be opened. This is given
+ * by an optional second character in the mode string. Default is
+ * text file if absent.
+ */
+ switch (modestr[1]) {
+ case 't':
+ case EOS:
+ filetype = TEXT_FILE;
+ break;
+ case 'b':
+ filetype = BINARY_FILE;
+ break;
+ default:
+ return (NULL);
+ }
+
+ switch (modestr[0]) {
+ case 'r':
+ status = c_fredir (fd, fname, READ_ONLY, filetype);
+ break;
+ case 'w':
+ status = c_fredir (fd, fname, NEW_FILE, filetype);
+ break;
+ case 'a':
+ status = c_fredir (fd, fname, APPEND, filetype);
+ break;
+ default:
+ return (NULL);
+ }
+
+ return (status == ERR ? NULL : fp);
+}
diff --git a/sys/libc/fseek.c b/sys/libc/fseek.c
new file mode 100644
index 00000000..fa32466c
--- /dev/null
+++ b/sys/libc/fseek.c
@@ -0,0 +1,93 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_fset
+#include <iraf.h>
+
+
+/* FSEEK -- Seek on a file opened under stdio. The seek functions do not
+** completely emulate the UNIX seek functions. The following restrictions
+** apply:
+**
+** - It is only permissible to seek to the beginning of a line if the
+** actual file is a text file. The seek offset must have been
+** obtained by a prior call to FTELL, which returns the seek offset
+** of the next line to be read or written. Seek offsets cannot be
+** manufactured, e.g., as physical char offsets in the file, as is
+** the case for binary files. These restrictions apply because text
+** files are record structured on many systems, rather than simple
+** byte stream files as in UNIX.
+**
+** - It is permissible to randomly seek about on a binary file, but
+** seeks must be aligned on XCHAR word boundaries in the file. This
+** can be guaranteed by structuring the application so that it always
+** reads and writes binary data records that are an integral number
+** of integers in size. If this is done the program is portable to
+** any IRAF machine as well as to UNIX. Seek offsets are specified
+** in units of bytes and are zero-indexed, as in C.
+*/
+int
+fseek (
+ FILE *fp, /* operand file */
+ long offset, /* offset in file */
+ int mode /* 0=absolute, 1=relative, 2=from EOF */
+)
+{
+ register XINT fd = fileno(fp);
+ int text_file, stat;
+ long c_note();
+
+
+ text_file = (c_fstati (fd, F_TYPE) == TEXT_FILE);
+ fp->_fflags &= ~_FEOF;
+
+ if (text_file) {
+ switch (mode) {
+ case 0:
+ if (offset == 0L)
+ stat = c_seek (fd, BOFL);
+ else
+ stat = c_seek (fd, offset);
+ break;
+ case 2:
+ if (offset == 0L) {
+ stat = c_seek (fd, EOFL);
+ fp->_fflags |= _FEOF;
+ } else
+ stat = ERR;
+ break;
+ default:
+ stat = ERR;
+ break;
+ }
+
+ } else {
+ /* Random seeks on (non-streaming) binary files are permitted,
+ * but the seek must be to an XCHAR offset. This is checked
+ * by c_seek, which takes a zero-indexed byte offset as argument.
+ */
+ switch (mode) {
+ case 0:
+ stat = c_seek (fd, offset);
+ break;
+ case 1:
+ stat = c_seek (fd, c_note(fd) + offset);
+ break;
+ case 2:
+ if ((stat = c_seek (fd, EOFL)) != ERR) {
+ if (offset == 0L)
+ fp->_fflags |= _FEOF;
+ else
+ stat = c_seek (fd, c_note(fd) - offset);
+ }
+ break;
+ default:
+ stat = ERR;
+ }
+ }
+
+ return (stat);
+}
diff --git a/sys/libc/ftell.c b/sys/libc/ftell.c
new file mode 100644
index 00000000..be373a6d
--- /dev/null
+++ b/sys/libc/ftell.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FTELL -- Get the FSEEK offset of the current position in a file, i.e.,
+** the file offset at which the next read or write will occur. For a text
+** file this is a magic number, for a binary file it is the zero-indexed
+** offset in bytes from the beginning of the file.
+*/
+long
+ftell (
+ FILE *fp /* operand file */
+)
+{
+ return (c_note (fileno(fp)));
+}
diff --git a/sys/libc/fwrite.c b/sys/libc/fwrite.c
new file mode 100644
index 00000000..cb9e06e6
--- /dev/null
+++ b/sys/libc/fwrite.c
@@ -0,0 +1,36 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* FWRITE -- Write a binary block of data to the output file. If the number
+** of bytes (C chars) specified does not fill an integral number of XCHARS
+** additional bytes will be written to fill out the last XCHAR. The actual
+** number of elements written is returned as the function value.
+*/
+int
+fwrite (
+ char *bp, /* output buffer */
+ int szelem, /* nbytes per element */
+ int nelem, /* nelems to read */
+ FILE *fp
+)
+{
+ register int stat;
+ XINT fd = fileno (fp);
+
+
+ if (szelem) {
+ stat = c_write (fd, bp, nelem * szelem);
+ if (stat == ERR) {
+ fp->_fflags |= _FERR;
+ return (0);
+ } else
+ return (stat / szelem);
+ } else
+ return (0);
+}
diff --git a/sys/libc/gets.c b/sys/libc/gets.c
new file mode 100644
index 00000000..309efa11
--- /dev/null
+++ b/sys/libc/gets.c
@@ -0,0 +1,34 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* GETS -- Read a newline terminated sequence from the standard input and
+** return the resultant string minus the newline to the user.
+*/
+char *
+gets (
+ char *buf /* user supplied output buffer */
+)
+{
+ register FILE *fp = stdin;
+ register char *op = buf;
+ register int ch;
+
+
+ while ((ch = getc (fp)) != EOF) {
+ if (ch == '\n')
+ break;
+ *op++ = ch;
+ }
+ *op = EOS;
+
+ if (ch == EOF && op == buf)
+ return ((char *) NULL);
+ else
+ return (buf);
+}
diff --git a/sys/libc/getw.c b/sys/libc/getw.c
new file mode 100644
index 00000000..c0dd0cf9
--- /dev/null
+++ b/sys/libc/getw.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* GETW -- Get a word (integer) from the input stream. When used in conjunction
+** with PUTW this permits storage and retrieval of binary words in any file,
+** albeit somewhat inefficiently.
+*/
+int
+getw (
+ FILE *fp /* input file */
+)
+{
+ int word;
+ register char *op = (char *)&word;
+ register int n = sizeof (int);
+
+
+ while (--n >= 0)
+ *op++ = getc (fp);
+
+ return ((fp->_fflags & (_FEOF|_FERR)) ? EOF : word);
+}
diff --git a/sys/libc/index.c b/sys/libc/index.c
new file mode 100644
index 00000000..fa7a4917
--- /dev/null
+++ b/sys/libc/index.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#define import_spp
+#include <iraf.h>
+
+
+/* INDEX -- Search string STR for char CH, returning a pointer to the first
+** occurrence of CH in STR or NULL.
+*/
+char *
+index (
+ char *str, /* string to be searched */
+ int ch /* character we are searching for */
+)
+{
+ register char *ip = str;
+
+ do {
+ if (*ip == ch)
+ return (ip);
+ } while (*ip++);
+
+ return ((char *) NULL);
+}
diff --git a/sys/libc/isatty.c b/sys/libc/isatty.c
new file mode 100644
index 00000000..b625299a
--- /dev/null
+++ b/sys/libc/isatty.c
@@ -0,0 +1,20 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* ISATTY -- Test if the given file is a terminal.
+*/
+int
+isatty (
+ XINT fd
+)
+{
+ XINT x_fd = fd;
+
+ return (XISATTY (&x_fd));
+}
diff --git a/sys/libc/libc_proto.h b/sys/libc/libc_proto.h
new file mode 100644
index 00000000..52590a8e
--- /dev/null
+++ b/sys/libc/libc_proto.h
@@ -0,0 +1,326 @@
+/* atof.c */
+extern double u_atof(char *str);
+/* atoi.c */
+extern int u_atoi(char *str);
+/* atol.c */
+extern long u_atol(char *str);
+/* caccess.c */
+extern int c_access(char *fname, int mode, int type);
+/* callocate.c */
+extern int c_allocate(char *device);
+extern int c_deallocate(char *device, int u_rewind);
+extern void c_devstatus(char *device, int out);
+extern int c_devowner(char *device, char *owner, int maxch);
+/* calloc.c */
+extern char *u_calloc(unsigned int nelems, unsigned int elsize);
+/* cclktime.c */
+extern long c_clktime(long reftime);
+extern long c_cputime(long reftime);
+/* cclose.c */
+extern int c_close(int fd);
+/* ccnvdate.c */
+extern char *c_cnvdate(long clktime, char *outstr, int maxch);
+/* ccnvtime.c */
+extern char *c_cnvtime(long clktime, char *outstr, int maxch);
+/* cdelete.c */
+extern int c_delete(char *fname);
+/* cenvget.c */
+extern char *u_envget(char *var);
+extern int c_envgs(char *var, char *outstr, int maxch);
+extern int c_envfind(char *var, char *outstr, int maxch);
+extern int c_envgb(char *var);
+extern int c_envgi(char *var);
+extern void c_envputs(char *var, char *value);
+extern void c_envreset(char *var, char *value);
+/* cenvlist.c */
+extern void c_envlist(int fd, char *prefix, int show_redefs);
+/* cenvmark.c */
+extern void c_envmark(int *envp);
+extern int c_envfree(int envp, int userfcn);
+extern int c_prenvfree(int pid, int envp);
+/* cenvscan.c */
+extern int c_envscan(char *input_source);
+/* cerract.c */
+extern void c_erract(int action);
+/* cerrcode.c */
+extern int c_errcode(void);
+/* cerrget.c */
+extern int c_errget(char *outstr, int maxch);
+/* cerror.c */
+extern void c_error(int errcode, char *errmsg);
+/* cfchdir.c */
+extern int c_fchdir(char *newdir);
+/* cfilbuf.c */
+extern int c_filbuf(struct _iobuf *fp);
+/* cfinfo.c */
+extern int c_finfo(char *fname, struct _finfo *fi);
+/* cflsbuf.c */
+extern int c_flsbuf(unsigned int ch, struct _iobuf *fp);
+/* cflush.c */
+extern void c_flush(int fd);
+/* cfmapfn.c */
+extern int c_fmapfn(char *vfn, char *osfn, int maxch);
+/* cfmkdir.c */
+extern int c_fmkdir(char *newdir);
+/* cfnextn.c */
+extern int c_fnextn(char *vfn, char *extn, int maxch);
+/* cfnldir.c */
+extern int c_fnldir(char *vfn, char *ldir, int maxch);
+/* cfnroot.c */
+extern int c_fnroot(char *vfn, char *root, int maxch);
+/* cfpath.c */
+extern int c_fpathname(char *vfn, char *osfn, int maxch);
+/* cfredir.c */
+extern int c_fredir(int fd, char *fname, int mode, int type);
+/* cfseti.c */
+extern void c_fseti(int fd, int param, int value);
+/* cfstati.c */
+extern int c_fstati(int fd, int param);
+/* cgetpid.c */
+extern int c_getpid(void);
+/* cgetuid.c */
+extern char *c_getuid(char *outstr, int maxch);
+/* cgflush.c */
+extern void c_gflush(int stream);
+/* cimaccess.c */
+extern int c_imaccess(char *imname, int mode);
+/* cimdrcur.c */
+extern int c_imdrcur(char *device, float *x, float *y, int *wcs, int *key, char *strval, int maxch, int d_wcs, int pause);
+/* ckimapc.c */
+extern int c_kimapchan(int chan, char *nodename, int maxch);
+/* clexnum.c */
+extern int c_lexnum(char *str, int *toklen);
+/* cmktemp.c */
+extern int c_mktemp(char *root, char *temp_filename, int maxch);
+/* cndopen.c */
+extern int c_ndopen(char *fname, int mode);
+/* cnote.c */
+extern long c_note(int fd);
+/* copen.c */
+extern int c_open(char *fname, int mode, int type);
+/* coscmd.c */
+extern int c_oscmd(char *cmd, char *infile, char *outfile, char *errfile);
+/* cpoll.c */
+extern int c_poll_open(void);
+extern int c_poll(int fds, int nfds, int timeout);
+extern void c_poll_close(int fds);
+extern void c_poll_zero(int fds);
+extern void c_poll_set(int fds, int fd, int type);
+extern void c_poll_clear(int fds, int fd, int type);
+extern int c_poll_test(int fds, int fd, int type);
+extern int c_poll_get_nfds(int fds);
+extern void c_poll_print(int fds);
+/* cprcon.c */
+extern unsigned int c_propen(char *process, int *in, int *out);
+extern int c_prclose(unsigned int pid);
+extern int c_prstati(int pid, int param);
+extern int c_prsignal(unsigned pid, int signal);
+extern int c_prredir(unsigned pid, int stream, int new_fd);
+extern int c_prchdir(int pid, char *newdir);
+extern int c_prenvset(int pid, char *envvar, char *value);
+/* cprdet.c */
+extern unsigned int c_propdpr(char *process, char *bkgfile, char *bkgmsg);
+extern int c_prcldpr(unsigned job);
+extern int c_prdone(unsigned job);
+extern int c_prkill(unsigned job);
+/* cprintf.c */
+extern int c_printf(char *format);
+extern int c_fprintf(int fd, char *format);
+extern void c_pargb(int ival);
+extern void c_pargc(int ival);
+extern void c_pargs(short sval);
+extern void c_pargi(int ival);
+extern void c_pargl(long lval);
+extern void c_pargr(float rval);
+extern void c_pargd(double dval);
+extern void c_pargstr(char *strval);
+/* crcursor.c */
+extern int c_rcursor(int fd, char *outstr, int maxch);
+/* crdukey.c */
+extern int c_rdukey(char *obuf, int maxch);
+/* cread.c */
+extern int c_read(int fd, char *buf, int maxbytes);
+/* crename.c */
+extern int c_rename(char *old_fname, char *new_fname);
+/* creopen.c */
+extern int c_reopen(int fd, int mode);
+/* csalloc.c */
+extern char *c_salloc(unsigned nbytes);
+extern void c_smark(int *sp);
+extern void c_sfree(int sp);
+/* cseek.c */
+extern int c_seek(int fd, long offset);
+/* csppstr.c */
+extern short *c_sppstr(char *str);
+/* cstropen.c */
+extern int c_stropen(short *obuf, int maxch, int mode);
+/* cstrpak.c */
+extern char *c_strpak(short *sppstr, char *cstr, int maxch);
+/* cstrupk.c */
+extern short *c_strupk(char *str, short *outstr, int maxch);
+/* ctsleep.c */
+extern void c_tsleep(int nseconds);
+/* cttset.c */
+extern void c_sttyco(char *args, int ttin, int ttout, int outfd);
+extern void c_ttseti(int fd, int param, int value);
+extern int c_ttstati(int fd, int param);
+extern void c_ttsets(int fd, int param, char *value);
+extern int c_ttstats(int fd, int param, char *outstr, int maxch);
+/* cttycdes.c */
+extern void c_ttycdes(XINT tty);
+/* cttyclear.c */
+extern void c_ttycr(int fd, XINT tty);
+/* cttyclln.c */
+extern void c_ttycn(int fd, XINT tty);
+/* cttyctrl.c */
+extern int c_ttyctrl(int fd, XINT tty, char *cap, int afflncnt);
+/* cttygetb.c */
+extern int c_ttygb(XINT tty, char *cap);
+/* cttygeti.c */
+extern XINT c_ttygi(XINT tty, char *cap);
+/* cttygetr.c */
+extern float c_ttygr(XINT tty, char *cap);
+/* cttygets.c */
+extern int c_ttygs(XINT tty, char *cap, char *outstr, int maxch);
+/* cttygoto.c */
+extern void c_ttygoto(int fd, XINT tty, int col, int line);
+/* cttyinit.c */
+extern void c_ttyinit(int fd, XINT tty);
+/* cttyodes.c */
+extern XINT c_ttyodes(char *ttyname);
+/* cttyputl.c */
+extern void c_ttype(int fd, XINT tty, char *line, int map_cc);
+/* cttyputs.c */
+extern int c_ttyps(int fd, XINT tty, char *cap, int afflncnt);
+/* cttyseti.c */
+extern void c_ttyseti(XINT tty, int param, int value);
+/* cttyso.c */
+extern void c_ttyso(int fd, XINT tty, int onoff);
+/* cttystati.c */
+extern XINT c_ttystati(XINT tty, int param);
+/* ctype.c */
+/* cungetc.c */
+extern int c_ungec(int fd, int ch);
+/* cungetl.c */
+extern int c_ungetline(int fd, char *str);
+/* cvfnbrk.c */
+extern void c_vfnbrk(char *vfn, int *root, int *extn);
+/* cwmsec.c */
+extern void c_wmsec(int msec);
+/* cwrite.c */
+extern int c_write(int fd, char *buf, int nbytes);
+/* cxgmes.c */
+extern void c_xgmes(int *oscode, char *oserrmsg, int maxch);
+/* cxonerr.c */
+extern void c_xonerr(int errcode);
+/* cxttysize.c */
+extern void c_xttysize(int *ncols, int *nlines);
+/* cxwhen.c
+extern void c_xwhen(int exception, PFI new_handler, PFI *old_handler);
+ */
+/* eprintf.c */
+extern void u_eprintf(char *format, ...);
+/* fclose.c */
+extern int u_fclose(struct _iobuf *fp);
+/* fdopen.c */
+extern struct _iobuf *u_fdopen(int fd, char *mode);
+/* fflush.c */
+extern int u_fflush(struct _iobuf *fp);
+/* fgetc.c */
+extern int u_fgetc(struct _iobuf *fp);
+/* fgets.c */
+extern char *u_fgets(char *buf, int maxch, struct _iobuf *fp);
+/* fopen.c */
+extern struct _iobuf *u_fopen(char *fname, char *modestr);
+/* fputc.c */
+extern int u_fputc(char ch, struct _iobuf *fp);
+/* fputs.c */
+extern void u_fputs(char *str, struct _iobuf *fp);
+/* fread.c */
+extern int u_fread(char *bp, int szelem, int nelem, struct _iobuf *fp);
+/* free.c */
+extern void u_free(char *buf);
+/* freopen.c */
+extern struct _iobuf *u_freopen(char *fname, char *modestr, struct _iobuf *fp);
+/* fseek.c */
+extern int u_fseek(struct _iobuf *fp, long offset, int mode);
+/* ftell.c */
+extern long u_ftell(struct _iobuf *fp);
+/* fwrite.c */
+extern int u_fwrite(char *bp, int szelem, int nelem, struct _iobuf *fp);
+/* gets.c */
+extern char *u_gets(char *buf);
+/* getw.c */
+extern int u_getw(struct _iobuf *fp);
+/* index.c */
+extern char *u_index(char *str, int ch);
+/* isatty.c */
+extern int u_isatty(int fd);
+/* malloc.c */
+extern char *u_malloc(unsigned nbytes);
+/* mktemp.c */
+extern char *u_mktemp(char *template);
+/* perror.c */
+extern void u_perror(char *prefix);
+/* printf.c */
+extern void u_printf(char *format, ...);
+extern void u_fprintf(struct _iobuf *fp, char *format, ...);
+/*
+extern void u_doprnt(char *format, va_list *argp, struct _iobuf *fp);
+extern void u_doarg(struct _iobuf *fp, short *formspec, va_list **argp, int prec[], int varprec, int dtype);
+*/
+/* puts.c */
+extern int u_puts(char *str);
+/* putw.c */
+extern int u_putw(int word, struct _iobuf *fp);
+/* qsort.c */
+extern void u_qsort(char *base, int n, int size, int (*compar)(void));
+/* realloc.c */
+extern char *u_realloc(char *buf, unsigned newsize);
+/* rewind.c */
+extern long u_rewind(struct _iobuf *fp);
+/* rindex.c */
+extern char *u_rindex(char *str, int ch);
+/* scanf.c */
+extern int u_scanf(char *format, ...);
+extern int u_fscanf(struct _iobuf *fp, char *format, ...);
+extern int u_sscanf(char *str, char *format, ...);
+/* setbuf.c */
+extern void u_setbuf(struct _iobuf *fp, char *buf);
+extern void u_setfbf(struct _iobuf *fp, char *buf, int size);
+extern void u_setlinebuf(struct _iobuf *fp);
+/* spf.c */
+extern int spf_open(char *buf, int maxch);
+extern void spf_close(int fd);
+/* sprintf.c */
+extern char *u_sprintf(char *str, char *format, ...);
+/* stgio.c */
+extern int c_stggetline(int fd, char *buf, int maxch);
+extern int c_stgputline(int fd, char *buf);
+/* strcat.c */
+extern char *u_strcat(char *s1, char *s2);
+/* strcmp.c */
+extern int u_strcmp(char *s1, char *s2);
+/* strdup.c */
+extern char *u_strdup(char *str);
+/* strcpy.c */
+extern char *u_strcpy(char *s1, char *s2);
+/* strlen.c */
+extern int u_strlen(char *s);
+/* strncat.c */
+extern char *u_strnt(char *s1, char *s2, int n);
+/* strncmp.c */
+extern int u_strnp(char *s1, char *s2, int n);
+/* strncpy.c */
+extern char *u_strny(char *s1, char *s2, int n);
+/* system.c */
+extern int u_system(char *cmd);
+/* ungetc.c */
+extern int u_ungetc(int ch, struct _iobuf *fp);
+/* zztest.c */
+extern int thello_(void);
+extern int tprint_(void);
+extern int tcopy_(void);
+extern int tscan_(void);
+extern int onint(int *code, int *old_handler);
+extern int tgettk_(void);
diff --git a/sys/libc/malloc.c b/sys/libc/malloc.c
new file mode 100644
index 00000000..af5506cf
--- /dev/null
+++ b/sys/libc/malloc.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* MALLOC -- Allocate an uninitialized block of memory at least nbytes in size.
+*/
+char *
+malloc (
+ unsigned nbytes
+)
+{
+ XINT x_nchars = (nbytes + sizeof(XCHAR)-1) / sizeof(XCHAR);
+ XINT x_ptr, x_dtype = TY_CHAR;
+
+ iferr (MALLOC (&x_ptr, &x_nchars, &x_dtype))
+ return (NULL);
+ else
+ return ((char *)&Memc[x_ptr]);
+}
diff --git a/sys/libc/mathf.f b/sys/libc/mathf.f
new file mode 100644
index 00000000..89279451
--- /dev/null
+++ b/sys/libc/mathf.f
@@ -0,0 +1,75 @@
+c
+c MATH -- C callable math functions. This is the only portable way
+c to access the Fortran intrinsic functions from C. As a local
+c optimization it is possible to add defines to map these external
+c names onto the local Fortran library functions, but since C is not
+c generally used intensively for computations and all floating point
+c is done in double precision anyway, it is probably not worth it.
+c
+
+ integer function xnint (x)
+ double precision x
+ xnint = nint (x)
+ end
+
+ double precision function xexp (x)
+ double precision x
+ xexp = exp(x)
+ end
+
+ double precision function xlog (x)
+ double precision x
+ xlog = log(x)
+ end
+
+ double precision function xlog10 (x)
+ double precision x
+ xlog10 = log10(x)
+ end
+
+ double precision function xpow (x, y)
+ double precision x
+ double precision y
+ xpow = x ** y
+ end
+
+ double precision function xsqrt (x)
+ double precision x
+ xsqrt = sqrt(x)
+ end
+
+ double precision function xsin (x)
+ double precision x
+ xsin = sin(x)
+ end
+
+ double precision function xcos (x)
+ double precision x
+ xcos = cos(x)
+ end
+
+ double precision function xtan (x)
+ double precision x
+ xtan = tan(x)
+ end
+
+ double precision function xasin (x)
+ double precision x
+ xasin = asin(x)
+ end
+
+ double precision function xacos (x)
+ double precision x
+ xacos = acos(x)
+ end
+
+ double precision function xatan (x)
+ double precision x
+ xatan = atan(x)
+ end
+
+ double precision function xatan2 (x, y)
+ double precision x
+ double precision y
+ xatan2 = atan2(x,y)
+ end
diff --git a/sys/libc/mkpkg b/sys/libc/mkpkg
new file mode 100644
index 00000000..74349a1a
--- /dev/null
+++ b/sys/libc/mkpkg
@@ -0,0 +1,168 @@
+# Mkpkg for the IRAF runtime C library. There is an additional dependence
+# on the global C include <iraf.h> which is not shown. Those files which
+# reference <libc/stdio.h> have an implicit dependence on the VOS include
+# files <fio.h> and <fio.com>, since the LIBC stdio routines reference the
+# FIO internal data structures directly.
+
+$checkout libc.a lib$
+$update libc.a
+$checkin libc.a lib$
+$exit
+
+libc.a:
+ $set XFLAGS = "$(XFLAGS) -/Wall"
+
+ atof.c <libc/ctype.h> <libc/libc.h> <libc/spp.h>\
+ <libc/xnames.h>
+ atoi.c <libc/ctype.h> <libc/libc.h> <libc/spp.h>
+ atol.c <libc/ctype.h> <libc/libc.h> <libc/spp.h>
+ caccess.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ calloc.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ callocate.c <libc/spp.h> <libc/libc.h> <libc/xnames.h>
+ cclktime.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cclose.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ ccnvdate.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ ccnvtime.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cdelete.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cenvget.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cenvlist.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cenvmark.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cenvscan.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cerract.c <libc/error.h> <libc/libc.h> <libc/spp.h>\
+ <libc/xnames.h>
+ cerrcode.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cerrget.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cerror.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cfchdir.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cfilbuf.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ cfinfo.c <libc/libc.h> <libc/xnames.h> <libc/finfo.h>\
+ <libc/spp.h>
+ cflsbuf.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ cflush.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cfmapfn.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cfmkdir.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cfnextn.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cfnldir.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cfnroot.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cfpath.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cfredir.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cfseti.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cfstati.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cgetpid.c <libc/libc.h> <libc/xnames.h>
+ cgetuid.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cgflush.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cimaccess.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cimdrcur.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ ckimapc.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ clexnum.c <libc/ctype.h> <libc/lexnum.h> <libc/spp.h>\
+ <libc/xnames.h> <libc/libc.h>
+ cmktemp.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cnote.c <libc/libc.h> <libc/xnames.h> <libc/fset.h> <libc/spp.h>
+ copen.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ coscmd.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cndopen.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cpoll.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>\
+ <libc/fpoll.h>
+ cprcon.c <libc/libc.h> <libc/prstat.h> <libc/stdio.h>\
+ <libc/xnames.h> <libc/spp.h>
+ cprdet.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cprintf.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ crcursor.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ crdukey.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cread.c <libc/libc.h> <libc/xnames.h> <libc/error.h>\
+ <libc/fset.h> <libc/spp.h> <libc/stdio.h>
+ crename.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ creopen.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ csalloc.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cseek.c <libc/libc.h> <libc/xnames.h> <libc/fset.h> <libc/spp.h>
+ csppstr.c <libc/libc.h> <libc/spp.h>
+ cstropen.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ cstrpak.c <libc/libc.h> <libc/spp.h>
+ cstrupk.c <libc/libc.h> <libc/spp.h>
+ ctsleep.c <libc/libc.h> <libc/xnames.h>
+ cttset.c <libc/libc.h> <libc/xnames.h>
+ cttycdes.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyclear.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyclln.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyctrl.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttygetb.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttygeti.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttygetr.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttygets.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttygoto.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyinit.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyodes.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyputl.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyputs.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyseti.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttyso.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cttystati.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ ctype.c <libc/ctype.h>
+ cungetc.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cungetl.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ cvfnbrk.c <libc/libc.h> <libc/spp.h> <libc/knames.h>
+ cwrite.c <libc/libc.h> <libc/xnames.h> <libc/error.h>\
+ <libc/fset.h> <libc/spp.h> <libc/stdio.h>
+ cxgmes.c <libc/knames.h> <libc/libc.h> <libc/spp.h>\
+ <libc/xnames.h>
+ cxonerr.c <libc/libc.h> <libc/xnames.h>
+ cxttysize.c <libc/libc.h> <libc/xnames.h>
+ cxwhen.c <libc/xwhen.h> <libc/knames.h> <libc/libc.h>\
+ <libc/spp.h> <libc/xnames.h>
+ cwmsec.c <libc/libc.h> <libc/spp.h> <libc/knames.h>
+ eprintf.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fclose.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ fdopen.c <libc/fset.h> <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fflush.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ fgetc.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fgets.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fopen.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ fputc.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fputs.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fread.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ freadline.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ free.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ freopen.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fseek.c <libc/fset.h> <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ ftell.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ fwrite.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ gets.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ getw.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ index.c <libc/libc.h> <libc/spp.h>
+ isatty.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ malloc.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ mathf.f
+ mktemp.c <libc/libc.h> <libc/spp.h>
+ perror.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ printf.c <libc/ctype.h> <libc/libc.h> <libc/spp.h>\
+ <libc/stdio.h> <libc/xnames.h>
+ puts.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ putw.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ qsort.c <libc/libc.h>
+ realloc.c <libc/libc.h> <libc/xnames.h> <libc/spp.h>
+ rewind.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ rindex.c <libc/libc.h> <libc/spp.h>
+ scanf.c <libc/ctype.h> <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ setbuf.c <libc/fset.h> <libc/libc.h> <libc/spp.h> <libc/stdio.h>
+ stgio.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ strcat.c <libc/libc.h>
+ strcmp.c <libc/libc.h>
+ strdup.c <libc/libc.h>
+ strcpy.c <libc/libc.h>
+ strlen.c <libc/libc.h>
+ strncat.c <libc/libc.h>
+ strncmp.c <libc/libc.h>
+ strncpy.c <libc/libc.h>
+ spf.c <libc/libc.h> <libc/spp.h> <libc/xnames.h>
+ sprintf.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ system.c <libc/knames.h> <libc/libc.h> <libc/spp.h>
+ ungetc.c <libc/libc.h> <libc/spp.h> <libc/stdio.h>\
+ <libc/xnames.h>
+ ;
diff --git a/sys/libc/mktemp.c b/sys/libc/mktemp.c
new file mode 100644
index 00000000..433e64ae
--- /dev/null
+++ b/sys/libc/mktemp.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#include <iraf.h>
+
+/* MKTEMP -- Make a unique temporary file name. This procedure is syntactically
+** equivalent to the UNIX procedure of the same name, but the XXXXXX are not
+** required in the input filename.
+*/
+char *
+mktemp (
+ char *template /* root filename, e.g., "tmp$xx" */
+)
+{
+ static char unique[SZ_FNAME];
+
+ if (c_mktemp (template, unique, SZ_FNAME) > 0) {
+ (void) strcpy (template, unique);
+ return (unique);
+ } else
+ return (NULL);
+}
diff --git a/sys/libc/perror.c b/sys/libc/perror.c
new file mode 100644
index 00000000..53aa923a
--- /dev/null
+++ b/sys/libc/perror.c
@@ -0,0 +1,36 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_xnames
+#define import_stdio
+#define import_libc
+#include <iraf.h>
+
+#define SZ_OSERRMSG 80
+
+int sys_nerr; /* UNIX standard */
+char *sys_errlist[1]; /* UNIX standard */
+int u_oserrcode;
+char u_oserrmsg[SZ_OSERRMSG+1];
+
+
+/* PERROR -- Print a short error message on the standard output describing
+** the last system error (e.g., exception). The prefix string supplied
+** as the argument is first printed, followed by an ":", followed by the
+** system dependent error message describing the error.
+*/
+void
+perror (
+ char *prefix /* prefix string */
+)
+{
+ u_oserrcode = c_errget (u_oserrmsg, SZ_OSERRMSG);
+ sys_nerr = 0;
+ sys_errlist[0] = u_oserrmsg;
+
+ fputs (prefix, stderr);
+ fputs (": ", stderr);
+ fputs (u_oserrmsg, stderr);
+ fputc ('\n', stderr);
+}
diff --git a/sys/libc/printf.c b/sys/libc/printf.c
new file mode 100644
index 00000000..03b155bb
--- /dev/null
+++ b/sys/libc/printf.c
@@ -0,0 +1,245 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#define import_ctype
+#define import_stdarg
+#include <iraf.h>
+
+
+/* PRINTF -- Emulation of the UNIX printf facilities with the IRAF FMTIO
+** interface as the backend. All features of the UNIX printf are supported
+** without modification. Additional format codes are supported in conformance
+** with the IRAF printf, e.g., hms format, variable radix, tabstops, etc.,
+** but these are upward compatible with standard UNIX usage.
+*/
+
+#define SZ_FMTSPEC 25 /* max size single format spec */
+#define SZ_OBUF SZ_COMMAND /* sz intermediate buffer */
+#define MAX_PREC 4 /* max "*" deferred args */
+#define NOARG (-1) /* % spec with no data value */
+
+
+/* PRINTF -- Formatted print to the standard output.
+*/
+void
+printf (char *format, ...)
+{
+ va_list argp;
+ void u_doprnt();
+
+ va_start (argp, format);
+ u_doprnt (format, &argp, stdout);
+ va_end (argp);
+}
+
+
+/* FPRINTF -- Formatted print to a file.
+*/
+void
+fprintf (FILE *fp, char *format, ...)
+{
+ va_list argp;
+ void u_doprnt();
+
+ va_start (argp, format);
+ u_doprnt (format, &argp, fp);
+ va_end (argp);
+}
+
+
+/* U_DOPRNT -- Process the format to the output file, taking arguments from
+** the list pointed to by argp as % format specs are encountered in the input.
+** The main point of this routine is to handle the variable number of arguments.
+** The actual encoding is all handled by the IRAF FPRINF and PARG calls.
+** N.B. we assume chars are stacked as ints, and floats are stacked as doubles.
+*/
+void
+u_doprnt (
+ char *format, /* "%w.dC" etc. format spec */
+ va_list *argp, /* pointer to first value arg */
+ FILE *fp /* output file */
+)
+{
+ register int ch; /* next format char reference */
+ XCHAR formspec[SZ_FMTSPEC]; /* copy of single format spec */
+ XCHAR *fsp; /* pointer into formspec */
+ int done, dotseen; /* one when at end of a format */
+ int varprec; /* runtime precision is used */
+ int prec[MAX_PREC]; /* values of prec args */
+
+ void u_doarg ();
+
+
+ while ( (ch = *format++) ) {
+ if (ch == '%') {
+ fsp = formspec;
+ *fsp++ = ch;
+ varprec = 0;
+ dotseen = 0;
+ done = 0;
+
+ while (!done) {
+ ch = *fsp++ = *format++;
+
+ switch (ch) {
+ case EOS:
+ --format;
+ done++;
+ break;
+
+ case 'l':
+ /* arg size modifier; ignored for now */
+ fsp--;
+ break;
+
+ case '*':
+ prec[varprec++] = va_arg ((*argp), int);
+ break;
+
+ case '.':
+ dotseen++;
+ break;
+
+ case 'r': /* nonstandard UNIX */
+ if ((ch = *fsp++ = *format++) == '*') {
+ int radix;
+ int radchar;
+
+ radix = va_arg ((*argp), int);
+ if (radix < 0)
+ radchar = 'A';
+ else if (radix > 9)
+ radchar = radix - 10 + 'A';
+ else
+ radchar = todigit (radix);
+ *(fsp-1) = radchar;
+ } else if (ch == EOS) {
+ --format;
+ break;
+ }
+ /* fall through */
+
+ case 'b': /* nonstandard UNIX */
+ case 'c':
+ case 'd':
+ case 'o':
+ case 'x':
+ case 'u':
+ *fsp = EOS;
+ u_doarg (fp, formspec, &argp, prec, varprec, TY_INT);
+ done++;
+ break;
+
+ case 'E': /* ANSI emulation */
+ *(fsp-1) = 'e';
+ goto rval;
+ case 'G': /* ANSI emulation */
+ *(fsp-1) = 'g';
+ goto rval;
+
+ case 'z': /* nonstandard UNIX */
+ case 'h': /* nonstandard UNIX */
+ case 'H': /* nonstandard UNIX */
+ case 'm': /* nonstandard UNIX */
+ case 'M': /* nonstandard UNIX */
+ case 'e':
+ case 'f':
+ case 'g':
+ /* If no precision was specified, default to 14 digits
+ * for %[efgz] and 3 digits for %[hm].
+ */
+rval: if (!dotseen) {
+ *(fsp-1) = '.';
+ if (ch == 'h' || ch == 'm' ||
+ ch == 'H' || ch == 'M') {
+ *fsp++ = '3';
+ } else {
+ *fsp++ = '1';
+ *fsp++ = '4';
+ }
+ *fsp++ = ch;
+ }
+
+ *fsp = XEOS;
+ u_doarg (fp, formspec, &argp, prec, varprec, TY_DOUBLE);
+ done++;
+ break;
+
+ case 's':
+ *fsp = EOS;
+ u_doarg (fp, formspec, &argp, prec, varprec, TY_CHAR);
+ done++;
+ break;
+
+ case 't': /* nonstandard UNIX */
+ case 'w': /* nonstandard UNIX */
+ *fsp = EOS;
+ u_doarg (fp, formspec, &argp, prec, varprec, NOARG);
+ done++;
+ break;
+
+ case '%':
+ putc (ch, fp);
+ done++;
+ break;
+ }
+ }
+
+ } else
+ putc (ch, fp);
+ }
+}
+
+
+/* U_DOARG -- Encode a single argument acording to the simplified format
+** specification given by formspec. This is the interface to the IRAF
+** formatted output procedures.
+*/
+void
+u_doarg (fp, formspec, argp, prec, varprec, dtype)
+FILE *fp; /* output file */
+XCHAR *formspec; /* format string */
+va_list **argp; /* pointer to data value */
+int prec[]; /* varprec args, if any */
+int varprec; /* number of varprec args */
+int dtype; /* datatype of data value */
+{
+ register int p;
+ XCHAR sbuf[SZ_OBUF+1];
+ XINT fd = fileno (fp);
+ XINT ival;
+ XDOUBLE dval;
+ char *cptr;
+
+
+ /* Pass format string and any variable precision arguments.
+ */
+ FPRINTF (&fd, formspec);
+ for (p=0; p < varprec; p++) {
+ ival = prec[p];
+ PARGI (&ival);
+ }
+
+ /* Pass the data value to be encoded, bump argument pointer by the
+ * size of the data object. If there is no data value the case
+ * is a no-op.
+ */
+ switch (dtype) {
+ case TY_INT:
+ ival = va_arg ((**argp), int);
+ PARGI (&ival);
+ break;
+ case TY_DOUBLE:
+ dval = va_arg ((**argp), double);
+ PARGD (&dval);
+ break;
+ case TY_CHAR:
+ cptr = va_arg ((**argp), char *);
+ PARGSTR (c_strupk (cptr, sbuf, SZ_OBUF));
+ break;
+ }
+}
diff --git a/sys/libc/puts.c b/sys/libc/puts.c
new file mode 100644
index 00000000..246b7bf6
--- /dev/null
+++ b/sys/libc/puts.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* PUTS -- Put a null terminated string to the standard output, followed by a
+** newline.
+*/
+int
+puts (
+ char *str /* input string */
+)
+{
+ register FILE *fp = stdout;
+ register char *ip;
+
+
+ for (ip=str; *ip != EOS; ip++)
+ putc (*ip, fp);
+ return (putc ('\n', fp));
+}
diff --git a/sys/libc/putw.c b/sys/libc/putw.c
new file mode 100644
index 00000000..d5cf6d8a
--- /dev/null
+++ b/sys/libc/putw.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+/* PUTW -- Put a word (integer) to the output stream. When used in conjunction
+** with GETW this permits storage and retrieval of binary words to any file,
+** albeit somewhat inefficiently.
+*/
+int
+putw (
+ int word, /* data word to be output */
+ FILE *fp /* output file */
+)
+{
+ register char *ip;
+ register int n = sizeof (int);
+
+
+ for (ip=(char *)&word; --n >= 0; ip++)
+ putc (*ip, fp);
+
+ return (ferror(fp) ? EOF : word);
+}
diff --git a/sys/libc/qsort.c b/sys/libc/qsort.c
new file mode 100644
index 00000000..345fc3bd
--- /dev/null
+++ b/sys/libc/qsort.c
@@ -0,0 +1,221 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+/*
+** Copyright (c) 1980 Regents of the University of California.
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms are permitted
+** provided that the above copyright notice and this paragraph are
+** duplicated in all such forms and that any documentation,
+** advertising materials, and other materials related to such
+** distribution and use acknowledge that the software was developed
+** by the University of California, Berkeley. The name of the
+** University may not be used to endorse or promote products derived
+** from this software without specific prior written permission.
+** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+/*
+** QSORT -- Quicker sort. Adapted from the BSD sources.
+*/
+
+#define THRESH 4 /* threshold for insertion */
+#define MTHRESH 6 /* threshold for median */
+
+static int (*qcmp)(); /* the comparison routine */
+static int qsz; /* size of each record */
+static int thresh; /* THRESHold in chars */
+static int mthresh; /* MTHRESHold in chars */
+static void qst();
+
+
+/* QSORT -- First, set up some global parameters for qst to share. Then,
+** quicksort with qst(), and then a cleanup insertion sort ourselves.
+** Sound simple? It's not...
+*/
+void
+qsort (
+ char *base,
+ int n,
+ int size,
+ int (*compar)()
+)
+{
+ register char c, *i, *j, *lo, *hi;
+ char *minval, *maxval;
+
+
+ if (n <= 1)
+ return;
+
+ qsz = size;
+ qcmp = compar;
+ thresh = qsz * THRESH;
+ mthresh = qsz * MTHRESH;
+ maxval = base + n * qsz;
+
+ if (n >= THRESH) {
+ qst (base, maxval);
+ hi = base + thresh;
+ } else
+ hi = maxval;
+
+ /* First put smallest element, which must be in the first THRESH, in
+ * the first position as a sentinel. This is done just by searching
+ * the first THRESH elements (or the first n if n < THRESH), finding
+ * the min, and swapping it into the first position.
+ */
+ for (j=lo=base; (lo += qsz) < hi; )
+ if ((*qcmp)(j, lo) > 0)
+ j = lo;
+ if (j != base) {
+ /* Swap j into place */
+ for (i=base, hi=base+qsz; i < hi; ) {
+ c = *j;
+ *j++ = *i;
+ *i++ = c;
+ }
+ }
+
+ /* With our sentinel in place, we now run the following hyper-fast
+ * insertion sort. For each remaining element, min, from [1] to [n-1],
+ * set hi to the index of the element AFTER which this one goes.
+ * Then, do the standard insertion sort shift on a character at a time
+ * basis for each element in the frob.
+ */
+ for (minval=base; (hi = minval += qsz) < maxval; ) {
+ while ((*qcmp) (hi -= qsz, minval) > 0)
+ /* void */;
+ if ((hi += qsz) != minval) {
+ for (lo = minval + qsz; --lo >= minval; ) {
+ c = *lo;
+ for (i=j=lo; (j -= qsz) >= hi; i=j)
+ *i = *j;
+ *i = c;
+ }
+ }
+ }
+}
+
+
+/* QST -- Do a quicksort.
+ * First, find the median element, and put that one in the first place as the
+ * discriminator. (This "median" is just the median of the first, last and
+ * middle elements). (Using this median instead of the first element is a big
+ * win). Then, the usual partitioning/swapping, followed by moving the
+ * discriminator into the right place. Then, figure out the sizes of the two
+ * partions, do the smaller one recursively and the larger one via a repeat of
+ * this code. Stopping when there are less than THRESH elements in a partition
+ * and cleaning up with an insertion sort (in our caller) is a huge win.
+ * All data swaps are done in-line, which is space-losing but time-saving.
+ * (And there are only three places where this is done).
+ */
+static void
+qst (
+ char *base,
+ char *maxval
+)
+{
+ register char c, *i, *j, *jj;
+ register int ii;
+ char *mid, *tmp;
+ int lo, hi;
+
+ /* At the top here, lo is the number of characters of elements in the
+ * current partition. (Which should be maxval - base).
+ * Find the median of the first, last, and middle element and make
+ * that the middle element. Set j to largest of first and middle.
+ * If maxval is larger than that guy, then it's that guy, else compare
+ * maxval with loser of first and take larger. Things are set up to
+ * prefer the middle, then the first in case of ties.
+ */
+ lo = maxval - base; /* number of elements as chars */
+
+ do {
+ mid = i = base + qsz * ((lo / qsz) >> 1);
+ if (lo >= mthresh) {
+ j = ((*qcmp)((jj = base), i) > 0 ? jj : i);
+ if ((*qcmp)(j, (tmp = maxval - qsz)) > 0) {
+ /* switch to first loser */
+ j = (j == jj ? i : jj);
+ if ((*qcmp)(j, tmp) < 0)
+ j = tmp;
+ }
+ if (j != i) {
+ ii = qsz;
+ do {
+ c = *i;
+ *i++ = *j;
+ *j++ = c;
+ } while (--ii);
+ }
+ }
+
+ /* Semi-standard quicksort partitioning/swapping
+ */
+ for (i = base, j = maxval - qsz; ; ) {
+ while (i < mid && (*qcmp)(i, mid) <= 0)
+ i += qsz;
+ while (j > mid) {
+ if ((*qcmp)(mid, j) <= 0) {
+ j -= qsz;
+ continue;
+ }
+ tmp = i + qsz; /* value of i after swap */
+ if (i == mid) {
+ /* j <-> mid, new mid is j */
+ mid = jj = j;
+ } else {
+ /* i <-> j */
+ jj = j;
+ j -= qsz;
+ }
+ goto swap;
+ }
+
+ if (i == mid) {
+ break;
+ } else {
+ /* i <-> mid, new mid is i */
+ jj = mid;
+ tmp = mid = i; /* value of i after swap */
+ j -= qsz;
+ }
+
+ swap:
+ ii = qsz;
+ do {
+ c = *i;
+ *i++ = *jj;
+ *jj++ = c;
+ } while (--ii);
+ i = tmp;
+ }
+
+ /* Look at sizes of the two partitions, do the smaller
+ * one first by recursion, then do the larger one by
+ * making sure lo is its size, base and maxval are update
+ * correctly, and branching back. But only repeat
+ * (recursively or by branching) if the partition is
+ * of at least size THRESH.
+ */
+ i = (j = mid) + qsz;
+ if ((lo = j - base) <= (hi = maxval - i)) {
+ if (lo >= thresh)
+ qst(base, j);
+ base = i;
+ lo = hi;
+ } else {
+ if (hi >= thresh)
+ qst(i, maxval);
+ maxval = j;
+ }
+
+ } while (lo >= thresh);
+}
diff --git a/sys/libc/realloc.c b/sys/libc/realloc.c
new file mode 100644
index 00000000..21446345
--- /dev/null
+++ b/sys/libc/realloc.c
@@ -0,0 +1,28 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* REALLOC -- Reallocate a buffer, i.e., change the size of an already
+** allocated buffer. If necessary the buffer is moved, preserving any
+** data in the buffer.
+*/
+char *
+realloc (
+ char *buf,
+ unsigned newsize
+)
+{
+ XINT x_nchars = (newsize + sizeof(XCHAR)-1) / sizeof(XCHAR);
+ XINT x_ptr, x_dtype = TY_CHAR;
+
+ x_ptr = buf ? Memcptr(buf) : NULL;
+ iferr (REALLOC (&x_ptr, &x_nchars, &x_dtype))
+ return (NULL);
+ else
+ return ((char *)&Memc[x_ptr]);
+}
diff --git a/sys/libc/rewind.c b/sys/libc/rewind.c
new file mode 100644
index 00000000..0185916c
--- /dev/null
+++ b/sys/libc/rewind.c
@@ -0,0 +1,19 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#include <iraf.h>
+
+
+/* REWIND -- Position the named stream to beginning of file, i.e., arrange
+** for the next read or write to read or write the first byte of the file.
+*/
+long
+rewind (
+ FILE *fp /* operand file */
+)
+{
+ return ((long) fseek (fp, 0L, 0));
+}
diff --git a/sys/libc/rindex.c b/sys/libc/rindex.c
new file mode 100644
index 00000000..74169120
--- /dev/null
+++ b/sys/libc/rindex.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#define import_spp
+#include <iraf.h>
+
+
+/* RINDEX -- Search string STR for char CH, returning a pointer to the last
+** occurrence of CH in STR or NULL.
+*/
+char *
+rindex (
+ char *str, /* string to be searched */
+ int ch /* character we are searching for */
+)
+{
+ register char *ip = str;
+ register char *last = NULL;
+
+ do {
+ if (*ip == ch)
+ last = ip;
+ } while (*ip++);
+
+ return (last);
+}
diff --git a/sys/libc/scanf.c b/sys/libc/scanf.c
new file mode 100644
index 00000000..1ada2000
--- /dev/null
+++ b/sys/libc/scanf.c
@@ -0,0 +1,558 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_ctype
+#define import_stdarg
+#include <iraf.h>
+
+
+/*
+** SCANF -- Formatted input. The syntax of the calls and of the format strings
+** are UNIX standard, but the lexical forms of numbers recognized are IRAF
+** standard.
+*/
+
+#define SCAN_STRING 0
+#define SCAN_FILE 1
+#define SZ_NUMBUF 256 /* maximum numeric field len */
+#define SZ_UCC 128 /* maximum size user char class */
+#define HUGE 999
+#define ISHEX(c) ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
+
+struct _format {
+ int f_type; /* field type (doxscef[%) */
+ int f_skipfield; /* skip next field scanned */
+ int f_width; /* max chars in field */
+ int f_longword; /* output longword */
+ int f_halfword; /* output halfword */
+ int f_delimset; /* ucc chars are delimiters */
+ char f_ucc[SZ_UCC+1];
+};
+
+/* Character input including pushback. Character input may come either from
+** a file or from a string, depending on the value of the "intype" flag.
+** We cannot open the string as a file because file buffer characters are
+** of type XCHAR.
+*/
+struct _input {
+ int i_type; /* file input if !0, else str */
+ int i_nchars; /* nchars read thus far */
+ union {
+ FILE *fp; /* file pointer if file */
+ char *ip; /* char pointer if string */
+ } u;
+};
+
+#define input()\
+ (in->i_nchars++, in->i_type ? (int)getc(in->u.fp) : (int)*in->u.ip++)
+#define unput(ch)\
+ (in->i_nchars--, in->i_type ? ungetc((ch),in->u.fp) : (int)(*--(in->u.ip)))
+#define ateof()\
+ (in->i_type ? feof(in->u.fp) : *(in->u.ip-1) == EOS)
+
+
+static int u_doscan (struct _input *in, char *format, va_list *argp);
+static char *u_crackformat (char *format, struct _format *fmt);
+static int u_scannum (struct _input *in, va_list **argp,
+ struct _format *fmt, int *eofflag);
+static char *u_setucc (char *format, struct _format *fmt);
+static int u_scanstr (struct _input *in, va_list **argp,
+ struct _format *fmt, int *eofflag);
+
+
+
+/* SCANF -- Scan the standard input. The output arguments must be
+** pointers. The number of fields successfully converted is returned as
+** the function value. EOF is returned for a scan at EOF.
+*/
+int
+scanf (char *format, ...)
+{
+ va_list argp;
+ struct _input in;
+ int status;
+
+ extern int u_doscan();
+
+
+ va_start (argp, format);
+ in.i_type = SCAN_FILE;
+ in.i_nchars = 0;
+ in.u.fp = stdin;
+
+ status = u_doscan (&in, format, &argp);
+ va_end (argp);
+ return (status);
+}
+
+
+/* FSCANF -- Formatted scan from a file.
+*/
+int
+fscanf (FILE *fp, char *format, ...)
+{
+ va_list argp;
+ int status;
+ struct _input in;
+
+ extern int u_doscan();
+
+
+ va_start (argp, format);
+ in.i_type = SCAN_FILE;
+ in.i_nchars = 0;
+ in.u.fp = fp;
+
+ status = u_doscan (&in, format, &argp);
+
+ va_end (argp);
+ return (status);
+}
+
+
+/* SSCANF -- Formatted scan from a string.
+*/
+int
+sscanf (char *str, char *format, ...)
+{
+ va_list argp;
+ struct _input in;
+ int status;
+
+ extern int u_doscan();
+
+
+ va_start (argp, format);
+ in.i_type = SCAN_STRING;
+ in.i_nchars = 0;
+ in.u.ip = str;
+
+ status = u_doscan (&in, format, &argp);
+
+ va_end (argp);
+ return (status);
+}
+
+
+/* U_DOSCAN -- Step along the format string, processing each %[*][w][lh]C
+** field specification and returning each argument using the pointer
+** supplied in the argument list. Ordinary characters appearing in the format
+** string must match actual characters in the input stream. Input may be
+** taken from either a string or a file. The technique used to handle the
+** variable number of arguments is machine dependent.
+*/
+static int
+u_doscan (
+ struct _input *in, /* input descriptor */
+ char *format, /* format string */
+ va_list *argp /* pointer to first argument */
+)
+{
+ register int ch;
+ struct _format fmt;
+ int nscan = 0, match;
+ int eofflag = 0;
+ char *u_crackformat(), *u_setucc();
+ int u_scanstr(), u_scannum();
+
+
+ while ( (ch = *format++) ) {
+ if (ch == '%' && *format != '%') {
+ /* Parse format specification.
+ */
+ format = u_crackformat (format, &fmt);
+
+ /* Extract, decode, and output the next field according to
+ * the field specification just generated.
+ */
+ ch = *format++;
+ if (ch == 'n') {
+ *(va_arg ((*argp), int *)) = in->i_nchars;
+ continue;
+ } else if (ch == '[') {
+ format = u_setucc (format, &fmt);
+ } else if (isupper (ch)) {
+ fmt.f_longword++;
+ ch = tolower (ch);
+ }
+ if (ch <= 0)
+ return (EOF);
+ fmt.f_type = ch;
+
+ if (ch == 's' || ch == 'c' || ch == '[')
+ match = u_scanstr (in, &argp, &fmt, &eofflag);
+ else
+ match = u_scannum (in, &argp, &fmt, &eofflag);
+
+ if (match && !fmt.f_skipfield)
+ nscan++;
+ if (eofflag)
+ break;
+
+ } else if (isspace (ch)) {
+ /* Skip optional whitespace. */
+ while (isspace (ch = input()))
+ ;
+ if (ateof()) {
+ eofflag++;
+ break;
+ }
+ unput (ch);
+
+ } else {
+ /* Match normal character. */
+ if (ch == '%')
+ format++;
+ match = ch;
+ if (match != (ch = input())) {
+ if (ateof())
+ eofflag++;
+ else
+ unput (ch);
+ break;
+ }
+ }
+ }
+
+ if (eofflag)
+ return (nscan ? nscan : EOF);
+ else
+ return (nscan);
+}
+
+
+
+/* U_CRACKFORMAT -- Decode a %[*][w][lh]C input field format specification,
+ * returning the decoded format parameters in the output structure fmt.
+ * The number of format characters is returned as the function value. The
+ * format string pointer is left pointing at the C character.
+ */
+static char *
+u_crackformat (
+ char *format, /* pointer to %+1 in format string */
+ struct _format *fmt /* output format descriptor */
+)
+{
+ register int ch;
+ register int width = 0;
+
+
+ fmt->f_skipfield = 0;
+ fmt->f_longword = 0;
+ fmt->f_halfword = 0;
+
+ /* Skip output if "*" present. */
+ ch = *format++;
+ if (ch == '*') {
+ fmt->f_skipfield++;
+ ch = *format++;
+ }
+
+ /* Get max field width, if any. */
+ while (isdigit (ch)) {
+ width = width * 10 + tointeg (ch);
+ ch = *format++;
+ }
+ fmt->f_width = (width == 0) ? HUGE : width;
+
+ /* Datatype size modifier. */
+ if (ch == 'l') {
+ fmt->f_longword++;
+ ch = *format++;
+ } else if (ch == 'h') {
+ fmt->f_halfword++;
+ ch = *format++;
+ }
+
+ return (--format);
+}
+
+
+/* U_SCANNUM -- Extract a numeric token from the input stream. The lexical
+** range of numbers recognized is as follows (ignoring leading +-):
+**
+** INDEF all types
+** [0-7]+ o
+** [0-9]+ d
+** [0-9][0-9a-fA-F]* x
+** '.'[0-9]+([eEdD]([+-])?[0-9]+)? f,e
+** [0-9][0-9:]'.'[0-9]+([eEdD]([+-])?[0-9]+)? f,e (sexagesimal)
+**
+** If the conversion fails the token is pushed back into the input, ready
+** to be rescanned. Argp is bumped if skipfield is false whether or not
+** a legal number is matched (else one might assign a string to a pointer
+** to int in the next format, overruning memory). If the match fails 0 is
+** output to argp and 0 is returned as the function value, indicating no
+** match.
+*/
+static int
+u_scannum (
+ struct _input *in, /* input descriptor */
+ va_list **argp, /* where output goes */
+ struct _format *fmt, /* format descriptor */
+ int *eofflag /* set to 1 on output if end of input */
+)
+{
+ char numbuf[SZ_NUMBUF+1];
+ register int ch;
+ register long num = 0;
+ register char *op = numbuf;
+ int floating = 0, radix=10, n;
+ int neg=0, ndigits=0, match=1;
+ int dotseen=0, expseen=0;
+
+
+ ch = fmt->f_type;
+ n = fmt->f_width;
+
+ if (ch == 'd')
+ radix = 10;
+ else if (ch == 'o')
+ radix = 8;
+ else if (ch == 'x')
+ radix = 16;
+ else if ( (floating = (ch == 'f' || ch == 'e' || ch == 'g') )) {
+ radix = 10;
+ dotseen = expseen = 0;
+ }
+
+ while (isspace ( (ch = input()) ))
+ ;
+
+ if (ch == '-' || ch == '+') {
+ if (ch == '-') {
+ neg++;
+ *op++ = ch;
+ }
+ ch = input();
+ --n;
+ }
+
+ /* Check for INDEF. Abbreviations are not permitted; if the match
+ * fails the input must be restored.
+ */
+ if (ch == 'I' && op == numbuf && n >= 5) {
+ char *ip = "INDEF";
+
+ for (n=5; --n >= 0 && (ch == *ip++); ch=input())
+ *op++ = ch;
+ *op = EOS;
+ if (!ateof())
+ unput (ch);
+
+ if (n < 0) {
+ /* If the 6th char is not a legal character in an identifier
+ * then we have a match.
+ */
+ if (! (isalnum (ch) || ch == '_')) {
+ if (fmt->f_skipfield)
+ return (1);
+ else if (floating)
+ goto out_;
+ else {
+ if (fmt->f_longword)
+ *(va_arg ((**argp), long *)) = INDEFL;
+ else if (fmt->f_halfword)
+ *(va_arg ((**argp), short *)) = INDEFS;
+ else
+ *(va_arg ((**argp), int *)) = INDEFI;
+ return (1);
+ }
+ }
+ }
+
+ /* No match; neither INDEF nor a number. Push back chars and exit.
+ * (the FIO ungetc may be called repeatedly).
+ */
+ for (--op; op >= numbuf; --op)
+ unput (*op);
+
+ match = 0;
+ num = 0;
+ numbuf[0] = '0';
+ goto out_;
+ }
+
+ /* Extract token into numbuf. If the token contains only digits it
+ * will have been converted to binary and left in the variable num.
+ */
+ for (*op++ = ch; --n >= 0; *op++ = ch = input()) {
+ if (isdigit (ch)) {
+ ch = tointeg (ch);
+ if (ch >= radix)
+ break;
+ ndigits++;
+ num = num * radix + ch;
+
+ } else if (radix == 16 && ISHEX(ch)) {
+ if (isupper (ch))
+ ch = tolower (ch);
+ ndigits++;
+ num = num * 16 + ch - 'a' + 10;
+
+ } else if (ch == '.') {
+ if (!floating || dotseen)
+ break;
+ dotseen++;
+ } else if (ch == ':') {
+ if (!floating || ndigits == 0 || dotseen || expseen)
+ break;
+
+ } else if (ch == 'e' || ch == 'E' || ch == 'd' || ch == 'D') {
+ if (!floating || expseen || (ndigits == 0 && !dotseen))
+ break;
+ expseen++;
+ *op++ = ch = input();
+ if (! (ch == '+' || ch == '-' || isdigit(ch)))
+ break;
+
+ } else
+ break;
+ }
+
+ *--op = EOS;
+ if (ateof())
+ *eofflag = 1;
+ else
+ unput (ch);
+
+ if (ndigits == 0)
+ match = 0; /* not a number */
+ if (neg)
+ num = -num;
+out_:
+ if (fmt->f_skipfield)
+ return (match);
+
+ /* Output value.
+ */
+ if (floating) {
+ float rval;
+ double dval, atof();
+
+ if (fmt->f_longword) {
+ *(va_arg ((**argp), double *)) = atof (numbuf);
+ } else if (fmt->f_halfword) {
+ dval = atof (numbuf);
+ rval = (dval == INDEFD) ? INDEFR : dval;
+ *(va_arg ((**argp), float *)) = rval;
+ } else
+ *(va_arg ((**argp), double *)) = atof (numbuf);
+ } else {
+ if (fmt->f_longword)
+ *(va_arg ((**argp), long *)) = num;
+ else if (fmt->f_halfword)
+ *(va_arg ((**argp), short *)) = num;
+ else
+ *(va_arg ((**argp), int *)) = num;
+ }
+
+ return (match);
+}
+
+
+/* U_SETUCC -- Extract a user defined character class from the format string.
+** A full 128 char table is not used since it is more expensive to prepare
+** than it is worth for small sets.
+*/
+static char *
+u_setucc (
+ char *format,
+ struct _format *fmt
+)
+{
+ register char *op = fmt->f_ucc;
+ register int n = SZ_UCC;
+
+ fmt->f_delimset = (*format == '^') ? *format++ : 0;
+ while (--n && *format && (*op = *format++) != ']') {
+ if (*op == '\\' && *format == ']')
+ *op = *format++;
+ op++;
+ }
+ *op = EOS;
+
+ return (format);
+}
+
+
+
+/* U_SCANSTR -- Extract a whitespace delimited sequence of characters.
+*/
+static int
+u_scanstr (
+ struct _input *in, /* input descriptor */
+ va_list **argp, /* output arglist */
+ struct _format *fmt, /* numeric format expected */
+ int *eofflag /* set to 1 on output if end of input */
+)
+{
+ register int ch, n;
+ register char *ip, *op;
+ int delimset;
+ char *ucc = "";
+
+
+ op = fmt->f_skipfield ? (char *)NULL : va_arg ((**argp), char *);
+ ch = fmt->f_type;
+ n = fmt->f_width;
+ if (ch == 'c' && n == HUGE)
+ n = 1;
+
+ /* Set up character class to be matched.
+ */
+ delimset = 1;
+ if (ch == 'c')
+ ucc = "";
+ else if (ch == 's')
+ ucc = " \t\n";
+ else if (ch == '[') {
+ ucc = fmt->f_ucc;
+ delimset = fmt->f_delimset;
+ }
+
+ /* Skip leading whitespace only for format %s.
+ */
+ if (ch == 's') {
+ while (isspace (ch = input()))
+ ;
+ } else
+ ch = input();
+
+ /* Extract chars matching set into output buffer.
+ */
+ while (--n >= 0 && (ch > 0 || !ateof())) {
+ /* Is char in set ucc. */
+ for (ip=ucc; *ip != EOS; ip++)
+ if (ch == *ip) {
+ if (delimset)
+ goto done_;
+ if (op)
+ *op++ = ch;
+ goto next_;
+ }
+
+ /* Char not in set if we get here. */
+ if (delimset) {
+ if (op)
+ *op++ = ch;
+ } else
+ break;
+next_:
+ ch = input();
+ }
+done_:
+ if (ateof())
+ *eofflag = 1;
+ else {
+ unput (ch);
+ }
+
+ if (op && fmt->f_type != 'c')
+ *op = EOS;
+
+ return (1);
+}
diff --git a/sys/libc/setbuf.c b/sys/libc/setbuf.c
new file mode 100644
index 00000000..845c9f9d
--- /dev/null
+++ b/sys/libc/setbuf.c
@@ -0,0 +1,68 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_stdio
+#define import_fset
+#include <iraf.h>
+
+
+/* SETBUF -- Assign a buffer to be used by the i/o system to access a file.
+** Should be called after opening the file but before doing any i/o.
+*/
+void
+setbuf (
+ FILE *fp,
+ char *buf
+)
+{
+ void setbuffer();
+
+ setbuffer (fp, buf, BUFSIZ);
+}
+
+
+/* SETBUFFER -- Assign a buffer of arbitrary size to be used by the i/o system
+** to access a file. Should be called after opening the file but before doing
+** any i/o. If the the pointer buf has the value NULL, i/o is unbuffered
+** (or as close to unbuffered as we can manage).
+*/
+void
+setbuffer (
+ FILE *fp,
+ char *buf,
+ int size
+)
+{
+ register XINT fd = fileno(fp);
+
+
+ if (buf == NULL)
+ c_fseti (fd, F_BUFSIZE, 1);
+ else {
+ c_fseti (fd, F_BUFPTR, Memcptr(buf));
+ c_fseti (fd, F_BUFSIZE, size);
+ }
+}
+
+
+/* SETLINEBUF -- Set line buffered mode for a file. A line buffered file
+ * buffers each line and flushes it to the output device when newline is
+ * seen. We may be even after doing i/o to the file.
+ */
+void
+setlinebuf (
+ FILE *fp
+)
+{
+ register XINT fd = fileno(fp);
+
+ extern int c_fstati();
+ extern void c_fseti();
+
+
+ if (c_fstati (fd, F_BUFSIZE) < SZ_LINE)
+ c_fseti (fd, F_BUFSIZE, SZ_LINE);
+ c_fseti (fd, F_FLUSHNL, YES);
+}
diff --git a/sys/libc/spf.c b/sys/libc/spf.c
new file mode 100644
index 00000000..2953ed76
--- /dev/null
+++ b/sys/libc/spf.c
@@ -0,0 +1,65 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/*
+** SPF.C -- String spoolfile utility package. Used to capture in a string
+** buffer the output of a routine set up to write to a file.
+**
+** Example:
+**
+** fd = spf_open (buf, maxch)
+** fprop (pp, fdopen(fd,"w"));
+** spf_close (fd);
+**
+** leaves the output of the fprop() function in the user buffer "buf".
+*/
+
+static XCHAR *spf_buf;
+static char *spf_userbuf;
+static int spf_maxch;
+
+
+/* SPF_OPEN -- Spoolfile open. Open a string spoolfile to be written into as
+** a file, using ordinary file i/o. Only one such file can be open at a time.
+*/
+int
+spf_open (
+ char *buf, /* user string buffer */
+ int maxch /* max chars of storage */
+)
+{
+ XINT x_maxch = maxch, x_mode = NEW_FILE;
+ char *malloc();
+
+
+ spf_userbuf = buf;
+ spf_maxch = maxch;
+
+ /* Malloc always returns a buffer which aligned to at least XCHAR. */
+ spf_buf = (XCHAR *) malloc ((maxch + 1) * sizeof(XCHAR));
+
+ return (STROPEN (spf_buf, &x_maxch, &x_mode));
+}
+
+
+/* SPF_CLOSE -- Close the spoolfile string, which should have been written
+** into via file i/o while the string was open. This leaves SPP chars in
+** the string; pack the string and return a pointer to the string.
+*/
+void
+spf_close (
+ XINT fd /* file descriptor of stringbuf */
+)
+{
+ XINT x_fd = fd;
+
+ CLOSE (&x_fd);
+ c_strpak (spf_buf, spf_userbuf, spf_maxch);
+ free ((char *)spf_buf);
+}
diff --git a/sys/libc/sprintf.c b/sys/libc/sprintf.c
new file mode 100644
index 00000000..24d408a0
--- /dev/null
+++ b/sys/libc/sprintf.c
@@ -0,0 +1,58 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#define import_stdarg
+#include <iraf.h>
+
+#define SZ_OBUF SZ_COMMAND /* sz intermediate buffer */
+
+
+/* SPRINTF -- Formatted print to a string. If char and XCHAR are the
+** same size we open the output string as a file and write directly into
+** it. Otherwise we must write into an intermediate buffer, then pack
+** XCHAR into the char output string. This is not as bad as it sounds
+** as the operation is negligible compared to the encoding operation.
+*/
+char *
+sprintf (char *str, char *format, ...)
+{
+ register XCHAR *ip;
+ register char *op;
+ XCHAR obuf[SZ_OBUF], *fiobuf;
+ XINT x_fd, x_maxch = SZ_OBUF, x_mode = NEW_FILE;
+ va_list argp;
+
+ extern int u_doprnt();
+
+
+ va_start (argp, format);
+
+ /* Select output buffer. */
+ if (sizeof (XCHAR) == sizeof (char))
+ fiobuf = (XCHAR *)str;
+ else
+ fiobuf = obuf;
+
+ /* Make it the file buffer. Call FIO to open the string as a file.
+ */
+ x_fd = STROPEN (fiobuf, &x_maxch, &x_mode);
+
+ /* Format the data into obuf. */
+ u_doprnt (format, &argp, FDTOFP(x_fd));
+
+ /* FIO does not write the EOS until the string file is closed.
+ * Move obuf to str if it is not already there.
+ */
+ CLOSE (&x_fd);
+ if (fiobuf == obuf)
+ for (ip=obuf, op=str; (*op++ = *ip++) != EOS; )
+ ;
+
+ va_end (argp);
+
+ return (str);
+}
diff --git a/sys/libc/stgio.c b/sys/libc/stgio.c
new file mode 100644
index 00000000..498a020a
--- /dev/null
+++ b/sys/libc/stgio.c
@@ -0,0 +1,60 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#include <iraf.h>
+
+
+/* STGIO.C -- STDGRAPH graphics terminal i/o interface. This is a C binding
+** for the VOS STDGRAPH graphics kernel text i/o routines. These are used to
+** do direct i/o to the graphics terminal, whether or not the terminal is in
+** graphics mode. When the terminal is not in graphics mode, i.e., when the
+** "workstation is deactivated", these routines are equivalent to the FIO
+** putline and getline procedures.
+**
+** nchars|EOF = c_stggetline (STDIN, buf)
+** c_stgputline (STDOUT, buf)
+*/
+
+
+/* C_STGGETLINE -- Get a line of text from the graphics terminal.
+*/
+int
+c_stggetline (
+ XINT fd, /* input stream */
+ char *buf, /* user string buffer */
+ int maxch /* max bufer size */
+)
+{
+ XCHAR xbuf[maxch+1];
+ XINT x_fd = fd;
+ int status;
+
+ iferr (status = STG_GETLINE (&x_fd, xbuf))
+ return (EOF);
+ else {
+ c_strpak (xbuf, buf, maxch);
+ return (status);
+ }
+}
+
+
+/* C_STGPUTLINE -- Put a line of text to the graphics terminal.
+*/
+int
+c_stgputline (
+ XINT fd, /* input stream */
+ char *buf /* user string buffer */
+)
+{
+ XCHAR xbuf[SZ_LINE+1];
+ XINT x_fd = fd;
+
+ c_strupk (buf, xbuf, SZ_LINE);
+ iferr (STG_PUTLINE (&x_fd, xbuf))
+ return (ERR);
+ else
+ return (OK);
+}
diff --git a/sys/libc/strcat.c b/sys/libc/strcat.c
new file mode 100644
index 00000000..49798ba0
--- /dev/null
+++ b/sys/libc/strcat.c
@@ -0,0 +1,24 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+
+/* STRCAT -- Concatenate S2 onto S1.
+*/
+char *
+strcat (
+ char *s1, /* output string */
+ char *s2 /* string to be appended */
+)
+{
+ register char *ip, *op;
+
+ for (op=s1; *op++; )
+ ;
+ for (--op, ip=s2; (*op++ = *ip++); )
+ ;
+
+ return (s1);
+}
diff --git a/sys/libc/strcmp.c b/sys/libc/strcmp.c
new file mode 100644
index 00000000..7b7dc54a
--- /dev/null
+++ b/sys/libc/strcmp.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+
+/* STRCMP -- Compare two strings. -N is returned if S1 < S2, 0 if S1 == S2,
+** and +N if S1 > S2.
+*/
+int
+strcmp (
+ char *s1,
+ char *s2
+)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+
+ return (*s1 - *--s2);
+}
diff --git a/sys/libc/strcpy.c b/sys/libc/strcpy.c
new file mode 100644
index 00000000..cbc072f0
--- /dev/null
+++ b/sys/libc/strcpy.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+/* STRCPY -- Copy string S2 to S1.
+*/
+char *
+strcpy (
+ char *s1, /* output string */
+ char *s2 /* string to be moved */
+)
+{
+ register char *ip, *op;
+
+ for (ip=s2, op=s1; (*op++ = *ip++); )
+ ;
+
+ return (s1);
+}
diff --git a/sys/libc/strdup.c b/sys/libc/strdup.c
new file mode 100644
index 00000000..4568d89f
--- /dev/null
+++ b/sys/libc/strdup.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+/* STRDUP -- Save a copy of a string.
+*/
+char *
+strdup (
+ char *str /* string to copy */
+)
+{
+ register char *ip, *op, *out;
+ int len = strlen (str);
+
+ out = calloc (1, strlen (str) + 1);
+ for (ip=str, op=out; (*op++ = *ip++); )
+ ;
+
+ return (out);
+}
diff --git a/sys/libc/strlen.c b/sys/libc/strlen.c
new file mode 100644
index 00000000..c6c2f813
--- /dev/null
+++ b/sys/libc/strlen.c
@@ -0,0 +1,21 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#define import_libc
+#include <iraf.h>
+
+
+/* STRLEN -- Length of a string.
+*/
+int
+strlen (
+ char *s
+)
+{
+ register char *ip=s;
+
+ while (*ip++)
+ ;
+
+ return (ip - s - 1);
+}
diff --git a/sys/libc/strncat.c b/sys/libc/strncat.c
new file mode 100644
index 00000000..9deae4eb
--- /dev/null
+++ b/sys/libc/strncat.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+
+/* STRNCAT -- Concatenate at most N chars from S2 onto S1.
+*/
+char *
+strncat (
+ char *s1, /* output string */
+ char *s2, /* string to be appended */
+ int n /* max length of S1 */
+)
+{
+ register char *ip, *op;
+
+ for (op=s1; *op++; )
+ ;
+ for (--op, ip=s2; (*op++ = *ip++) && --n >= 0; )
+ ;
+ *--op = '\0';
+
+ return (s1);
+}
diff --git a/sys/libc/strncmp.c b/sys/libc/strncmp.c
new file mode 100644
index 00000000..089df283
--- /dev/null
+++ b/sys/libc/strncmp.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+/* STRNCMP -- Compare up to the first N characters of two strings. -N is
+** returned if S1 < S2, 0 if S1 == S2, and +N if S1 > S2.
+*/
+int
+strncmp (
+ char *s1,
+ char *s2,
+ int n
+)
+{
+ while (--n >= 0 && *s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+
+ return (n < 0 ? 0 : *s1 - *--s2);
+}
diff --git a/sys/libc/strncpy.c b/sys/libc/strncpy.c
new file mode 100644
index 00000000..79e99495
--- /dev/null
+++ b/sys/libc/strncpy.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_libc
+#include <iraf.h>
+
+
+/* STRNCPY -- Copy exactly N characters from S2 to S1, truncating or null
+** padding S2; the output string may not be null terminated if the length
+** of S2 is N or more.
+*/
+char *
+strncpy (
+ char *s1, /* output string */
+ char *s2, /* string to be moved */
+ int n
+)
+{
+ register char *ip, *op;
+
+ for (ip=s2, op=s1; --n >= 0 && (*op++ = *ip++); )
+ ;
+ while (--n >= 0)
+ *op++ = '\0';
+
+ return (s1);
+}
diff --git a/sys/libc/system.c b/sys/libc/system.c
new file mode 100644
index 00000000..44265864
--- /dev/null
+++ b/sys/libc/system.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_knames
+#include <iraf.h>
+
+
+/* SYSTEM -- Send a command to the host system. OK is returned if the command
+** executes properly, else a positive integer error code identifying the error
+** which occurred.
+*/
+int
+system (
+ char *cmd /* command to be sent to host system */
+)
+{
+ PKCHAR nullstr[1];
+ XINT status;
+
+ nullstr[0] = EOS;
+ ZOSCMD (cmd, nullstr, nullstr, nullstr, &status);
+
+ return ((int) status);
+}
diff --git a/sys/libc/ungetc.c b/sys/libc/ungetc.c
new file mode 100644
index 00000000..2773f4e1
--- /dev/null
+++ b/sys/libc/ungetc.c
@@ -0,0 +1,29 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+*/
+
+#define import_spp
+#define import_libc
+#define import_xnames
+#define import_stdio
+#include <iraf.h>
+
+
+/* UNGETC -- Push a character back into the input stream. Pushback is last
+** in first out, i.e., the last character pushed back is the first one
+** read by GETC. Characters (and strings) may be pushed back until the
+** FIO pushback buffer overflows.
+*/
+int
+ungetc (
+ int ch,
+ FILE *fp
+)
+{
+ XINT x_fd = fileno(fp);
+ XCHAR x_ch = ch;
+
+ iferr (UNGETC (&x_fd, &x_ch))
+ return (EOF);
+ else
+ return (ch);
+}
diff --git a/sys/libc/zzdebug.x b/sys/libc/zzdebug.x
new file mode 100644
index 00000000..88cf9551
--- /dev/null
+++ b/sys/libc/zzdebug.x
@@ -0,0 +1,7 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+task hello = t_hello,
+ print = t_print,
+ copy = t_copy,
+ scan = t_scan,
+ gettok = t_gettok
diff --git a/sys/libc/zztest.c b/sys/libc/zztest.c
new file mode 100644
index 00000000..b43fe705
--- /dev/null
+++ b/sys/libc/zztest.c
@@ -0,0 +1,98 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#define import_libc
+#define import_stdio
+#define import_spp
+#define import_error
+#define import_xwhen
+#include <iraf.h>
+
+thello_()
+{
+ fputs ("hello, world\n", stdout);
+}
+
+
+tprint_()
+{
+ char buf[128];
+
+ sprintf (buf, "\tabcdef %0*d[%-5.2s], %h\n", 5, 99, "wxyz", 12.5);
+ fputs (buf, stdout);
+}
+
+
+tcopy_()
+{
+ FILE *in, *out;
+ int ch;
+
+ if ((in = fopen ("junk", "r")) == NULL)
+ c_erract (EA_ERROR);
+ if ((out = fopen ("junk2", "wb")) == NULL)
+ c_erract (EA_ERROR);
+
+ while ((ch = getc (in)) != EOF)
+ putc (ch, out);
+
+ fclose (in);
+ fclose (out);
+}
+
+
+tscan_()
+{
+ char buf[SZ_LINE];
+ char str[SZ_LINE];
+ char cval;
+ int ival, nscan, n1, n2;
+ int onint(), oldint;
+ double dval;
+
+ c_xwhen (X_INT, onint, &oldint);
+
+ printf (">> \n");
+ fflush (stdout);
+
+ while (fgets (buf, SZ_LINE, stdin) != NULL) {
+ nscan = sscanf (buf,
+ "%n%c %*s %d %lg %s%n", &n1, &cval, &ival, &dval, str, &n2);
+ printf ("nscan=%d: %d '%c' %d %g '%s' %d\n",
+ nscan, n1, cval, ival, dval, str, n2);
+ printf (">> \n");
+ fflush (stdout);
+ }
+
+ eprintf ("all done\n");
+}
+
+
+onint (code, old_handler)
+int *code; /* NOTUSED */
+int *old_handler;
+{
+ write (2, "\7", 1);
+ *old_handler = 0;
+}
+
+
+tgettk_()
+{
+ XCHAR fname[SZ_FNAME+1];
+ char token[SZ_LINE+1], delim;
+ int maxch = SZ_FNAME;
+ FILE *fp;
+
+ clgstr_ (c_sppstr("fname"), fname, &maxch);
+ c_strpak (fname, token, maxch);
+
+ fp = fopen (token, "r");
+ if (fp == NULL)
+ c_erract (EA_ERROR);
+
+ while (fscanf (fp, " %[^ \t\n,:()!^&+-*/;|?<>]%c", token,&delim) != EOF)
+ eprintf ("%s\n%c\n", token, delim);
+
+ fclose (fp);
+}