From 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 Mon Sep 17 00:00:00 2001 From: Joe Hunkeler Date: Tue, 11 Aug 2015 16:51:37 -0400 Subject: Repatch (from linux) of OSX IRAF --- unix/os/doc/os.ms | 4249 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4249 insertions(+) create mode 100644 unix/os/doc/os.ms (limited to 'unix/os/doc/os.ms') diff --git a/unix/os/doc/os.ms b/unix/os/doc/os.ms new file mode 100644 index 00000000..61aa14fe --- /dev/null +++ b/unix/os/doc/os.ms @@ -0,0 +1,4249 @@ +.RP +.ND +.TL +A Reference Manual +.br +for the +.br +IRAF System Interface +.AU +Doug Tody +.AI +.K2 "" "" "*" +May 1984 +.AB +The IRAF system interface is the interface between the transportable IRAF +system and the host operating system. An overview of the software design +of the IRAF system is presented, naming the major interfaces and +discussing their relationships. The system interface is shown to consist +of a language interface, the subset preprocessor (SPP), and a procedural +interface, the IRAF kernel. The reasoning which led to the choice of +a Fortran preprocessor for the language interface is reviewed. A reference +manual for the IRAF kernel is presented, followed by the detailed technical +specifications for the kernel procedures. +.AE + +.NH +Introduction +.PP +The IRAF system libraries currently total 42 thousand lines of code. +The applications software adds another 75 thousand lines +of code, about half of which was imported (i.e., the graphics utilities and +math library routines). The UNIX implementation of the machine dependent +portion of the IRAF system consists of some 3300 lines of code, or about +3 percent of the current system. The remainder of the system, i.e., +approximately 97 percent of the current system, is machine and device +independent. It is this 3 percent of the IRAF system which is machine +dependent, known as the \fBsystem interface\fR, which is the focus of this +document. +.PP +The importance of maximizing the transportability of a large software system +cannot be overemphasized. The IRAF system is required to run on +a variety of different computers and operating systems from the time of +its first release to the end of its useful life. The computer the IRAF +system is being developed on is already old technology. Two years from +now when IRAF is a mature system, it will almost certainly contain 20 to +30 manyears of software. With the increasing dependence on computers for +scientific data analysis, and the demand for increasingly powerful software, +it is no longer possible to keep up with demand if we have to throw out +our systems every 5 or 10 years and start over. +.PP +Commercially developed operating systems/programming environments such as +UNIX and ADA offer some hope for the future. At present, however, ADA is +not widely available and there are at least half a dozen versions of UNIX +in use, with no clear cut standard yet to emerge. The different versions +of UNIX resemble each other, but there are many differences. UNIX has been +steadily evolving for ten years and there is no reason to expect that the +process will stop now. +.PP +Many manufacturers offer machine dependent extensions to get around the +inefficiencies of basic UNIX, and it is desirable to be able to take advantage +of these in a production system. Even in a hardcore UNIX system like 4.2BSD, +significant efficiency gains are possible by taking advantage of the +peculiarities of the 4.2BSD kernel, e.g., by always doing file transfers +in units of the machine page size, into buffers aligned on page boundaries. +In a large system it is difficult to take advantage of such machine +peculiarities unless the system has a well defined and well isolated interface +to the host system. There is no denying the fact that despite the many +attractive aspects of UNIX, it is nice to have the option of switching to +a more efficient operating system if IRAF is to be used in a production +environment. +.PP +Perhaps the most powerful argument is that despite the increasingly widespread +use of UNIX, many of the sites for which IRAF is targeted do not or can not +run UNIX on their current computers. The increasing availability of +transportable operating systems will make transporting IRAF easier, but is no +substitute for a well defined and well isolated system interface. +.PP +The \fBsystem interface\fR is the interface between the machine independent +IRAF software and the host operating system. +The system interface consists of a procedural interface, the IRAF +\fBkernel\fR, and a language interface, the IRAF Subset Preprocessor +language (SPP). Both types of interface are required to isolate the +IRAF software from the host system. +.PP +We first present an overview of the structure of the IRAF system, naming the +major interfaces and explaining their functions. The system interface is +introduced and the role it plays in the full system is described. +The choice of an implementation language for IRAF is next discussed, +concentrating on the role the language interface plays in addressing the +transportability problem. Next we define the kernel and discuss its attributes. +The conceptual model of the host operating system, or \fBvirtual machine +model\fR assumed by IRAF is presented. The design and functioning of the +kernel is discussed in detail, followed by the detailed specifications +(\fBmanual pages\fR) for the subroutines constituting the actual interface. +.PP +It is not necessary to carefully read the first part of this document +to implement the IRAF system interface for a new host operating system. +The first part of this document (the \fBreference manual\fR) concentrates on +the role the system interface plays in IRAF, the principles underlying +the design of the interface, and on how and why the interface came to be +what it is. The second part of the document (the \fBmanual pages\fR) +presents the detailed specifications for the individual routines comprising +the system interface, and is intended to be self contained. The reference +manual tells what modules the interface consists of, how they work together, +and why they are designed the way they are. The manual pages tell +precisely \fIwhat\fR each routine does, with no attempt to explain why, +or how the routine fits into the system. +.PP +Interfacing to new \fBgraphics devices\fR is likely to be one of the most +difficult problems to be solved in porting the IRAF system. Nonetheless +the graphics device interface is not (or should not be) part of the system +interface, and is not discussed here. Ideally, a graphics device will be +interfaced to IRAF file i/o as a binary file. The device should +have a data driven interface, rather than a control interface, i.e., +all device control should be effected by inserting control instructions in +the data stream transmitted to the device, rather than by calling system +dependent subroutines. The software required to drive the device should +be device independent, table driven, and fully portable. Virtually all +graphics devices either fit this model, or can be made to fit this model +by writing system dependent device drivers to interpret metacode generated +by the high level, machine and device independent software. + +.NH +Structure of the IRAF System Software +.PP +The major components of the IRAF system are +the high level applications and systems \fBprograms\fR and \fBpackages\fR, +the Command Language (CL), also known as the \fBuser interface\fR, +the \fBprogram interface\fR (library procedures called by programs), +and the \fBsystem interface\fR. The system interface is further subdivided +into the \fBkernel\fR and the \fBlanguage interface\fR. +Other system modules not relevant to our discussion are the math library +and the graphics device interfaces. +.PP +The relationship and relative importance of these modules is strongly +dependent upon one's point of view; all points of view are equally valid. +From the point of view of the (highly idealized) user, looking at the +system from the top level, the user is at the center of the system and +is in command. The CL appears to be the central piece of software, and +applications packages are mere extensions of the CL. To the extent that the +user is aware of the host system, the CL appears to be the interface +between the user and the host system. The user expects the system to behave +predictably and reliably, and be responsive to their commands. +To a first approximation, the user does not care what language programs +are written in, or how they are interfaced to the host system (real users, +of course, are often programmers too, and do care). +.PP +From the point of view of the applications programmer, the program they +are writing is at the center of the system and is in command (and indeed +the program does control the system when it is run). The programmer sees +only the abstract problem to be solved and the environment in which the +solution must be constructed, defined by the program interface and the SPP +language. The CL is an abstract data structure, accessed via the CLIO +library in the program interface. The fact that there is a host system +underlying the program interface is irrelevant, and is of no concern to the +applications programmer. As far as the applications programmer is concerned, +the CL could be CL1, CL2, a file, the host OS command interpreter, Forth, +Lisp, or anything else. Ideally, the applications programmer does not know +that the target language of the SPP is Fortran. +.PP +From the point of view of the systems programmer, the kernel is the center +of the system, with the host operating system below and the program interface +above. The system software is subservient to the program which calls it, +and does exactly what it is told to do and nothing more. The CL and the SPP +compiler are \fIapplications programs\fR which use only the facilities +of the program and system interfaces. +.PP +The structural design of the IRAF software is outlined in the figure below. +In general, control and parameters flow downward and data flows both both +downward and upward (mostly upward). The procedures at one level do +not call procedures at a higher level, e.g., kernel routines are +not permitted to call procedures in the program interface libraries. +A procedure may call other procedures at the same level or in the next +lower level, but calls to routines more than one level lower are avoided, +i.e., a program should not bypass the program interface and talk directly +to the kernel. IRAF applications programs \fInever\fR bypass the system +interface to talk directly to the host system. + +.KS +.ce +\fBStructure of the Major IRAF Interfaces\fR +.sp +.nf + \fIuser interface\fR + high level program + \fIprogram interface\fR + \fIsystem interface\fR + host operating system +.fi +.KE + +.PP +This structure chart illustrates only the control hierarchy of the major +interfaces. Additional structure is imposed on the actual system. +Thus, the CL uses only a small portion of the facilities provided by the +program interface, calling external programs to perform most functions. +Few system or applications programs, on the other hand, use the process +control facilities, the part of the program interface most heavily used +by the CL (apart from file i/o). The CL and external applications +programs are minimally coupled, using only human readable text files for +interprocess communication (interprocess communication is implemented as +a special file in IRAF). +.PP +These restrictions tend to result in more functional programs which can be +combined in many ways at the CL level, and which can be used quite +productively without the CL. In particular, any IRAF program can easily +be debugged without the CL, using the host system debugger, and any IRAF +program can be used productively on a system which cannot support the CL. +The system perceived by the user at the CL level can easily be extended +or modified by the user or by a programmer. +.PP +The \fBprocess structure\fR of the IRAF system, with the CL serving +up and networking all processes, while fundamental to the design of +the IRAF system, is not relevant to a discussion of the system interface +because it is all handled above the system interface, i.e., in the machine +independent code. Many quite different process structures are possible +using the one IRAF system interface. Concentration of most or all of the +complex logic required to implement process control, the CL process cache, +the CL/program interface, pseudofiles, multiprocessing, i/o redirection, +exception handling and error recovery, efficient file access, etc., +into the machine \fIindependent\fR code was a major goal of the IRAF +system design. + +.NH +The IRAF System Interface +.PP +As has already been noted, the IRAF system interface consists of both a +procedural interface or kernel (library of Fortran callable subroutines), +and a language interface (preprocessor for Fortran). All communication +with the host system is routed through the kernel, minimizing the machine +dependence of the system and providing scope for machine dependent +optimizations. Similarly, all code other than existing, imported numerical +Fortran procedures is processed through the language interface, further +minimizing the machine dependence of the system. The language interface, +or subset preprocessor (SPP), isolates IRAF programs from the peculiarities +of the host Fortran compiler, provides scope for optimization by making it +possible to take advantage of the nonstandard features of the compiler +without compromising transportability, and does much to correct for the +defects of Fortran as a programming language. +.NH 2 +The Language Interface +.PP +The kernel alone is not sufficient to solve all the problems of +transporting a large software system. There remain many problems associated +with the programming language itself. The many problems of transporting +even purely numerical software are well known and we will not attempt to +discuss them in detail here. The reasoning which led to the decision to +implement the IRAF system in a Fortran preprocessor language (SPP) is less +obvious, and is probably worth recounting. In the process of retracing +the logic which led to the decision to develop SPP, we will come to understand +the purpose of the language interface. +.PP +For some reason programming languages are one of the most controversial +topics in all of programming. No language is perfect, and it is important +to try to objectively gauge the advantages and disadvantages of a language +for a particular application. It is difficult to make such comparisons +without the injection of opinion, and for that we apologize. In the final +analysis the choice of a language is probably not all that important, +provided the cost of the project is minimized and the resultant code is +reliable, portable, readable, and efficient. Only the Fortran and C languages +are discussed; these were the only candidates seriously considered in 1982, +when the decision to implement the IRAF system in a Fortran preprocessor +language was made. +.NH 3 +Fortran +.PP +Consider the typical scientific applications program. Such a program may +need to talk to the CL, access files, access images, access databases, +dynamically allocate memory, generate graphics, perform vector operations, +and so on. These are all functions provided by the program interface. +In addition, in a scientific program there will often be some central +transformation or numerical computation which will almost certainly be +performed by a Fortran subprogram. There is an enormous amount of high +quality Fortran numerical and graphics software available, both commercially +and in the public domain, which IRAF programs must have access to. A third +of the current IRAF system consists of highly portable, numerical (no i/o) +Fortran code, all of it in the public domain. +.PP +To be useful, these general purpose, numerical Fortran subroutines must +be integrated into an IRAF program to perform some specific function. +Here we run into the first serious problem: while Fortran is great for +numerical procedures, it has many defects as a general purpose programming +language. When it comes to complex systems software, Fortran is vastly +inferior to a modern programming language such as C or Pascal. It is +very difficult to implement complex nonnumerical applications in +standard Fortran; the temptation to use a manufacturer's nonstandard +language extensions is often too difficult to resist, and a nonportable +program results. Clearly, Fortran is not the language of choice for the +IRAF system software, in particular the program interface. +.PP +The next question is what to do about the high level part of the scientific +applications program, the part which talks to the program interface, +performs applications specific functions, and eventually calls the numerical +Fortran procedures. In a large scientific package Fortran subprograms +will almost certainly be used somewhere in the package, sometimes quite +heavily, but the bulk of the software is often very similar to systems +software, concerned with allocating resources, managing data structures, +doing i/o of various kinds, and directing the flow of control. +.PP +This is all nonnumerical programming, for which Fortran is poorly suited. +Many Fortran compilers provide nonstandard language extensions which make +it easier to code nonnumerical applications in Fortran. Most applications +programmers and scientists are not intimately familiar with the Fortran +standard, and are more interested in getting a program working than in making +it portable, and nonportable code will result. In any case, programmers +and scientists should not have to struggle to code an application in +a language which was designed for another purpose. We conclude that Fortran +is not the language of choice for general scientific programming within a +complex system. +.PP +A more serious problem with using Fortran for general scientific programming, +however, is that the high level portion of an IRAF scientific program depends +heavily on the capabilities of the program interface. To produce sophisticated +scientific programs with minimum effort we must have a large and powerful +program interface, providing the capabilities most often needed by scientific +programs. We also need a large and powerful program interface for +\fIsystem\fR programs, and in fact the capabilities required by scientific +programs are not all that different than those of system programs, so +clearly it is desirable if the same program interface can support both +kinds of programs. +.PP +The next step is to explore the implications of the heavy dependence of +a systems or scientific program on the program interface. The program +interface is a large interface, consisting of a dozen subsystems containing +several hundred procedures. To have a sophisticated, high level, efficient +interface, it is necessary to use "include" files to parameterize argument +lists, machine parameters, and data structures, we must use dynamic memory +management (pointers) for buffer allocation, and something has to be done +about error handling and recovery. In short, there is a lot of communication +between high level programs and the program interface. This level of +communication is only feasible if the program interface and the high level +program are written in the \fIsame language\fR. Standard Fortran provides +\fIalmost no language support\fR for these facilities. +.sp +.KS +.LP +To summarize our reasoning to this point: +.RS +.IP \(bu +Fortran must be used extensively in the scientific applications. +.IP \(bu +Fortran is not the language of choice for IRAF systems software, +in particular the program interface. +.IP \(bu +Fortran is not the language of choice for general scientific programming, +because most scientific programming is nonnumerical in nature, i.e., +much like systems programming. +.IP \(bu +A single program interface should support both systems programs and +scientific programs. +.IP \(bu +The level of communication required between a high level program and the +program interface requires that both be written in the same language. +.IP \(bu +Standard Fortran provides almost no language support for include files, +globally defined parameters, dynamic memory management and pointers, +data structures, or error recovery. These facilities are required by +both systems and applications software. +.RE +.KE +.NH 3 +Mixing C and Fortran in the same System +.PP +All of our logic to this point forces us to conclude that standard Fortran +just is not suitable for the bulk of the IRAF software. The complexity of +large applications packages, not to mention that of the system software, +would be unmanageable in straight Fortran. Nonetheless we must +still face the requirement that a third or so of the system be existing, +imported numerical Fortran procedures. The obvious question to be answered +is, if Fortran is such a poor choice for the main programming language +of IRAF, can we program in an appropriate modern structured language like C, +calling the numerical Fortran functions and subroutines from within C programs? +.PP +The answer is sure we can, if our target system supports both a Fortran +compiler and a C compiler, but there are serious portability implications. +Furthermore, when examined closely C turns out to be not that great a +language for general scientific programming either, and the defects of C +cannot easily be fixed, whereas those of Fortran can. +.PP +Mixing two different languages in the same program is straightforward on +many operating systems and possible with difficulty on others. No language +standard could attempt to specify how its subprograms would by called by a +completely different, unspecified language, so the one thing we can be +sure of is that the method used will be system dependent. Even on systems +where mixing subprograms from different languages is straightforward, +there are many potential problems. +.PP +Argument lists present many problems. +A potentially deadly problem is the fact that C is a recursive +language while (standard) Fortran is not. C expects the arguments to a +procedure to be passed on the stack, while Fortran was designed with static +storage of argument lists in mind; static storage is somewhat more efficient. +Arguments pushed on a stack are usually pushed in the reverse of the order +used for static allocation. C is call by value; Fortran is call by +reference. Returning a function value is trivial on many systems, +but can be a problem. The Fortran standard requires that a function be +called as a function (in an expression) and not as a subroutine, while +C permits either type of call (all C procedures are functions). +.PP +The method used to implement Fortran character strings is machine dependent; +some machines may pass two items in the argument list to represent a +character string, while others pass only one. On some machines a Fortran +character string is implemented with a count byte, on others an end of string +marker is used. The C standard requires that a character string be delimited +by a trailing zero byte. Thus, on some systems C and Fortran character strings +will be equivalent; programs written on such a system are not portable +to to systems where strings are implemented differently in the two languages. +.PP +Global variables are likely to be a problem, because Fortran common blocks +and C external variables are quite different types of data structures. +Though it would be poor programming practice to use global variables +or common blocks to pass data between C and Fortran procedures, it is +sometimes justified for control parameters, in particular in connection +with error handling. A C include file cannot be accessed from a Fortran +program. +.PP +Finally, external identifiers have a set of problems all of their own. +On some systems, e.g. VMS and AOS, C and Fortran external identifiers are +equivalent, and a procedure is referred to by the same name in both +languages. This makes it easy to mix calls in the two languages, +but can lead to serious name conflicts in libraries. On other systems, +e.g. UNIX, the external identifiers generated for the two languages are +\fInot\fR equivalent, and a C procedure cannot be called from Fortran +unless special provisions are taken (the UNIX Fortran compiler adds an +underscore to all Fortran external identifiers). +.PP +The problem is not that it is hard to mix the two languages, but that +every one of the points mentioned above is a potential machine dependency +which is not covered by any standard. We conclude that mixing C and +Fortran in the same program is inevitably going to be machine dependent. +The problem is controllable only if the number of procedures common to +the two languages is small, or if some automated technique can be developed +for interfacing the two languages. The former solution is straightforward, +the second requires use of some form of \fIpreprocessor\fR to isolate the +machine dependencies. +.PP +C and Fortran should not be mixed in applications software because the +number of Fortran procedures involved is potentially very large. +Since the number of procedures is large, the effort required to port the +applications is also potentially large, and it is the applications which +change most between system releases. If the applications total, say, +200 thousand lines of code, a new release of the system occurs every 3 months, +and it takes two weeks to make all the changes in the high level software +necessary to port it, then we have a bad situation. Porting the system +should ideally be a simple matter of reading a tape, possibly modifying a +config file or two, and running diagnostics. +.PP +C and Fortran should not be mixed in the program interface (in the system +libraries) because it introduces machine dependency into the program +interface where formerly there was none. Less obviously, the problem +discussed in \(sc3.1.2 of communication between modules written in different +languages is very serious. The modules of the program interface use +global \fBinclude\fR files to communicate with one another, and to +parameterized the characteristics of the host system. To ensure a reliable +and modifiable system, there must be only one copy of these include files +in the system. Furthermore, the IRAF error handling scheme, employed +in all code above the kernel, is based on the use of a Fortran common +and to access this from C code would be awkward and would introduce additional +machine dependence. +.PP +The only remaining alternative is to write applications programs entirely in +Fortran and the system software in C, using a small program interface between +the two parts of the system. The problems with this approach were noted in +the last section. The small program interface will inevitably prove too +restrictive, and more and more scientific programs will be written as +"system" programs. These programs will inevitably want to use the numerical +Fortran libraries, and the problem of a large interface between two languages +resurfaces at a different level in the system. +.NH 3 +Critique of C as a Scientific Language +.PP +The major strengths of C as a programming language are that it lends itself +well to structured, self documenting programming, has great expressive power, +strong compile time type checking, tends to result in highly transportable +code (when not mixed with other languages), and is efficient for a large +range of applications. C has been widely used in computer science research +for a decade, and many high quality systems applications are available in +the public domain. +.PP +As a scientific programming language, however, C has serious shortcomings; +C was not designed to be a scientific programming language. The major problem +with C as a scientific programming language is that the scientific community +already has such a large investment in Fortran, and it is difficult to mix +the two languages, as we have already discussed. Upon close analysis we find +that there are additional problems, and these deserve mention. +.PP +C does not support multidimensional arrays. C provides something similar +using pointers, but the feature is really just a side effect of the +generality of pointers, and is not fully supported by the language. +A multidimensional array cannot be passed to a subprogram along with its +dimensions as it can in Fortran. Few C compilers optimize loops, i.e., +evaluate common subexpressions (such as array subscripts) only once, +or remove constant expressions from inner loops. These problems can +be overcome by sophisticated use of pointers, but such hand optimization +of code is extra work and increases the complexity of the code. +On a machine such as the Cray, which has a Fortran compiler that +recognizes vector operations, the problem would be even more severe. +.PP +Char and short integer (8 and 16 bit) expressions are evaluated using +integer instructions (32 bits on a VAX), and single precision floating +expressions are evaluated using double precision instructions. +In a tight loop, this will require the addition of a type conversion +instruction to promote a variable to the higher precision datatype, +and another to convert back to the original datatype after the evaluation. +This alone can double the size and execution +time of a tight loop. In addition, on many machines double precision +floating is not well supported by the hardware and is several times more +expensive than single precision floating. C does not support the +\fBcomplex\fR datatype, important in some scientific applications. +.PP +The C language does not include support for \fBintrinsic\fR and \fBgeneric\fR +functions. These are used heavily in scientific applications. Typed function +calls are required to access the scientific functions, and to perform +exponentiation. I am not aware of any C standard for the scientific functions, +though most systems appear to have adopted the Fortran standard. +The scientific functions, e.g., the trigonometric functions, are evaluated +in double precision. This could lead to a serious degradation +of performance in a large class of applications. +.PP +Despite these quite serious shortcomings, faced with the task of coding a +large and complex application I would prefer C to Fortran, if I had only +the two languages to choose from. Fortunately there is a third alternative, +the use of a Fortran preprocessor. +This approach preserves the best features of Fortran while providing many +of the nice features of a modern language such as C, and in addition allows +us to provide language level support for the IRAF i/o facilities. +The preprocessor approach provides a means of isolating both systems and +applications code from the underlying host compiler, making portability +a realistic goal. +.NH 3 +The IRAF Subset Preprocessor Language +.PP +The Subset Preprocessor language (SPP) is a precursor to a full language +scheduled for development in 1986. The subset language is a fully defined, +self contained language, suitable both for general programming and for +numerical scientific programming. The basic language is modeled after +both C and Ratfor but is a distinct language and should not be confused +with either. SPP is fully integrated into the IRAF system, i.e., +SPP provides substantial language support for the program interface, +the IRAF system itself is written in SPP, and the SPP compiler is an IRAF +applications program written in SPP and using the facilities provided by +the program interface (this is not true of the original preprocessor but +that is not relevant to the design). The syntax of the SPP language is +nearly identical to that of the IRAF command language. +.PP +The SPP language is defined in the document \fIA Reference Manual for the +IRAF Subset Preprocessor Language\fR. The language provides modern +control flow constructs, a wide range of datatypes, support for both system +and user \fBinclude\fR files, a macro definition facility, free format +input, long (readable) identifiers, C-like character constants and strings, +Fortran-like arrays, access to the standard Fortran intrinsic and generic +functions, powerful error handling facilities, and limited but adequate +support for pointers, automatic storage allocation, and data structuring. +Since the target language is Fortran, there is no problem calling Fortran +subprograms from SPP programs or vice versa. We do require, however, +that the Fortran subprograms be purely numerical in nature, i.e., +no Fortran i/o is permitted. +.PP +The function of the preprocessor is to translate an SPP source file +into a highly portable subset of ANSI-66 Fortran. The transformation is +governed by a set of machine dependent tables describing the characteristics +of the host computer and of the target Fortran compiler. These tables +must be edited to port the preprocessor to a new machine; the tables are +ideally the only part of the preprocessor which is machine dependent. +.PP +Even if it should turn out that all of the necessary machine dependence +has not been concentrated into the tables, however, it will often be possible +to port the hundreds of thousands of lines of code in the system by +modifying or adding a few lines of code to the preprocessor, +\fIbecause we have placed an interface between the language of the IRAF system +and that of the host computer\fR. The language interface provides both +a solution to the problem of transporting software between different +contemporary machines, and protection from future changes in the Fortran +language. +.PP +The principal motivation of the preprocessor approach taken in IRAF is +that it provides a real solution to the transportability problem, i.e., +one which does not depend upon perfect programmers. An additional incentive +is that by defining our own language we can provide excellent support the +IRAF i/o facilities, i.e., they can be more than just subroutines and +functions. +.PP +If one has the freedom of being able to modify the programming language +used by applications programs, one can do things that are impractical to +do any other way. In other words, it becomes feasible to solve problems +that were formerly too difficult to address. An example is the use of +lookup tables to implement blocked storage of images, an alternative to +line storage mode which is superior in a large class of image processing +applications. To do this well requires language support, and it is unlikely +that such support will be found in any standard, general purpose programming +language. The SPP is intended partially to provide a path for the future +development of the IRAF system, in the hope that the system will be able +to evolve and be competitive with new systems in coming years. +.NH 3 +Limitations of the Subset Preprocessor +.PP +No compiled language, SPP included, can guarantee transportability. +SPP programs developed on one machine will normally have to tested on +one or more other machines before they can be declared portable. +SPP suffers from many of the same portability problems as standard +Fortran, the main difference being that the output Fortran is very +simple, and nonstandard language extensions are strictly controlled. +Further discussion of the portability aspects of SPP programs is given +in the document \fIIRAF Standards and Conventions\fR. +.PP +We hope to eventually have IRAF running on several types of machines +at the development centers. New releases will be brought up and tested +on several different machines before distribution. +No large software package developed on a single system is portable; +if it is tested on even two different systems, that is much better. +.PP +The SPP language also depends on certain side effects which are not +specified in the Fortran standard, but which many other systems also +depend upon and which are commonly permitted by Fortran compilers. +These include: +.RS +.IP [1] +It must be possible to reference beyond the bounds of an array. +.IP [2] +It must be possible to reference a subarray in a call to a subprocedure, +i.e., "call copyarray (a[i], b, npix)". +.IP [3] +The compiler should permit a procedure to be called with an actual +argument of type different than that of the corresponding dummy argument +(except type \fBcharacter\fR: SPP does not use this type anywhere). +.IP [4] +It must be possible to store a machine address or the entry point +address of an external procedure in an integer variable. +.RE +.LP +Common language extensions used by the preprocessor in output code include +the nonstandard datatypes such as INTEGER*2, any associated type coercion +functions (INT2), and the boolean intrinsic functions if provided by the +target compiler. +.PP +The output of the current preprocessor is ANSI-66 Fortran only to a first +approximation. The following features of Fortran 77 are also used: +.DS +general array subscripts +zero-trip do loop checking +\fBsave\fR statement +\fBentry\fR statement +generic intrinsic functions (\fBmax\fR rather than \fBamax0\fR, etc.) +.DE +All of these extensions are correctable in the preprocessor itself +except the use of the \fBentry\fR statement, if it should ever prove +necessary. + +.NH 2 +Bootstrapping the System +.PP +Since the SPP is fully integrated into the system -- the program interface +is written in SPP and SPP uses the program interface, one may have been +wondering how to go about getting it all set up in the first place. +The basic procedure for porting IRAF to a new system is as follows. +The actual procedure has not yet been fully defined and will be tailored +to the individual target systems, i.e., there will be a separate +installation guide and distribution package for UNIX, VMS, DG/AOS, +and any other systems supported by the IRAF development team. +.RS +.IP [1] +Implement and test the kernel routines. +.IP [2] +Compile the bootstrap SPP, which has already been preprocessed for the +target machine (the datatype used to implement \fBchar\fR must match that +expected by the kernel procedures). +.IP [3] +Edit the system dependent files \fBiraf.h\fR, \fBconfig.h\fR, and the +preprocessor tables to define the characteristics of the host machine. +.IP [4] +Preprocess and compile the production SPP. +.IP [5] +Do a full \fBsysgen\fR of the system libraries (the program interface etc.). +This takes a couple hours on the VAX/UNIX 11/750 development system; get +the config tables right the first time. +.IP [6] +Run diagnostics on the system library procedures. +.IP [7] +\fBMake\fR the applications packages. +.RE +.PP +Once the system has been ported, installing a new release requires only +steps 5 through 7 (sometimes step 4 may also be required), after reading +the distribution tape. + +.NH 2 +The IRAF Kernel +.PP +The IRAF kernel is a set of Fortran callable subroutines. +Every effort has been made to make these primitives as simple as possible; +the kernel primitives provide raw functionality with minimum overhead. +Ideally the kernel primitives should map directly to the kernel of the +host operating system. The implementation of the kernel primitives +should emphasize simplicity and efficiency; these primitives embody the +machine dependence of IRAF and there is little reason to try to make them +machine independent. Critical routines should be coded in assembler +if a substantial gain in efficiency will result. In IRAF, \fIall\fR +communication with the host system is routed through the kernel, +so kernel efficiency is paramount. +.PP +With very few exceptions, applications programs and high level systems +modules do not talk directly to the kernel. The kernel primitives are +called only by the routines comprising the core of the IRAF \fBprogram +interface\fR, the lowest level of the machine independent part of the +IRAF system. The core of the program interface, i.e, file i/o, process +control, exception handling, memory management, etc., combined with the +kernel, constitute a \fBvirtual operating system\fR, the heart of IRAF. +The virtual operating system approach is the key to maximizing +transportability without sacrificing either functionality or efficiency. +.PP +Ideally all of the machine dependence of the IRAF system is concentrated +into the kernel, which should be as small and efficient as possible while +offering sufficient raw functionality to support a large and sophisticated +system. In practice it is possible to come quite close to this ideal, +although the range of host systems on which the kernel can be implemented is +finite, being inversely proportional to the richness of function +provided by the kernel. We did not consider it acceptable to provide +transportability at the expense of a restrictive and limited program +interface, so IRAF has a large and quite sophisticated program interface +which depends upon a sizable kernel. The IRAF kernel embodies much of +the functionality provided by the typical minicomputer operating system, +and should be implementable on a wide range of such systems. +.NH 2 +The Virtual Machine Model +.PP +The virtual machine model is the conceptual model of the host machine assumed +by the kernel. The difficulty of implementing the kernel on a given host +depends on how closely the model matches the host operating system. In general, +the older large batch oriented machines do not match the model well, +and it will be difficult to port the full IRAF system to such a machine. +At the other end of the scale are the small 16 bit minicomputers; these +machines do not have a sufficiently large memory addressing range to run IRAF. +In the middle are the multiprocessing, multiuser, terminal oriented supermicro +and minicomputers with large address spaces and large physical memories: +these are the machines for which the IRAF system was primarily designed. +.PP +Our intent in this section is to summarize the most important features of +the virtual machine model. Much of the material given +here will be presented again in more detail in later sections. The design +of the IRAF system is such that there are actually two distinct virtual +machine models, the full model and a subset model. The subset model assumes +little more than disk file i/o, and will be presented first. +.NH 3 +The Minimal Host Machine +.PP +Even though it may be difficult to run the \fIfull\fR IRAF system on a large +batch oriented (timesharing) machine, it should still be possible to run most +of the science software on such a system. The IRAF system was designed such +that the science software is placed in separate processes which can be run +independently of the CL and of each other. +These processes actually use only a portion of +the full system interface; most of the system and device dependence is in +the CL and the graphics control processes, i.e., in the user interface, +which is what one has to give up on a batch machine. +.PP +On the typical batch oriented timesharing system, the IRAF applications +programs would be run under control of the host job control language, +reading commands and parameters from an input file, and spooling all +textual output into an output file. The IRAF command language would not +be used at all; this mode of operation is built into the present system. +Little more than file i/o is required to run a program on such a system, +though dynamic memory allocation is highly desirable. Exception handling +and error recovery can be done without if necessary; process control is not +used by applications processes. The i/o subsystems required by an +applications program are CL i/o, image i/o, and database i/o, each of +which is built upon file i/o. +.PP +Applications programs that produce graphics write device independent +metacode instructions, rather than talking directly to a graphics device, +so a graphics device interface is not required to run an applications +program. Graphics output can be discarded, or the output file can be +postprocessed to generate graphics hardcopy. +Graphics input (cursor readback) is parameterized, so any program that +normally reads a cursor can just as easily read coordinates directly from +the input file. +.PP +All of the software in the science modules is Fortran or Fortran based +(C is used only in the CL and in some kernels), so only a Fortran compiler +is required. A C compiler is currently required to compile the command +language, though it is not necessary to have such a compiler on every +physical machine. We can compile the CL on one machine and distribute +the object code or executables to other machines of the same type; this +will be done, for example, for VAX/VMS. +.PP +If it is necessary to port IRAF to a machine which +does not have a C compiler, it is feasible to code a basic, stripped down +command language in SPP in a few weeks. A command language capable of +executing external processes, parsing argument lists, managing parameter +files, and redirecting i/o is sufficient to run most of the IRAF software, +the main loss being CL scripts. Virtually all of the system and science +software is external to the CL and would be unaffected by substitution of +a new CL. +.NH 3 +The Ideal Host Machine +.PP +The minimal IRAF target machine therefore need offer little more than +file i/o and a Fortran compiler. One would have to do without a nice user +interface, but it should still be possible to do science in the fashion it +has traditionally been done on such machines. +Fortunately, however, minicomputers of modern design are widely available today +and will be increasingly available in the future. We expect that most IRAF +implementations will be ports of the full system onto a modern supermicro or +minicomputer. Such a host system should provide the following general classes +of facilities: + +.DS +.RS +.IP \(bu +file i/o, file management +.IP \(bu +process control +.IP \(bu +exception handling +.IP \(bu +memory management +.IP \(bu +date and time +.IP \(bu +bit and byte primitives +.RE +.DE + +Most of the complexity of the kernel is in file i/o, process control, +and exception handling. File management (file deletion, renaming, etc.) +is straightforward on virtually any system. Memory management can be +some work to implement, but many systems provide dynamic allocation +primitives in which case the interface is trivial. The date and time +facilities assume that the host provides some sort of facilities for +reading the clock time (ideally as a high precision integer) and the cpu +time consumed by a process. The bit and byte primitives do not actually +do any i/o, and are included in the interface primarily because Fortran +is difficult to use for such applications. +.PP +The IRAF \fBfile i/o\fR system deals with two types of files. +\fBText files\fR contain only character data, are read and written in +units of records (lines of text), and are maintained in a such a form +that they can be edited with a host editor. +Writing may occur only at the end of file. +Reading is normally sequential, but seeking to the beginning of a line +prior to a read is permitted. The user terminal is interfaced +as a text file, opened by the IRAF main at process startup. Terminal i/o +is generally line oriented, but character at a time input is used by some +programs, and the system expects to be able to send control codes to the +terminal. Text files are accessed synchronously. Character data is always +ASCII within IRAF, with the kernel routines mapping to and from the host +character set (e.g. EBCDIC). +.PP +The second file type is the \fBbinary file\fR. A binary file is an +extendible array of machine bytes. There are two types of binary files, +\fBblocked\fR (random access) binary files and \fBstreaming\fR (sequential) +binary files. Transfers to and from blocked binary files are +always aligned on device block boundaries and are asynchronous. +The size of a transfer may be any integral multiple of the device block +size, up to a device dependent maximum transfer size. +The IRAF file i/o system (FIO) assumes that a file can be extended by +overwriting the end of file, and that a partial record can be written at +the end of file without the host filling the record to the size of a +device block. The device block size is assumed to be device dependent. +Devices with different block sizes may coexist on the same system. +.PP +Streaming binary files are for devices like magtapes and the interprocess +communication (IPC) facilities. Seeks are not permitted on streaming files, +and there are no restrictions on block size and alignment of transfers, +other than an upper limit on the transfer size. The ideal host system will +initiate an asynchronous transfer from either type of binary file directly +from the mass storage device into the buffer pointed to by the kernel +(or vice versa). +.PP +The model does not assume that the host system provides device independent +file i/o. A different set of kernel routines are provided for each device +interfaced to FIO. On a system which does provide device independent i/o +the kernel routines may be coded as calls (or multiple entry points) to a +single set of interface subroutines. Standard file devices include disk +resident text and binary files, the IPC facilities, magtapes, line printers, +and (currently) the image display devices and the batch plotters. +The special devices are normally interfaced to FIO as binary files. +The IPC files are streaming binary files. +.PP +Although it is highly desirable that the host provide a hierarchical files +system, it is not required. IRAF tends to generate and use lots of small files. +FIO maps virtual filenames into machine dependent filenames, and will pass +only filenames acceptable to the host system to the kernel routines. +It should be possible to read filenames from a host directory, +determine if a file exists and is accessible, +delete a file, and rename a file. The model assumes that there are two types +of filenames: files within the current directory (directory name omitted), +and files within a particular directory, and that both types of files can be +simultaneously accessed. The directory name is assumed to be a string which +can be prepended to the filename to produce a pathname. Multiple versions +of a file are neither assumed nor supported. +.PP +\fBMagnetic tape\fR devices are interfaced as streaming binary files. +A magnetic tape is either empty or consists of one or more files, +each delimited by an end of file (EOF) mark, with an end of tape (EOT) +mark following the last file on the tape. +The kernel routine opens the device positioned to +the first record of a specific file or EOT. Tape density may be manually +set on the device, or may be set at allocate time or at open time (the IRAF +software will work regardless of which method is used). A separate file +open is required to access each file on the tape, i.e., FIO will not try +to read or write beyond a tape mark. +.PP +Record and file skipping primitives are desirable for tape positioning in +the kernel open procedure, but are not assumed by the model. Tape records +may be variable in length. No attempt will be made to position the tape +beyond EOT. FIO knows nothing about labeled tapes or multivolume tapes; +if it is necessary to deal with such tapes, the details should be handled +either by the host system or by the kernel routines. All IRAF programs +which read and write magtape files can also be used to read and write disk +files. +.PP +The virtual machine model assumes that a parent process can spawn one or +more child \fBsubprocesses\fR, to execute concurrently with the parent, +with bidirectional streaming binary communications channels connected to +the parent. The IPC facilities are used only to communicate with child +processes; the model does not assume that any one process can talk to any +other process. The model assumes that an IPC channel can only be opened +when a child process is spawned; the two functions are bound into the +same kernel primitive. A child process is assumed to inherit the same +current working directory as the parent. The child is not assumed to +inherit environment or logical name tables, open files, or the parent's +address space. +.PP +\fBException handling\fR is very machine dependent and is difficult to model. +Fortunately the IRAF system will probably still be usable even if the host does +not entirely fit the model, since exceptions are not the norm. +A parent process is assumed to be able to interrupt a child process. For error +recovery and process shutdown to occur properly control should transfer +to an interrupt handler in the child process when the interrupt signal is sent. +.PP +All exceptions occurring during execution of a process should be caught by +the kernel and mapped into the exception classes assumed by the kernel. +The model assumes that all exceptions can be caught, that control can be +transferred to an exception handler, and that execution can resume following +processing of the exception. The host and the kernel should let the high +level software process all exceptions and handle error recovery. +.PP +In summary, IRAF can be used to do science on a limited, batch oriented host +machine, at the expense of a limited user interface and considerable hacking +of the released system. The ideal host system will provide a hierarchical +files system, large asynchronous file transfers directly into process memory, +multiprocessing, efficient binary interprocess communication facilities, +dynamic memory management facilities, and high level exception handling. + +.NH +A Reference Manual for the IRAF Kernel +.PP +The kernel is a set of SPP or Fortran callable subroutines. The syntax +and semantics of these routines, i.e., the external specifications of the +interface, are the same for all machines. The code beneath the interface +will in general be quite different for different operating systems. +Any language may be used to implement the kernel routines, provided the +routines are Fortran callable. Typed functions are avoided in the kernel +where possible to avoid the problems of passing a function value between +routines written in different languages. +.PP +The method chosen to implement a kernel routine for a given host should be +dictated by the characteristics of the host and by the external specifications +of the routine, not by the method chosen to implement the same kernel +routine for some other host. Nonetheless it is often possible to reuse +code from an existing interface when coding an interface for a new host. +This occurs most often in the numerical procedures, e.g., the bit and byte +primitives. Furthermore, some routines are placed in the kernel only +because they are potentially machine dependent; these routines need only be +examined to see if they need to be modified for the new host. +.PP +The kernel routines are found in the \fBOS package\fR, the interface to the +host Operating System (OS). The OS package is maintained in the logical +directory \fBsys$os\fR, and the kernel routines are archived in the +system library \fBlib$libos.a\fR. + +.NH 2 +Conventions +.PP +At the kernel level, data is accessed in units of \fBmachine bytes\fR. +The size of a machine byte in bits and the number of bytes per SPP data +type are both parameterized and are assumed to be machine dependent. +It is fundamentally assumed throughout IRAF that an integral number of bytes +will fit in each of the language datatypes. Conversion between byte units +and SPP units is handled by the high level code; the kernel routines deal +with data in byte units. +.PP +All offsets in IRAF are \fBone-indexed\fR, including in the kernel routines. +Thus, the first byte in a file is at offset 1, and if the device block size +is 512 bytes, the second device block is at offset 513. The first bit in a +word is bit number 1. Many operating systems employ zero-indexing instead +of one-indexing, and the implementor must be especially careful to avoid off +by one errors on such systems. +.PP +All \fBcharacter strings\fR are packed in the high level code before +transmission to the kernel, and strings returned by the kernel are unpacked +by the high level code into SPP strings. The packed string is passed in an +array of SPP type \fBchar\fR. +The format of a packed string is a sequence of zero or more characters +packed one character per byte and delimited by end-of-string (EOS). +SPP strings are ASCII +while packed strings use the host character set. The EOS delimiter occupies +one character unit of storage but is not counted in the length of the string. +Thus if a kernel routine returns a packed string of at most \fImaxch\fR +characters, up to \fImaxch\fR characters are returned followed by an EOS. +.PP +Kernel procedures should call only other kernel procedures or the host +system. Calls to program interface routines are forbidden to avoid problems +with \fBreentrancy\fR and backwards library references (and because code which +references upwards is usually poorly structured). A program crash should +never occur as a result of a call to a kernel procedure. Illegal operations +should result in return of an error status to the routine which called the +kernel procedure. The SPP error handling facilities must not be used in +kernel procedures, even if a kernel procedure can be coded in SPP. +This is because the high level code does not error check kernel procedures, +and because printing an error message involves calls to FIO and possible +reentrancy. +.PP +Any kernel procedure which can fail to perform its function returns an +integer status code as its final argument. Other integer codes are used +to parameterize input arguments, e.g., the file access modes. Codes which +are used only in a particular procedure are documented in the specifications +for that procedure. The codes used extensively in the kernel are shown in +the table below. The magic integer values given in the table must agree +with those in the SPP global include file \fBiraf.h\fR. +.sp 0.08i +.TS +center box; +cb s s +ci | ci | ci +l | c | l. +Kernel Constants +_ +name value usage += +ERR \(mi1 function was unsuccessful +EOS '\\\\0' end of string delimiter +OK 0 function successfully completed +NO 0 no (false) +YES 1 yes (true) +.TE +.sp 0.08i +.PP +The names of kernel routines never exceed six characters, and only alphanumeric +letters are used. The Fortran implicit datatyping convention (I through N for +integer identifiers) is not used in IRAF. The IRAF naming convention is +package prefix plus function plus optional type suffix letter. This convention +is little used in the kernel because there are few functions, but it does occur +in a few places, e.g. the bitwise boolean functions \fBand\fR and \fBor\fR. +The procedure naming convention and other IRAF conventions are further +discussed in the document \fIIRAF Standards and Conventions\fR. + +.NH 2 +Avoiding Library Conflicts +.PP +Only documented OS interface routines should be callable from the high level +SPP and Fortran code. If at all possible, all non-interface kernel +subprocedures and host system calls referenced in the kernel should be +named such that they are not Fortran callable. All external identifiers +used in IRAF code adhere to the Fortran standard, i.e., at most six +alphanumeric characters, the first character being a letter. Non-interface +kernel procedures are guaranteed not to cause library conflicts with the +high level software provided they are not legal Fortran identifiers. +.PP +For example, on UNIX systems, the Fortran compiler appends a hidden underscore +character to all Fortran external identifiers. No standard C library or system +procedures have names ending in an underscore, so library conflicts do not +arise. On a VMS system, the VMS system service procedures all have external +names beginning with the package prefix "sys$", hence the system service +procedures are guaranteed not to cause library conflicts with standard Fortran +identifiers. +.PP +If there is no way to avoid library conflicts by using a naming convention +at the kernel level, it is possible to modify the SPP to map identifiers in +a way which avoids the conflicts (e.g., by use of \fBdefine\fR statements +in the global include file \fBiraf.h\fR). This approach is less desirable +because it involves modification of high level code, and because it does +nothing to avoid library conflicts with Fortran subprograms which are not +preprocessed. Furthermore, it is important that the mapping of SPP +identifiers to plain vanilla Fortran identifiers be simple and predictable, +to ease interpretation of host Fortran compiler error messages, and to make +the host system debugger easy to use with SPP programs. + +.NH 2 +File I/O +.PP +The file i/o subsystem is the most critical i/o subsystem in IRAF. +No process can run without file i/o, and the high level system code and +applications programs are all built upon file i/o. Many programs are i/o +intensive, and an efficient file i/o system is vital to the functioning +of such programs. The high level of functionality and device independence +provided by the IRAF file i/o subsystem is critical to minimizing the +complexity and maximizing the flexibility of all code which uses file i/o. +In particular, the database and image i/o subsystems are heavily dependent +upon file i/o; the IRAF file i/o system was designed expressly to provide +the kinds of facilities required by these and similar applications. +.PP +Most of the complexity of the file i/o system is in the machine independent +FIO interface. FIO handles all buffer allocation and management including +management of buffer caches, record blocking and deblocking, and read ahead +and write behind. FIO makes all files and file storage devices look the same, +and allows new devices to be interfaced dynamically at run time without +modifying the system. The database facilities rely on FIO for efficient +random file access, which requires use of a buffer cache to to minimize file +faults. Image i/o relies on FIO for efficient sequential file access, +which requires asynchronous i/o and large buffers. +.PP +Kernel support for file i/o consists of a few simple file management +primitives, e.g. for file deletion and renaming, plus the "device drivers" for +the standard devices. There are two basic types of files, \fBtext files\fR +and \fBbinary files\fR. The device driver for a text device consists of +8 subroutines; the driver for a binary device consists of 6 subroutines. +A different set of driver subroutines are required for each device interfaced +to FIO. All system and device dependence is hidden within and beneath these +subroutines. Most devices are interfaced to FIO as binary files. Kernel +device drivers are closely matched in capabilities to the actual device +drivers found on many systems. +.PP +The file access modes, device parameters, and other codes used to communicate +with the kernel file i/o primitives are summarized in the table below. + +.TS +center box; +cb s s +ci | ci | ci +l | c | l. +FIO Kernel Constants +_ +name value usage += +BOF \(mi3 beginning of file +EOF \(mi2 end of file +_ +READ_ONLY 1 file access modes +READ_WRITE 2 +WRITE_ONLY 3 +APPEND 4 write at EOF +NEW_FILE 5 create a new file +_ +TEXT_FILE 11 file types +BINARY_FILE 12 +_ +FSTT_BLKSIZE 1 device block size +FSTT_FILSIZE 2 file size, bytes +FSTT_OPTBUFSIZE 3 optimum transfer size +FSTT_MAXBUFSIZE 4 maximum transfer size +.TE +.sp 0.08i + +.NH 3 +Text Files +.PP +A \fBtext file\fR is a sequence of lines of text, i.e., of characters. +Examples of text files are parameter files, list files, program source files, +and \fBterminals\fR. Although it is not strictly required, it is desirable +that text files be maintained in such a form that they can be accessed by the +host system file editor and other host utilities. The principal function +of the text file primitives is to convert text data from the host format +to the IRAF internal format, and vice versa. +.PP +The physical representation of a text file is hidden beneath the kernel +interface and is not known to an IRAF program. +The logical (IRAF) and physical (host system) representations of a text +file will in general be quite different. On some systems +it may be possible to represent a single logical text file in any of several +different physical representations, and the kernel primitives will have to +be able to recognize and deal with all such representations. On other systems +there may be only a single physical format for text files, or there may be no +distinction between text files and binary files. +.PP +The \fBlogical representation\fR of a text file is a sequence of lines of text. +Each line of text consists of zero or more ASCII characters terminated by +the \fBnewline\fR character. The newline character defaults to ASCII LF +(linefeed), but some other character may be substituted if desired. +IRAF assumes that any ASCII character can be stored in a text file; +in particular, case is significant, and control characters may be embedded +in the text. There is no fixed limit on the number of characters per line. +It may not be possible to edit a file containing arbitrarily long lines +or embedded control characters with some host system editors, but such files +are rare. +.PP +Character data is represented within IRAF with the SPP datatype \fBchar\fR. +On many systems, char is implemented as the (nonstandard) Fortran datatype +INTEGER*2. The read and write primitives +for a text file must convert SPP arrays of ASCII char to and from the +internal host representation. This conversion usually involves a packing +or unpacking operation, and may also involve conversion between ASCII and +some other character set, e.g., EBCDIC. Regardless of the precision of the +datatype used to implement char on a given host system, characters are +limited to ASCII values, i.e., 0 to 127 decimal (negative valued characters +are permitted only in SPP variables and arrays). +.PP +The kernel primitives used to access ordinary disk resident text files, +i.e., the "device driver" primitives for an ordinary text file, are shown below. +The calling sequences for other text file devices are identical if the +two character device code for the new device is substituted for the "tx" +suffix shown. A device driver is installed in FIO by passing the entry +points of the subroutines to FIO with \fBfopntx\fR or \fBfdevtx\fR; +the entry point addresses of the 8 subroutines are saved in the FIO device +table. +.PP +The \fBzopntx\fR primitive opens a text file or creates a new one, +returning the channel number (an integer magic number) or ERR as +its status value. +All subsequent references to the file are by this channel number. +The file access modes are listed in the table in \(sc4.3. +Output text is assumed to be buffered; \fBzflstx\fR is called by FIO to flush +any buffered output to the device when the file is closed, or when file output +is flushed by the applications program. +.sp 0.08i +.TS +center; +cb s +n l. +Text File Primitives +.sp +zopntx \&(osfn, mode, chan) open or create a textfile +zclstx \&(chan, status) close a textfile +zgettx \&(chan, text, maxch, status) get next record +zputtx \&(chan, text, nchars, status) put next record +zflstx \&(chan, status) flush output +znottx \&(chan, loffset) note file position +zsektx \&(chan, loffset, status) seek to a line +zstttx \&(chan, param, lvalue) get file status +.TE +.sp 0.08i +.PP +If the physical file is record oriented, there will normally be one newline +delimited line of text per record. A sequence of characters output with +\fBzputtx\fR is however not necessarily terminated with a newline. +The \fBzputtx\fR primitive is called to write the FIO output buffer when +(1) newline is seen, (2) the buffer fills, (3) the output is flushed, +or (4) the file is closed. Thus if a very long line is written, several +calls to \fBzputtx\fR may be required to output the full line. Conversely, +if the input record contains more than \fImaxch\fR characters, \fBzgettx\fR +should return the remainder of the record in the next call. In no case should +more than maxch characters be returned, as the output buffer would be overrun. +.PP +A \fBzgettx\fR call with \fBmaxch=1\fR has a special meaning when the input +device is a terminal. This call will switch the terminal from line mode to +\fBcharacter mode\fR, causing \fBzgettx\fR to return immediately each time a key +is typed on the terminal. This highly interactive mode is useful for programs +like screen editors, and is discussed further in \(sc4.3.4.1. Character mode +applies only to terminal input; if individual characters are to be output, +the output must be flushed after each character is written. +.PP +Text files are virtually always accessed sequentially. Writing is permitted +only at end of file (EOF). A file opened for reading is initially positioned +to the beginning of file (BOF). Seeking to the beginning of any line in the +file is permitted prior to a read. The seek offset must be BOF, EOF, or an +offset returned by a prior call to the \fBznottx\fR primitive, which returns +the file offset of the last text line read or of the next text line to be +written. Seeks on text files are restricted to lines; seeks to individual +characters are not permitted. The long integer file offset returned by +\fBznottx\fR is a magic number, i.e., the value is assumed to be machine +dependent. +.NH 3 +Binary Files +.PP +A \fBbinary file\fR is an extendible array of bytes accessed in segments the +size of a device block. The principal difference between a text file and +a binary file is that character data is converted in some machine dependent +fashion when a text file is accessed, whereas data is copied to and from +a binary file without change. A second difference is that only binary files +are randomly accessible for both reading and writing at any offset. +Binary files are used to implement interprocess communication (IPC) files, +database files (datafiles), picture storage files (imagefiles), and so on. +Special devices such as magtape, the line printer, image display devices, +and process memory are interfaced to FIO as binary files. +.PP +The fundamental unit of storage in a binary file is the \fBmachine byte\fR. +The number of bits per byte is presumed to be machine dependent, although +IRAF has thus far been used only on machines with 8 bit bytes. IRAF assumes +only that there are an integral number of bytes in each SPP or Fortran datatype. +The SPP datatype \fBchar\fR should not be confused with the machine byte. +The char is the fundamental unit of storage in SPP programs; the number +of machine bytes per SPP char is greater than or equal to one and is given +by the machine dependent constant SZB_CHAR, defined in \fBiraf.h\fR. +Though the distinction between chars and machine bytes is important in the +high level system code, it is of no concern in the kernel since the kernel +routines access binary files only in units of machine bytes. +.PP +Binary files are further differentiated into \fBblocked\fR (random access) +binary files and \fBstreaming\fR (sequential) binary files. The most +common blocked binary file is the binary random access disk file. +IPC files and magtape files are typical streaming binary files. +The \fBdevice block size\fR is used to differentiate between blocked and +streaming binary files. A device with a block size greater than or equal +to one byte is understood to be blocked, whereas a device with a block size +of zero is understood to be a streaming file. Transfers to and from blocked +devices are always aligned on device block boundaries. There are no alignment +restrictions for streaming files. +.sp 0.08i +.TS +center; +cb s +n l. +Binary File Primitives +.sp +zopnbf \&(osfn, mode, chan) open or create a binary file +zclsbf \&(chan, status) close a binary file +zardbf \&(chan, buf, maxbytes, loffset) initiate a read at loffset +zawrbf \&(chan, buf, nbytes, loffset) initiate a write at loffset +zawtbf \&(chan, status) wait for transfer to complete +zsttbf \&(chan, param, lvalue) get file status +.TE +.sp 0.08i +.PP +The kernel primitives used to access ordinary disk resident binary files, +i.e., the "device driver" primitives for a binary file, are shown above. +The calling sequences for other binary file devices are identical if the +two character device code for the new device is substituted for the "bf" +suffix shown. The device driver for a binary file is particularly simple +since all buffering is performed at a high level. A binary file is opened +or created with \fBzopnbf\fR, which returns the channel number or ERR as +its final argument. All subsequent references to the file are by channel +number. +.PP +The kernel primitives for a binary file closely approximate the functionality +of the typical host system device driver. +Ideally an asynchronous kernel read or write +to a binary file will translate into a DMA transfer directly from the data +buffer to the device, or vice versa. FIO guarantees that only a single transfer +will be pending on a channel at a time, i.e., that a new i/o request will not be +issued until any previous transfer is completed. There is no \fBseek\fR +primitive for binary files since the absolute file offset is specified in +a read or write request (the file offset argument should be ignored for a +streaming file). There is no \fBnote\fR primitive since there is no concept +of the current file position for a binary file at the kernel level. +.PP +The \fBzardbf\fR and \fBzawrbf\fR (asynchronous read and write) primitives +should initiate a transfer and return immediately. No status value is +returned by these primitives: rather, the number of bytes read or written +or ERR is returned in the next call to \fBzawtbf\fR (asynchronous wait). +A byte count of zero on a read indicates end of file. It is not an error +if fewer than \fBmaxbytes\fR bytes can be read; \fBzardbf\fR should return +immediately with whatever data it was able to read, rather than try to +read exactly maxbytes bytes. In no case should more than maxbytes bytes +be returned, as this would overflow the caller's buffer. If the size of the +input block or record is greater than maxbytes bytes when reading from a +streaming file, data is assumed to be lost. An attempt to read or write +before BOF or after EOF is illegal and will be caught by FIO. +.PP +The status value ERR should be returned for all illegal requests or +i/o errors. FIO will always call \fBzawtbf\fR after a transfer for +synchronization and to check the status value. Repeated calls to \fBzawtbf\fR +after a single i/o transfer should continue to return the same status. +Errors should not "stick", i.e., an error status should be cleared when +the next transfer is initiated. +.PP +It is fundamentally assumed that it is possible to extend a file by +overwriting EOF in a call to \fBzawrbf\fR. It is further assumed that the +last block in a file need not be full. For example, suppose the device +block size is 512 bytes, the FIO buffer size is 512 bytes, and we are +writing to a file 1024 bytes long. We write 18 bytes at file offset 1025, +the fourth block in the file, and then close the file. +When the file is subsequently reopened, FIO will call \fBzsttbf\fR to get +the file size, which should be 1042 bytes. If the program calling FIO +then attempts to write 50 bytes at EOF, FIO will call \fBzardbf\fR to initiate a +read of 512 bytes at file offset 1025, and a subsequent call to \fBzawtbf\fR +will return a byte count of 18. FIO will copy the 50 bytes into the buffer +starting at byte offset 19 and eventually write the buffer to the file +at file offset 1025, overwriting EOF and extending the file. +.PP +.NH 3 +Specifying Device Parameters +.PP +Each device interfaced to FIO has a unique status primitive callable while +the file is open to obtain values for the device parameters. +These parameters reflect the characteristics of the \fIdevice\fR +or \fIfilesystem\fR on which the file is stored. +The status primitives for disk resident text and binary +files are \fBzstttx\fR and \fBzsttbf\fR. These primitives are the only file +status primitives available for a file while it is open; \fBzfinfo\fR is not +called to get information on open files. +.PP +The device block size and file size parameters are currently not used for +text files, although they are read when the file is opened. +The file size parameter is not needed for text files because \fBzsektx\fR +is used to seek to EOF on a text file. All four parameters are required for +binary files. +.sp +.in 1.0i +.ti -0.5i +FSTT_BLKSIZE +.sp 0.04i +The device block size in bytes (binary files only). A block size of zero +indicates a streaming device; no alignment checking will be performed, +and only sequential i/o will be permitted. +If the block size is greater than or equal to one, the device is understood +to be a random access binary file with the indicated device block size. +File reads and writes will be aligned on device block boundaries, +although if the block size is given as 1 byte (e.g., if process memory is +accessed as a file) there is effectively no restriction on block alignment. +.sp +.ti -0.5i +FSTT_FILSIZE +.sp 0.04i +The file size in bytes; zero should be returned for a new file. +Not used for streaming files. FIO will ask for this once, when the file +is opened, if the file is a regular disk resident binary file. +Thereafter FIO keeps track of the file size itself. If necessary the +kernel can get the file size from the host system before opening the file. +.sp +.ti -0.5i +FSTT_OPTBUFSIZE +.sp 0.04i +The optimum transfer or buffer size for "normal" file access. This parameter +defines the default FIO buffer size for both read and write access. +The optimum transfer size typically depends on the characteristics of +the i/o system of the host, and may also depend on the characteristics +of the device or of the file system on which the file is found. +For example, the optimum transfer size of a file system configured for +the storage of images (large files) may well be larger than that for a +file system configured for general use (predominantly small files). +.sp +.ti -0.5i +FSTT_MAXBUFSIZE +.sp 0.04i +The maximum permissible transfer size in a single read or write request. +This parameter determines the maximum FIO buffer size, and hence the +maximum size of a FIO read or write request. +.in -1.0i +.sp +.PP +The optimum buffer size for magtape devices is usually different (larger) +for reading than for writing; the default magtape buffer sizes are set by +system tuning parameters in \fBconfig.h\fR (\(sc6). FIO automatically +adjusts the internal FIO buffer size for a file to be an integral multiple +of the device block size. The FIO buffer size may be further controlled +at a high level by advising FIO that i/o to a file is to be highly random +or highly sequential. With all this going on in the high level code, +it is inadvisable to try to tune the system by adjusting the device +parameters. The file status parameters should reflect the physical +characteristics of the device or files system on which the file is resident. +.PP +For example, consider a random access binary disk file on a UNIX system. +The device block size will typically be 512 bytes and is generally wired +into the status primitive as a constant. The file size may be obtained +at any time from the inode for the file. The optimum buffer size is +512 bytes on V7 UNIX, 1024 bytes on 4.1BSD, and dependent on how a filesystem +is configured on 4.2BSD. There is no maximum transfer size for a disk +file, so the maximum integer value is returned. If the file happens to +be a pipe, the block size would be given as 0, the file size is ignored, +the optimum transfer size is arbitrary, e.g. 2048 bytes, and the maximum +transfer size is typically 4096 bytes. +.NH 3 +Standard File Devices +.PP +The kernel routines for the ordinary text and binary disk files have +already been presented. An arbitrary number of other devices may be +simultaneously interfaced to FIO. The standard devices are disk, memory, +terminal, line printer, IPC, magtape, and the pseudofiles (STDIN, STDOUT, +etc.). The memory and pseudofile interfaces are machine independent and +will not be discussed here. The IRAF development system currently also +supports file interfaces for image display devices and plotters, but the +graphics device interfaces are being redesigned to use the ISO standard +Graphical Kernel System (GKS) graphics device interface, so we will not +discuss those devices here. +.PP +Each device is interfaced with a distinct set of kernel interface routines +to give the implementor maximum scope for tailoring the interface to a +device. If the host system provides device independent file i/o at a low level, +it may be possible to use the same kernel routines for more than one device. +For example, the text file driver might be used for both disk resident text +files and terminals, and the IPC, magtape, and line printer devices might +resolve into calls to the kernel routines for a disk resident binary file. +This approach offers maximum flexibility for minimum effort and should be +followed if the host system permits. On the other extreme, a host might +not have something fundamental like IPC channels, and it might be +necessary to build the driver from the ground up using non-file resources +such as shared memory. +.NH 4 +The User Terminal +.PP +Terminal devices are interfaced to FIO as text files. The device code +is "ty". The driver subroutines are shown below. The legal access +modes for a terminal are READ_ONLY, READ_WRITE, WRITE_ONLY, and APPEND. +Seeking to offsets other than BOF or EOF is illegal; seeks to BOF and +EOF should be ignored. +.sp 0.08i +.TS +center; +cb s +n l. +Terminal Driver +.sp +zopnty \&(osfn, mode, chan) open a terminal file +zclsty \&(chan, status) close a terminal +zgetty \&(chan, text, maxch, status) get next record +zputty \&(chan, text, nchars, status) put next record +zflsty \&(chan, status) flush output +znotty \&(chan, loffset) not used +zsekty \&(chan, loffset, status) not used +zsttty \&(chan, param, lvalue) get file status +.TE +.sp 0.08i +.PP +When an IRAF process is run from the CL it communicates with the CL via +IPC files; when not run from the CL, an IRAF process assumes it is talking +to a terminal. The terminal driver is therefore linked into every IRAF main. +The main assumes that the terminal is already open when an IRAF process +starts up; the \fBzopnty\fR and \fBzclsty\fR routines are used only when +a terminal is directly accessed by a program. +.PP +If possible the terminal driver should be set up so that input can come +from either a terminal or an ordinary text file, allowing IRAF processes +to be run in batch mode taking input from a file. On a batch oriented +system the "terminal" driver would be the same as the text file driver, +and input would always come from a file. +.PP +Terminal input is normally line oriented. The host terminal driver +accumulates each input line, handling character, word, and line deletions and +other editing functions, echoing all normal characters, checking for control +characters (e.g. interrupt), and returning a line of text to \fBzgetty\fR +when carriage return is hit. The line returned by \fBzgetty\fR to the +calling program should always be terminated by a \fBnewline\fR. +.PP +If \fBzgetty\fR is called with \fBmaxch=1\fR the terminal is put into raw +character mode. In this mode \fBzgetty\fR returns each character as it +is typed, control characters have no special significance (as far as possible), +and characters are not automatically echoed to the terminal. A subsequent +call with maxch greater than one causes a mode switch back to line input +mode, followed by accumulation of the next input line. +.PP +The IRAF system includes device independent software for terminal control +and vector graphics, and expects to be able to send device dependent control +sequences to the terminal. Any program which does anything out of the ordinary +with a terminal, e.g., clearing the screen or underlining characters, uses +the TTY interface to generate the device dependent control sequences necessary +to control the terminal. Ordinary output to the terminal, however, is not +processed with the TTY interface. +.PP +The control characters commonly present in ordinary text are \fBnewline\fR, +\fBcarriage return\fR, and \fBtab\fR. The \fBnewline\fR character delimits +lines of text and should result in a carriage return followed by a line feed. +\fBZputtx\fR may be called repeatedly to build up a line of text; the output +line should not be broken until newline is sent. The carriage return character +should cause a carriage return without a line feed. If the host system terminal +driver can conditionally expand tabs, tab characters present in the text +should be passed on to the host driver. The terminal should be allowed +to expand tabs if possible as it is much faster, especially when working +from a modem. On many systems it will be necessary to map newlines upon +output, but all other control characters should be left alone. +.NH 4 +The Line Printer Device +.PP +Line printers are interfaced at the kernel level as binary files. +At the FIO level a line printer may be opened as either a text file or +a binary file. If opened as a text file at the FIO level, textual +output is processed under control of the device independent TTY interface, +generating the control sequences necessary to control the device, +then the output is packed and written to the device as a binary byte +stream. If the printer is opened as a binary file at the high level, +binary data is passed from the applications program through FIO and on +to the kernel without modification. +.sp 0.08i +.TS +center; +cb s +n l. +Line Printer Driver +.sp +zopnlp \&(osfn, mode, chan) open printer or spoolfile +zclslp \&(chan, status) close printer +zardlp \&(chan, buf, maxbytes, notused) initiate a read +zawrlp \&(chan, buf, nbytes, notused) initiate a write +zawtlp \&(chan, status) wait for transfer to complete +zsttlp \&(chan, param, lvalue) get file status +.TE +.sp 0.08i +.PP +The line printer is a streaming device. Currently only APPEND mode +is used, although there is nothing in the FIO interface to prevent +reading from a line printer device. The filename argument is the +\fBlogical name\fR of the printer device, as defined by the CL environment +variable \fBprinter\fR and as found in the \fBdev$termcap\fR file. +These logical device names are quite system dependent, and in general +it will be necessary to add new device entries to the termcap file, +and change the name of the default printer device by modifying the +\fBset printer\fR declaration in \fBlib$clpackage.cl\fR. +.PP +On some systems or for some devices it may be desirable to spool printer +output in an ordinary binary file opened by \fBzopnlp\fR, disposing of +the file to the host system when \fBzclslp\fR is called, or at some +later time. This is desirable when the line printer device is so slow +that asynchronous printing is desired, or when the printer device is +located on some other machine and the spoolfile must be pushed through +a network before it can be output to the device. +.PP +In general it should not be necessary to modify printer data upon output. +The high level code processes form feeds, expands tabs, generates control +sequences to underline characters, breaks long lines, maps newline into +the device end of line sequence, pads with nulls (or any other character) +to generate delays, and so on, as directed by the \fBdev$termcap\fR file. +If the host system driver insists on processing printer output itself, +it may be necessary to modify the termcap entry for the printer to generate +whatever control sequences the host system requires (the newline sequence +is likely to be a problem). The termcap entry for a printer is potentially +machine dependent since raw output to a line printer may not be feasible on +some systems, and it may be easier to edit the termcap file than to filter +the output stream in the driver. +.PP +Part of the reason for implementing the printer interface as a binary file +was to provide a convenient and efficient means of passing bitmaps to printer +devices. If a bitmap is to be written to a printer device, ideally the +device will be data driven and it will be possible to pass data directly +to the device without translation. If this is not the case, the driver +must make the device look like it is data driven by scanning the data +stream for a control sequence indicating a change to bitmap mode, +then poking the host driver to change to bitmap mode. Since the device +is data driven at the kernel level it will still be possible to spool +the output in a file and process it on a remote network node. +.NH 4 +Interprocess Communication +.PP +Interprocess communication (IPC) channels are necessitated by the multiprocess +nature of IRAF. When a subprocess is spawned by the CL (or by any IRAF +process) it is connected to its parent by two IPC channels, one for reading +and one for writing. An IPC channel is a record oriented streaming binary +file. +.sp 0.08i +.TS +center; +cb s +n l. +IPC Driver +.sp +zopnpr \&(osfn, mode, chan) not used +zclspr \&(chan, status) not used +zardpr \&(chan, buf, maxbytes, notused) initiate a read +zawrpr \&(chan, buf, nbytes, notused) initiate a write +zawtpr \&(chan, status) wait for transfer to complete +zsttpr \&(chan, param, lvalue) get file status +.TE +.sp 0.08i +.PP +The IPC channels are set up when a subprocess is spawned, and a process may +use IPC facilities only to talk to its parent and its children (the process +structure is a tree, not a graph). Since the opening of an IPC channel is +bound to the spawning of a subprocess, the open and close primitives are +not used for IPC files. The \fBprconnect\fR procedure (not a kernel primitive), +called by the parent to spawn a subprocess, sets up the IPC channels and +installs the IPC driver in FIO, +returning two binary file descriptors to the calling program. +The \fBprconnect\fR procedure is very much like a file \fBopen\fR, except that +the "file" it opens is active. The IRAF main in the child process senses +that it has been spawned by an IRAF process, and installs the same IPC driver +in its FIO, connecting the IPC channels to the streams CLIN and CLOUT. +.PP +Since the IPC channels are read and written by concurrent processes, +some care is necessary to ensure synchronization and to avoid deadlocks. +Fortunately most of the necessary logic is built into the high level protocols +of the CL interface, and an understanding of these protocols is not necessary +to implement the IPC driver. It is however essential that the low level +protocols of an IPC channel be implemented properly or deadlock may occur. +.PP +An IPC channel is \fBrecord oriented\fR. This means that if \fBzawrpr\fR +is called by process A to write N bytes, and \fBzardpr\fR is called by +process B to read from the same channel, N bytes will be read by process B. +If the IPC facilities provided by the host are sufficiently sophisticated, +records may be \fBqueued\fR in an IPC channel. The writing process should +block when the IPC channel fills and no more records can be queued. The +reading process should block when it attempts to read from an empty channel. +.PP +For example, suppose process A writes an N byte record and then an M byte +record. If \fBzardpr\fR is called by process B to read from the channel, +it should return to its caller the first record of length N bytes. +A second call will be required to read the next record of length M bytes. +On some systems, e.g. UNIX, the IPC facilities are not record oriented and the +first read might return either N bytes or N+M bytes, depending on unpredictable +system timing details. Hence the IPC driver for a UNIX system must impose +a record structure upon the UNIX "pipe" used as the IPC channel. +.PP +On other systems the IPC facilities may be limited to the transfer of single +records, i.e., process B will have to read a record +before process A can transmit the next record. This is the lowest common +denominator, and hence the protocol chosen for the IPC driver. Despite the +use of the lowest common denominator for the low level protocol, a high +bandwidth can be achieved for IPC channels if the maximum transfer size +is large and records are queued. The high level protocol ensures that only +one process will be writing or reading at a time, thus preventing deadlock. +The high level protocol also uses special data records as semaphores to achieve +synchronization and permit record queuing. +.PP +Most modern operating systems provide some sort of interprocess communications +facilities which the IPC driver can use. UNIX calls it a pipe or a socket, +VAX/VMS calls it a mailbox, and DG/AOS calls it an IPC port. If the host +system has no such facility, or if the facility provided by the host is +inefficient, an IPC driver can often be built using shared memory (use a +circular buffer to implement the queue). As a last resort, a real driver +can be coded and installed in the host system. On \fBmulti-processor\fR +systems the IPC facilities should allow the parent and child processes to +reside on different processors. +.NH 4 +Imagefile Access +.PP +Imagefiles, i.e., bulk data files, are a special kind of binary file. +The ordinary disk binary file driver may be used to access imagefiles, +but imagefiles have certain properties which can be exploited on some +systems for increased i/o efficiency. The image i/o software (IMIO) therefore +uses a special kernel driver to access imagefiles. Since this driver is +a special case of the ordinary binary file driver, a transportable version +of the driver which simply calls the ordinary binary file driver is included +in the standard distribution. The transportable driver may easily be replaced +by a machine dependent version to optimize image i/o for the host system. +.PP +Imagefiles differ from ordinary binary files in that the size of the image +is known when the \fBpixel storage file\fR is created. Furthermore, images +do not dynamically change in size at run time. On many systems it is possible +to preallocate the pixel storage file before writing any data into it, +rather than creating the file by writing at EOF. +.PP +Preallocation of a file makes it feasible for the host system to allocate +\fBcontiguous storage\fR for the file. Use of a preallocated, fixed size +file also makes it possible on some systems to map the file into +\fBvirtual memory\fR. If image access is expected to be sequential, or if +the host system does not support virtual memory, it is often possible to +\fBdirectly access\fR the file via the host system device driver, bypassing +the host files system software and significantly reducing the overhead of +file access (e.g., eliminating any intermediate buffering by the host system). +.sp 0.08i +.TS +center; +cb s +n l. +Static File Driver +.sp +zopnsf \&(osfn, mode, chan) open static file +zclssf \&(chan, status) close static file +zardsf \&(chan, buf, maxbytes, loffset) initiate a read +zawrsf \&(chan, buf, nbytes, loffset) initiate a write +zawtsf \&(chan, status) wait for transfer to complete +zsttsf \&(chan, param, lvalue) get file status +.sp +zfaloc \&(osfn, nbytes, status) preallocate a binary file +.TE +.sp 0.08i +.PP +The use of a file i/o interface to implement virtual memory access to files +is desirable to minimize the machine dependence of applications which use +virtual memory. The functional behavior of the static file driver is the +same whether it maps file segments into virtual memory or copies file +segments into physical memory. If IRAF is to be used on a system which does +not provide virtual memory facilities, the image processing software +will work without modification, provided the physical memory requirements +of the software are reasonable. +.PP +FIO divides a file up into segments of equal size, where the size of a segment +is equivalent to the size of a file buffer and is an integral multiple of the +virtual memory page size. IMIO ensures that the pixel data in the pixel +storage file begins on a block boundary, and is an integral number of pages +in length. Furthermore, when FIO allocates a file buffer, it ensures that +the buffer is aligned on a virtual memory page boundary. The virtual memory +page size is parameterized in \fBconfig.h\fR, and is set to 1 on a nonvirtual +machine. +.PP +Provided that the buffer and the file data are both properly aligned, +\fBzardsf\fR may be used to map a file segment into memory. The file buffer +pages are first deleted and then remapped onto the new file segment. +If the buffer is written into, \fBzawrsf\fR will eventually be called to +update the segment, i.e., flush modified pages to the image file (the pages +should not be unmapped). If desired a single FIO buffer may be allocated +the size of the entire image and all reads and writes will reference this +single buffer with minimum overhead. Alternatively the image may be mapped +in segments; reusing the same buffers avoids flushing the system page cache +when sequentially accessing a large image. +.PP +When an image section is read or written by IMIO, the interface returns +a pointer to a buffer containing the pixels. If all of the necessary +conditions are met (e.g., no subsampling, no datatype conversion, etc.), +IMIO will return a pointer directly into the file buffer, otherwise IMIO +extracts the pixels from the file buffer into a separate buffer. If the file +buffer is mapped onto the imagefile, IMIO thus returns a pointer directly into +the imagefile without performing any i/o (until the data is referenced). +Thus it is possible to exploit virtual memory for image access without +restricting the flexibility of programs which operate upon images; general image +sections may be referenced, datatypes need not agree, etc., yet i/o will still +be optimal for simple operations. +.PP +For example, suppose an entire large image is to be mapped into virtual +memory. FIO does not allocate any buffers until the first i/o on a file +occurs. IMIO will be called by the applications program to read a "subraster" +the size of the entire image. If the image can be directly accessed, +IMIO will set the FIO buffer size to the size of the image, then issue a +\fBseek\fR and a \fBread\fR to read the pixels. +FIO will allocate the buffer, aligned on a page boundary, then call +\fBzardsf\fR which maps the buffer onto the pixel storage file. +.PP +If all the necessary conditions are met, IMIO will return a pointer into the +FIO buffer and hence to the segment of memory mapped onto the pixel storage +file. If this is not possible, IMIO will allocate a new buffer of its own +and perform some transformation upon the pixels in the FIO buffer, writing +the transformed pixels into the IMIO buffer. The IMIO pointer will be +dereferenced in an subprogram argument list in the applications program, +and the SPP or Fortran subprogram will see what appears to be a static array. +.PP +Most virtual memory implementations are designed more for random access than +for \fBsequential access\fR. +Some systems, e.g. VAX/VMS, allow a variable number of pages (the page fault +cluster) to be read or written when a page fault occurs. +Other systems, e.g., DG/AOS, read or write a single page for each fault. +Even when the page fault cluster can be made large to minimize faulting +when sequentially accessing a large image, i/o is not optimal because paging +is not asynchronous, and because the heavy faulting tends to flush the process +and system page caches. Thus for sequential image operations conventional +double buffering with large buffers and large DMA transfers direct from +disk to memory is preferable. This level of i/o is available via QIO calls +on VAX/VMS and is feasible via \fIphysio\fR calls on UNIX, if images are +static and contiguous or nearly contiguous. +.PP +If the host system provides both virtual memory facilities and low level +asynchronous i/o, the static file driver should ideally be capable of +performing i/o by either technique. The choice of a technique may be based +upon the alignment criteria and upon the size of the transfer. +If the alignment criteria are not met or if the size of the transfer is +below a threshold, conventional i/o should be used. If the size of the +transfer is large, e.g., some sizable fraction of the working set size, +virtual i/o should be used. Virtual memory should only be used for images +which are to be accessed randomly, so the page fault cluster should be small. +.NH 4 +Magtape Devices +.PP +The magnetic tape device interface is the most complex file device interface +in the IRAF system. Operating systems vary greatly in the type of i/o +facilities provided for magtape access, making it difficult to design a +machine independent interface. Some systems provide primitive access to +the drive, permitting file and record skipping, writing of tape marks, +and so on, while others permit only sequential access in the forward direction. +Magtape access is further complicated by the storage of multiple files on +a tape, by variable size records, the occasional need to swap bytes, +and the need to specify the density. Error recovery is particularly difficult +for magtape devices because it is possible to lose track of the position +of the tape: whereas most binary devices are accessed by absolute offset, +magtapes are accessed relative to the current position. +.PP +To avoid having to deal with this level of complexity in the kernel, +the magtape device driver has been subdivided into a machine independent +part and a unique magtape device interface. The standard streaming +binary file driver subroutines are coded in SPP and are portable. An inner +set of six "zz" routines are defined especially for accessing magtape +devices. The portable driver routines constitute the MTIO interface and +are not part of the kernel. MTIO opens and initializes multiple magtape +devices, keeps track of the file position, and handles error recovery. +The kernel routines are responsible for physically positioning the tape +and for reading and writing records. +.sp 0.08i +.TS +center; +cb s +n l. +Magtape Driver +.sp +zopnmt \&(osfn, mode, chan) open a magtape file +zclsmt \&(chan, status) close magtape device +zardmt \&(chan, buf, maxbytes, notused) initiate a read +zawrmt \&(chan, buf, nbytes, notused) initiate a write +zawtmt \&(chan, status) wait for transfer to complete +zsttmt \&(chan, param, lvalue) get file status +.TE +.sp 0.08i +.PP +A magtape device must be \fBallocated\fR at the CL level before the device +can be accessed. A file on a magtape device is opened by calling the program +interface procedure \fBmtopen\fR in an applications program. +Once opened, a magtape file is accessed via the FIO interface and +hence benefits from the buffer management facilities provided by FIO. +Use of the FIO interface also provides device independence, allowing programs +which access magtape to be used to (sequentially) access any other binary +file. In particular, any IRAF program which commonly accesses magtape may +also be used to access a disk file. This permits use of the FITS reader and +writer, for example, for image transmission between stranger machines in a local +area network. +.PP +When a magtape device is allocated a device \fBlock file\fR is written into +the IRAF public directory \fBdev$\fR by the high level code. In addition to +telling other IRAF processes that the device has been allocated, the lock file +is used to keep track of the tape position while the device is closed. +When a device is closed, either normally or during error recovery, a new lock +file is written recording the current position of the drive as well as various +statistics (owner, time of last access, number of records read or written, +etc.). When a device is opened the lock file is read to determine the +current position. The \fBsystem.devstatus\fR program prints the contents +of the device lock file; if there is no lock file, the IRAF system assumes +that the device has not been allocated. +.PP +Each file on a reel must be opened individually, just as each file on a disk +must be opened individually. A pair of calls to \fBmtopen\fR and \fBclose\fR +(FIO) are required to access each file. +Drives are referred to by the logical names "mta", "mtb", and so on. +The assignment of logical drives to physical devices is system dependent. +The logical drive number, density, absolute file number on the tape, +absolute record number within the file, access mode, and FIO buffer size +(most of which can be defaulted) are specified in the file "name" argument +when the file is opened. For example, the filespec "mtb1600[3,10]" refers +to record 10 of file 3 of logical drive "mtb" at 1600 bpi. The minimum +filespec consists of just the logical drive name; everything else is optional. +.PP +The \fBmtopen\fR procedure parses the magtape filespec to determine whether +a magtape device or a disk binary file is being referenced. If a disk file +is named, \fBmtopen\fR reduces into a conventional call to \fBopen\fR. +If a magtape file is named, the filespec is parsed to determine the logical +drive, density, and the file and record numbers to which the tape is to +be opened. If this information is legal, if the drive is allocated, +and if the drive is not already open, \fBmtopen\fR reads the lock file to +determine the current position. FIO is then called to open the device. +A global common is used to pass device dependent information from \fBmtopen\fR +to \fBzopnmt\fR, since device dependent information cannot be passed through +FIO. +.PP +The magtape kernel primitives are shown below. Our intent here is only to +introduce the routines and discuss the role they fulfill in the MTIO interface. +Detailed specifications for the routines are given in the manual pages. +.sp 0.08i +.TS +center; +cb s +n l. +Magtape Kernel Primitives +.sp +zzopmt \&(drive, density, mode, oldrec, oldfile, newfile, chan) open +zzclmt \&(chan, mode, nrecords, nfiles, status) close +zzrdmt \&(chan, buf, maxbytes) aread +zzwrmt \&(chan, buf, nbytes) awrite +zzwtmt \&(chan, nrecords, nfiles, status) await +zzrwmt \&(chan, status) arewind +.TE +.sp 0.08i +.PP +The \fBzopnmt\fR procedure is called by FIO to open a magtape device. +The only legal access modes for magtape files are READ_ONLY and WRITE_ONLY. +The device parameters are retrieved from the global common prepared by +\fBmtopen\fR and passed on to the kernel primitive \fBzzopmt\fR to physically +open the drive. The kernel open primitive sets the density of the drive and +opens the drive with the desired access mode, leaving the tape positioned to +record 1 of the desired file. +.PP +The exact position of the tape at open time, i.e., both file and record +numbers (one-indexed), is passed to \fBzzopmt\fR to facilitate positioning +the tape. Many systems can skip records and tapemarks in either the forward +or reverse direction, and it is easy to position the tape on such systems +given the current position and the new position. The current record number +is needed to tell \fBzzopmt\fR when the current file is already rewound. +On some systems it is not possible to backspace to the last tapemark, +and the only way to rewind the current file or position to a previous file +is to rewind the tape and read forward. +.PP +Upon input to \fBzzopmt\fR, the \fInewfile\fR argument specifies the number +of the file to which the tape is to be positioned, or the magic number EOT. +Upon output, \fInewfile\fR contains the number of the file to which the +tape was actually positioned. The high level code assumes that the +tape does not move when the device is closed and subsequently reopened; +if this is not the case, \fBzzopmt\fR should ignore the old position arguments. +.PP +The \fBzzrdmt\fR and \fBzzwrmt\fR primitives initiate an asynchronous +read or write of a record at the current tape position. The number of bytes +read or written and the number of records and or files skipped in the operation +are returned in the next call to \fBzzstmt\fR. If a tape mark is seen when +attempting to read the next record, \fBzzwtmt\fR should return a byte count +of zero to signal EOF. It does not matter whether the tape is left positioned +before or after the tape mark, provided the record and file counts are +accurate. +.PP +A file containing zero records marks logical EOT. If physical EOT is seen +either the host system or the kernel should signal the operator to mount +the next reel, returning only after a record has been read or written on +the next reel. The high level code does not try to reread or rewrite +records. Error retry should be handled either by the kernel routines or +preferably by the host driver. The kernel should return ERR only if it +cannot read or write a record. It is not an error if less data is read +than was requested, or if more data was available in the record than was +read, resulting in loss of data. Loss of data is unlikely because FIO +generally allocates a large (16K or 32K) input buffer when reading magtapes. +.PP +If an error occurs when accessing the magtape device, e.g. a keyboard +interrupt, the high level code will mark the position of the tape as +undefined and call \fBzzclmt\fR to close the device. When the device is +subsequently reopened, \fBmtopen\fR will see that the position of the tape +is undefined and will rewind the tape before calling \fBzzopmt\fR to open +and position the drive. Since this is handled by MTIO, the kernel routines +need not be concerned with error recovery except possibly to abort a tape +motion if an interrupt occurs, to prevent runaway (hopefully this will not +be necessary on most systems). +.PP +The \fBzzclmt\fR primitive will be called to close the device upon normal +termination or during error recovery. MTIO assumes that \fBzzclmt\fR will +write an EOT mark (two tapemarks) \fIat the current tape position\fR when +a tape opened with write permission is closed. This is the only way in which +MTIO can write EOF and EOT marks on the tape. To avoid clobbering tapes, +\fBzzopmt\fR may need to open the drive read-only while positioning the tape. +Since an interrupt may occur while the tape is being positioned, \fBzzopmt\fR +should return the OS channel argument immediately after the channel has been +opened, before positioning the tape. +.PP +In summary, the magtape kernel primitives are highly machine independent +because they permit access to only a single file at a time, reading or +writing sequentially in the forward direction. No primitive tape positioning +commands are required except \fBzzrwmt\fR, and that can be implemented +with a call to \fBzzopmt\fR if necessary (the difference is that \fBzzrwmt\fR +may be asynchronous). No assumptions are made about where the tape is left +positioned if an error occurs or if a tapemark is read or written. +All writing of tapemarks is left to the kernel or to the host system. + +.NH 2 +Filename Mapping +.PP +The syntax of a filename is highly system dependent. This poses a major +obstacle to transporting a large system such as IRAF, since the standard +distribution consists of several thousand files in several dozen directories. +Many of those files are referred to by name in the high level program sources, +and use of host system dependent filenames in such a context would make the +IRAF system very difficult to transport. +.PP +To avoid this problem only \fBvirtual filenames\fR (VFNs) are used in IRAF +source files. FIO converts a VFN into a host system dependent filename (OSFN) +whenever a filename is passed to a kernel routine. Conversely, when FIO reads +a directory it converts the list of OS filenames in the host directory into +a list of virtual filenames. The kernel routines see only machine dependent +filenames packed as Fortran character constants. +.PP +While it is not necessary to study filename mapping to implement the kernel, +filename mapping is a vital part of the system interface and an understanding +of the mapping algorithm employed is necessary to adjust the machine dependent +parameters controlling the mapping. The filename mapping parameters are given +in the system configuration file \fBlib$config.h\fR. +.NH 3 +Virtual Filenames +.PP +A VFN consists of three fields, the \fBdirectory\fR, the \fBroot\fR, +and the \fBextension\fR. Directories are specified by a \fBlogical +directory\fR name followed by a \fBpathname\fR to a subdirectory. +Either the logical directory name or the pathname may be omitted. +If the logical directory field is omitted the current directory is assumed. +The extension field is optional and is used to specify the file type, +e.g., CL source, SPP source, object module, and so on. Either the logical +directory delimiter character \fB$\fR or the subdirectory delimiter +character \fB/\fR may delimit the directory field, and a period delimits +the root and extension fields. +.DS + \fIdir\fR \fB$\fR \fIpath\fR \fB/\fR \fIroot\fR \fB.\fR \fIextn\fR +.DE +.PP +The combined length of the root and extension fields is limited to 32 +characters. The legal character set is \fBA-Za-z0-9_.\fR, i.e., +the upper and lower case alphanumerics (case is significant), underscore, +and period. Other characters may be permitted on some systems, but if +present the filename is machine dependent. The first character of a filename +is not special, i.e., the first character may be a number, underscore, +or any other filename character. Purely numeric filenames are permitted. +The VFN syntax does not support VAX/VMS-like version numbers. A file naming +syntax would not be sufficient to emulate versions; extensive FIO support +would also be required on systems other than VMS. +.PP +The following are all legal virtual filenames (avoiding directory specifications +for the moment). +.DS + 20 + 02Jan83 + Makefile + 10.20.11 + M92_data.Mar84 + extract_spectrum.x + _allocate +.DE +.NH 4 +Logical Directories and Pathnames +.PP +The use of logical directories and pathnames is perhaps best explained by +an example. Consider the VFN \fBplot$graph.x\fR, specifying the file +\fBgraph.x\fR in the logical directory \fBplot\fR. +The logical directory \fBplot\fR is +defined in the CL environment (file \fBlib$clpackage.cl\fR) as follows. +.DS + \fBset plot = "pkg$plot/"\fR + \fBset pkg = "iraf$pkg/"\fR +.DE +These definitions state that \fBplot\fR is a subdirectory of \fBpkg\fR, +and that \fBpkg\fR is a subdirectory of \fBiraf\fR, the root directory of +the IRAF system. The definition for the root directory is necessarily +both machine and configuration dependent. On a VAX/VMS system \fBiraf\fR +might be defined as follows: +.DS + \fBset iraf = "dra0:[iraf]"\fR +.DE +Recursively expanding the original VFN produces the following partially +machine dependent filename: +.DS + \fBdra0:[iraf]pkg/plot/graph.x\fR +.DE +The final, fully translated, machine dependent filename is produced by +folding the subdirectory names into the VMS directory prefix, mapping +the remaining filename (which does not change in this case), and concatenating: +.DS + \fBdra0:[iraf.pkg.plot]graph.x\fR +.DE +.PP +The important thing here is that while there may be many directories in the +system, \fIonly the definition of the IRAF root directory is machine +dependent\fR. Filenames in package script tasks, in the \fBhelp\fR database, +in makefiles, and so on inevitably include references to subdirectories, +hence the VFN syntax must recognize and map subdirectory references to fully +address the problems of machine independence. +.PP +Even when porting the system to another host running the same operating +system the root directory may (and usually will) change. +Since all logical directories and filenames are defined in +terms of the root directory, since the root is defined at runtime, and since +filenames are mapped at runtime, the system may be ported to another machine +running the same operating system by editing only one file, \fIwithout having +to recompile the system\fR. The importance of not having to recompile the +system becomes clear when the local hardware configuration changes or when +installing periodic updates at a site with multiple host computers all running +the same operating system. +.sp 0.08i +.TS +center; +cb s +n l. +Filename Mapping Primitives +.sp +zfsubd \&(osdir, subdir, new_osdir, maxch, nchars) fold subdir into osdir +zfxdir \&(osfn, osdir, maxch, nchars) get directory prefix +zfpath \&(osfn, pathname, maxch, nchars) get absolute pathname +.TE +.sp 0.08i +.PP +The primitives used to map filenames are shown above. The \fBzfsubd\fR +primitive folds a subdirectory name into a machine dependent directory +name (OSDIR), producing the OSDIR name of the subdirectory as output. +The subdirectory name ".." refers to the next higher directory in the +hierarchy, allowing upwards directory references. The form of a host +directory name is undefined, hence the primitive \fBzfxdir\fR is required +to extract a machine dependent directory prefix from a host filename (OSFN). +Directory expansion does not guarantee that the OSFN produced is independent +of the current working directory, hence the \fBzfpath\fR primitive is provided +to convert OSFNs into absolute pathnames. +.NH 4 +Filename Extensions +.PP +Filename \fBextensions\fR, like directories, pose a problem because different +operating systems use different extensions for the same logical file types. +Thus a Fortran source file might have the extensions ".f", ".f77", and +".for" on various systems. IRAF defines a standard set of file extensions +to be used in virtual filenames. Filename extensions are mapped by string +substitution when a file is referenced; unrecognized extensions are left alone. +The standard extensions used in IRAF virtual filenames are essentially those +used by UNIX, plus extensions for the special IRAF file types (e.g., +CL script files and parameter files). +.PP +To illustrate the mapping of filename extensions, consider the IRAF system +library \fBlib$libos.a\fR, which contains the kernel routines in object form. +On a UNIX system this might be expanded as "\fB/usr/iraf/lib/libos.a\fR", +whereas on a VMS system it might be converted to \fBdra0:[iraf.lib]libos.olb\fR. +.PP +The standard IRAF filename extensions are listed in the table below. +Those which are system dependent and are normally mapped are marked +at the right. +.sp +.TS +center box; +cb s s +c | c c +c | l c. +Standard Filename Extensions += +Extension Usage Mapped +_ +\\.a Library file (archive) ** +\\.c C language source ** +\\.cl Command Language script file +\\.com Global common declaration +\\.db database file +\\.e executable image ** +\\.f Fortran 77 source file ** +\\.h SPP header file +\\.hlp \fILroff\fR format help text +\\.ms \fITroff\fR format text +\\.o object module ** +\\.par CL parameter file +\\.pix pixel storage file +\\.x SPP language source +.TE +.sp +.PP +For the convenience of the user working interactively within the IRAF +environment, FIO permits virtual and host system dependent filenames +to be used interchangeably. Any arbitrary file or directory in the host +system may be referenced as an argument to an IRAF program, even if the +host directory has not been assigned a logical name. The filename mapping +scheme thus provides indirect support for pathnames, by permitting the +use of OS dependent pathnames to specify files when working interactively. +If a machine dependent filename is given, mapping of the root and extension +fields is disabled. +.NH 3 +Filename Mapping Algorithm +.PP +The primary requirement for filename mapping is that the process be +reversible, i.e., it must be possible to map a VFN to an OSFN and later +recover the original VFN by applying the reverse mapping. The following +additional requirements led to the selection of the algorithm described +in this section. +.sp 0.08i +.RS +.IP \(bu +There should be no efficiency penalty for simple filenames. +.IP \(bu +The algorithm must permit multiple processes to access the same directory +without contention. +.IP \(bu +The mapping must be transparent, i.e., reversible by inspection of the +host system directory, making it easy to work with directories and files +at the host system level. +.IP \(bu +The reverse mapping (OSFN to VFN) should be efficient, i.e., there must +not be a serious degradation of performance for template expansion and +directory listings. +.IP \(bu +The mapping should permit use of IRAF, with some loss of efficiency, +on a computer with a flat directory system. +.RE +.sp 0.08i +.PP +The algorithm selected consists of two phases. If the maximum information +content of a host system filename is sufficiently large, the first phase will +succeed in generating a unique mapping with no significant overhead. +If the first phase fails, the second phase guarantees a unique mapping on +any system with minimal overhead. The first phase maps the VFN into the +OSFN character set using \fBescape sequences\fR to map non-OSFN characters, +preserving the information content of a filename by increasing its length. +If the length of the OSFN thus generated exceeds the maximum filename length +permitted by the host system, the second phase accesses an \fBauxiliary +hidden file\fR to recover the excess information. +.PP +The operation of the mapping algorithm differs slightly depending on whether +an existing file is to be accessed or a new file is to be created. +The procedure followed to generate a unique OSFN when opening an existing +file is outlined below. The complications caused by multiple logical +directories, filename extensions, and transparency to machine dependent +filenames are not relevant to the algorithm and are omitted. +.sp +.DS +.cs 1 18 +\fBalgorithm\fR vfn_to_osfn +.sp .05 +\fBbegin\fR + # Phase one: encode VFN using only legal OSFN characters. +.sp 0.05i + map vfn to osfn using escape sequence encoding + \fBif\fR (length of osfn is within host limit) + \fBreturn\fR (osfn) +.sp 0.05i + # Phase two. Access or read auxiliary file to get OSFN. +.sp 0.05i + squeeze osfn to legal host filename length + \fBif\fR (squeezed osfn is degenerate) { + extract unique_osfn for named vfn from mapping file + \fBreturn\fR (unique_osfn) + } \fBelse\fR + \fBreturn\fR (osfn) +\fBend\fR +.DE +.cs 1 +.sp +.PP +\fBEscape sequence encoding\fR is a technique for mapping illegal characters +into sequences of legal characters. A single illegal character is mapped into +two legal characters. Strings of illegal characters, e.g., a sequence of +characters of the wrong case, are prefixed by a font change sequence. +For example, suppose the host system permits only upper case alphanumeric +characters in filenames. Lower case is the dominant case in VFNs, so case +will be inverted in the mapping and upper case in a VFN must be escaped. +If we pick the letter Y as our escape character, the following mappings might +be established (these are the defaults for VMS and AOS): +.sp 0.08i +.DS +.TS +ci ci ci +c c l. +vfn osfn usage +.sp +y Y0 the escape character itself +tolower Y1 switch to primary case +toupper Y2 switch to secondary case +\\_ Y3 underscore +\\. Y4 period +A-Z YA-YZ upper case letters +.TE +.DE +.sp 0.08i +.PP +The use of escape sequences can result in confusing mappings, +but if the escape character is chosen carefully such cases will be rare. +Most filenames are quite ordinary and will map with at most a case conversion. +Some examples of filenames which do not map trivially are given below. +The maximum length of a filename extension on the host system is assumed +to be 3 characters in these examples. +Any host limit on the maximum number of characters in the root is ignored. +For the purposes of illustration, we assume that the first character of the +OS filename cannot be a number, necessitating use of a no-op sequence. +.sp 0.08i +.in 0.8i +.TS +l l. +20 Y120 +02Jan83 Y102YJAN83 +Makefile YMAKEFILE +10.20.11 Y110Y420.11 +M92_data.Mar84 YM92Y3DATAY4YMAR84 +extract_spectrum.x EXTRACTY3SPECTRUM.X +_allocate Y3ALLOCATE +yy.tab.c Y0Y0Y4TAB.C +README Y2README +.TE +.in -0.8i +.sp 0.08i +.PP +Escape sequence encoding will probably suffice for most filename mapping, +particularly if the host system permits long filenames (e.g., AOS/VS currently +permits filenames of up to 32 characters). If the encoded filename is +too long for the host system, auxiliary files must be used to store the +excess information. A single \fBmapping file\fR is used for the entire +directory to permit efficient inverse mapping when expanding filename templates +and listing directories, and to avoid wasting disk space by generating many +small files. +.PP +If escape sequence encoding produces an OSFN longer than the maximum OS +filename length N, then characters must be discarded to produce an N character +filename. This is done by squeezing the long OSFN, preserving the first few +and final characters of the root, and the first character of the extension +(if any). For example, if the OSFN is CONCATENATE.PAR and N is 9, +the squeezed OSFN will be CONCATEEP.PAR (the mapping is the same as that +employed for long identifiers in the SPP, except that the first character +of the extension is appended). Once this is done, of course, the mapping +is no longer guaranteed to be unique. +.PP +More often than not a squeezed OSFN will be unique within the context +of a single directory. If this is the case it is not necessary to read the +mapping file to convert a VFN to an OSFN, although it is always necessary to +read the mapping file to carry out the inverse transformation. If the mapping +is unique within a directory, a null file with the same root name as the +primary file but with the (default) extension \fB.zmu\fR is created to +indicate that the mapping is unique (e.g., CONCATEEP.ZMU and CONCATEEX.ZMU). +If a second file is created with the same root OSFN and the mapping is no +longer unique, the \fB.zmu\fR directory entry is simply deleted, and the +mapping file will have to be read whenever either file is accessed. +.PP +The utility of the \fB.zmu\fR file is based on the assumption that the +determining the existence of a file is a much less expensive operation on +most systems than opening, reading, and closing the mapping file. +Furthermore, the \fB.zmu\fR file is a null length file, i.e., just an +entry in a directory, so no disk space is wasted. +Use of the advisory \fB.zmu\fR file does however involve an assumption that the +host system permits filename extensions. If this is not the case, +set the maximum length of a filename extension to zero in \fBconfig.h\fR, +and FIO will not generate the files. +.PP +The mapping file is effectively an extension of the directory and hence +will lead to contention problems when \fBconcurrent processes\fR try to +access the same directory. +A process must not be allowed to read the mapping file +while another process is modifying it, and under no circumstances may two +processes write to the mapping file at the same time. This requires that +a process which wishes to modify the mapping file place a lock on the +file before accessing it, and that a process be capable of waiting if the +mapping file is locked. The mapping data must not be buffered, i.e., +the file should be reread every time a (degenerate) file is accessed. +Fortunately contention should be rare since most file accesses to not +require use of the mapping file. +.PP +In summary, the overhead of the filename mapping algorithm should be +insignificant when (1) accessing files with simple names, +and (2) accessing files with long names for which the mapping is unique. +A small but fixed overhead is incurred when a file with a long name is +created or deleted, when a directory is read, and when a file is accessed +for which the mapping is degenerate. If the host computer has a decent +files system the algorithm will incur negligible overhead for all operations. + +.NH 2 +Directory Access +.PP +The capability to read filenames from a host directory is required for +the expansion of filename templates and for the directory listing program. +At the program interface level a directory appears to be a simple text file, +i.e., an unordered list of virtual filenames. A directory file is opened +at the applications level with \fBdiropen\fR and successive VFNs are read +with \fBgetline\fR. The driver procedures used to interface a directory to +FIO as a text file are machine independent. The kernel primitives called +to read OS filenames from a directory are machine dependent and are summarized +below. +.sp 0.08i +.TS +center; +cb s +n l. +Directory Access Primitives +.sp +zopdir \&(osfn, chan) open a directory +zcldir \&(chan, status) close directory +zgfdir \&(chan, osfn, maxch, status) get next OSFN +.TE +.sp 0.08i +.PP +Directory files are read-only and are accessed sequentially. +A single filename is returned in each call to \fBzgfdir\fR as a +packed string, returning as status the length of the string or EOF. +Filenames may be returned in any order; all filenames in the directory +should be returned (there are no "hidden" files at this level). +Raw OS dependent filenames should be returned. The inverse mapping +from OSFN to VFN is carried out in the machine independent code. +.PP +If the host system does not permit direct access to a directory file, +or does not provide a primitive which returns successive filenames, +it may be necessary to read the entire contents of the directory +into a buffer at \fBzopdir\fR time, returning successive filenames +from the internal buffer in \fBzgfdir\fR calls, and deleting the buffer +at \fBzcldir\fR time. + +.NH 2 +File Management Primitives +.PP +The kernel provides a number of general file management primitives for +miscellaneous operations upon files and directories. These are summarized +in the table below. These primitives are all alike in that they operate +upon files by name rather than by channel number. +The file management primitives +read, write, create, and delete the \fIdirectory entries\fR for files; +none access the actual file data. No primitive which operates upon a file +by name will be called while the file is open for i/o. +.sp 0.08i +.TS +center; +cb s +n l. +File Management Primitives +.sp +zfacss \&(osfn, mode, type, status) access file +zfchdr \&(new_directory, status) change directory +zfdele \&(osfn, status) delete a file +zfinfo \&(osfn, out_struct, status) get info on a file +zfmkcp \&(old_osfn, new_osfn, status) make null copy of a file +zfpath \&(osfn, pathname, maxch, status) osfn to pathname +zfprot \&(osfn, prot_flag, status) file protection +zfrnam \&(old_osfn, new_osfn, status) rename a file +.TE +.sp 0.08i +.PP +The \fBzfacss\fR primitive is used to determine whether or not a file +exists, is accessible with the given permissions, or is a text or binary +file. The \fBzfinfo\fR primitive returns a data structure defining the +file type, access modes, owner, size, creation date, time of last modify, +and so on. Information not returned includes whether the file is a text +or binary file, and whether or not the file is protected from deletion, +because this information is expensive to determine on some systems. +The \fBzfprot\fR primitive is called to place or remove delete protection +on a file, and to test whether or not a file is protected. +.PP +Primitives for accessing directories are limited to \fBzfpath\fR, which +returns the pathname of a file or of the current working directory, +and \fBzfchdr\fR, which changes the current directory. There are no +primitives for creating or deleting new subdirectories: thus far no program +has needed such a primitive. Directory creation and manipulation is +probably best left to the host system. +.PP +The assumption that there are only two basic file types, text and binary, +is overly simplistic when it comes to copying an arbitrary file. If an +executable file is copied as a binary file, for example, the copy will +not be executable. The problem is that a conventional binary file copy +operation copies only the file data: the directory entry is not copied, +and information is lost. The \fBzfmkcp\fR primitive makes a zero length +file which inherits all the system dependent attributes of another file, +excluding the filename, length, and owner. The new file is subsequently +opened for appending as either a text or binary file, and the file data +is copied in the conventional manner. Directory files cannot be copied. + +.NH 2 +Process Control +.PP +Process control, interprocess communication, exception handling, and error +recovery are probably the most complex and subtle services provided by the +IRAF virtual operating system, and the most likely to be machine dependent. +Despite the effort to isolate the machine dependence into the kernel and to +make the kernel primitives as simple and self contained as possible, a high +level understanding of the subtleties of process control may be necessary +to debug system problems. An introduction to process control in IRAF is +therefore presented to supplement the specifications for the kernel primitives. +It should be possible for a systems programmer implementing the kernel to +skim or skip most of this section, referring to it only to resolve ambiguities +in the kernel specifications. +.PP +The CL is currently the only process in the IRAF system which spawns other +processes. In this section we present an overview of process control in the +CL, defining important terms, discussing the conceptual model of a subprocess +as a command file, and describing the architecture of the process control +subsystem. The synchronous protocol for communicating with subprocesses +is discussed, as is the asynchronous file oriented protocol for communicating +with background jobs. The function of the IRAF main is described, including +error recovery and implementation strategies for interfacing asynchronous +processes to a host system window manager or job status terminal. The kernel +primitives for process control are presented at the end of the section. +.NH 3 +Overview and Terminology +.PP +From the point of view of the CL, an executable program is a \fBcommand file\fR +containing a sequence of commands to be parsed and executed. Once opened or +\fBconnected\fR, a compiled program is equivalent to a script task or the +user terminal; the CL does not know or care where the commands are coming from. +Any CL command that can be executed from the user terminal can also be executed +by a compiled program or a script task. Calls to external programs, script +tasks, the terminal, or any other \fBlogical task\fR may be nested until the +CL runs out of file descriptors or stack space. +.PP +A \fBprogram\fR is a compiled logical task. An arbitrary number of programs +may be linked together to form a single physical \fBprocess\fR, i.e., +executable file. When an IRAF process is executed the \fBIRAF Main\fR +(main routine or driver procedure) in the subprocess initializes the process +data structures and then enters an interpreter loop awaiting a command from +the input file, which may be an IPC file (the CL), a terminal, or a text file. +Hence, not only does a subprocess look like a file to the CL, the CL looks +like a file to a subprocess. +.PP +Task termination occurs when the CL reads either end of file (EOF) or the +command \fBbye\fR. When a script task terminates the script file is closed; +when a program terminates the associated process may be \fBdisconnected\fR. +A subprocess is disconnected by sending the command \fBbye\fR to the +IRAF Main in the subprocess. The IRAF main cleans up the files system and +dynamic memory, calls any procedures posted by the user program with +\fBonexit\fR, and then returns to its caller (the \fBprocess main\fR), +causing process exit. +.PP +When a process spawns a subprocess, the original process is called +the \fBparent\fR process, and the subprocess is called the \fBchild\fR process. +A parent process may have several child processes, but a child process may +have only a single parent, hence the process structure of IRAF is a rooted +tree. The root process is the interactive CL; the user terminal (or a window +manager process) is the parent of the CL. Since the CL is the only process +which spawns other processes, an IRAF process tree has only two levels. +.PP +Processes communicate with each other only via \fBIPC channels\fR or +ordinary disk files. Since the only way to open an IPC channel is to connect +a subprocess, a process may communicate only with its parent or with one of its +children. Separate channels are used for reading and writing, rather than +a single read-write channel, to conform to the logical model of a subprocess +as a text file and to facilitate record queueing in the write channel. +Since only IPC channels and ordinary files are used for interprocess +communication and synchronization, the parent and child processes may reside +on separate processors in a \fBmultiple processor\fR system configuration. +.PP +The IPC channels are used to pass commands, data, and control parameters. +While a program is executing it sends commands to the CL, +most commonly to get or put the values of \fBCL parameters\fR. +In a get parameter operation the CL responds by printing the value of the +parameter on its output, just as it does when the +same command is typed in interactively. The output of the CL is connected +to the input IPC channel of the child process, which reads and decodes the +value of the parameter, returning the binary value to the calling program. +.PP +The standard input, standard output, standard error output, standard graphics +output, etc. of the child process are known as \fBpseudofiles\fR because the +actual files are opened and controlled entirely by the CL. A read or write +to a pseudofile in the child process is converted into a command to read or +write a binary block of data and sent over the IPC channel along with the +binary data block. Hence, even though most traffic on the IPC channels is +ASCII text, the channels are implemented as binary files. A large transfer +block size is used for all pseudofiles except STDERR to maximize throughput. +All parameter i/o and pseudofile i/o is multiplexed into a single command stream +and transmitted over the two IPC channels. +.PP +To minimize process connects, the CL maintains a \fBprocess cache\fR of +connected but generally idle subprocesses. A process is connected and placed +in the cache when a program in that process is run. A process will remain +in the cache, i.e., remain connected to the CL process, until either a new +process connect forces the process out of the cache or until the cache +is flushed. Since programs execute serially, at most one cached process will be +active at a time. Since several subprocesses may simultaneously be connected +and each subprocess may contain an arbitrary number of programs, the cache +can greatly reduce the average overhead required to run an external program, +while permitting dynamic linking of programs at run time. +.PP +The CL executes programs serially much as a program executes subroutines +serially. The protocol used to communicate with a connected subprocess is +synchronous. To execute a program or general command block as a +\fBbackground job\fR, i.e., asynchronously, the CL spawns a copy of itself +which executes independently of the parent CL. The child CL inherits the +full interior state of the parent CL, including the metacode for the command +to be executed, all loaded packages and parameter files, the environment list, +and the dictionary and stacks. Open files are not inherited, the child CL +is not connected to the parent CL, and the CL subprocess is not placed in the +process cache of the parent. The child CL manages its own process cache +and executes external programs using the synchronous protocol. A child CL +may spawn a child CL of its own. +.NH 3 +Synchronous Subprocesses +.PP +The sequence of actions required to synchronously execute an external compiled +program are summarized below. Only those actions required to execute a +program are shown; the process cache is a local optimization hidden within the +CL which is not relevant to a discussion of the synchronous subprogram protocol. +Everything shown is machine independent except the process main and the +IPC driver. Only a single process may be in control at any one time. +.PP +A process may be spawned by another IRAF process or by the host command +interpreter or JCL. When a process is spawned the host system transfers +control to a standard place known as the \fBprocess main\fR. The process +main must determine what type of parent it has and open the type of input +and output channels required by the parent. If the parent is another process +IPC channels are opened. The process main then calls the IRAF Main which +initializes IRAF i/o and enters the Main interpreter loop to read commands +from the parent. +.sp 0.05i +.DS +.ce +\fBProcess Startup\fR +.sp +\fIParent process:\fR + spawn the subprocess + open IPC channels between parent and child + send commands to initialize environment list in child +.sp +\fIProcess Main in child:\fR + determine whether input device is a terminal, text file, or process + open input and output channels (e.g. the IPC channels) + call the IRAF Main +.sp +\fIIRAF Main in child:\fR + save process status for error restart + initialize file i/o, dynamic memory, and error handling + post default exception handlers + enter interpreter loop, reading commands from parent +.DE +.sp +.PP +An IRAF process will interpret and execute successive commands in its input +file until it encounters either EOF or the command \fBbye\fR. The first +block of commands read by the Main will normally be a sequence of \fBset\fR +statements initializing the process environment (defining logical directories +and devices, etc.). A number of calls to the programs resident in the process +will normally follow. When a program runs it assumes control and begins +issuing commands to the parent to read and write parameters and pseudofiles. +The IRAF i/o system is reset to its default initial state each time a program +terminates (this can be overridden by a program if desired). +.sp +.DS +.ce +\fBProcess Execution\fR +.sp +\fIParent process:\fR + send name of program to be run to the IRAF Main in the child process + redirect command input to child, i.e., transfer control to the + program in the child process +.sp +\fIProgram in child process:\fR + (we were called by the interpreter in the IRAF Main) + execute, sending commands to parent to read and write parameters + and pseudofiles + return to caller (the IRAF Main) when done +.sp +\fIIRAF Main:\fR + flush STDOUT, close any open files, etc. + send the command \fBbye\fR to parent to signal that program has + completed and to return control to the parent + enter interpreter loop, reading commands from parent +.DE +.sp +.PP +A process shuts down or exits only when commanded to do so by the parent, +i.e., when an input file read returns EOF or the command \fBbye\fR is executed. +Any user defined procedures posted with \fBonexit\fR calls during process +execution will be executed during process shutdown. Control eventually +returns to the process main which takes whatever system dependent actions +are required to terminate the process. +.sp +.DS +.ce +\fBProcess Shutdown\fR +.sp +\fIParent process:\fR + if no further programs are to be run, send the command \fBbye\fR + to the child to initiate process shutdown +.sp +\fIIRAF Main:\fR + disable IPC output (parent is no longer reading) + call any user procedures posted with \fBonexit\fR, i.e., flagged + to be executed upon process shutdown + return to caller (the process main) when done +.sp +\fIProcess Main:\fR + terminate subprocess +.sp +\fIParent process:\fR + disconnect child process +.DE +.sp 0.05i +.PP +If a process issues a read request on an IPC channel +and there is no input in the channel, the reading process will block, hence +reading from an empty IPC channel causes process synchronization. Successive +writes are queued until the channel is full, hence writing is generally +asynchronous and some degree of overlapped execution is possible. +Traffic on the IPC channels is restricted to the small set of commands +described in the next section. +.NH 3 +Standard IPC Commands +.PP +Although in principle a subprocess may send any legal CL command to the CL +process, in practice only a small subset of commands are permitted in order to +minimize the size of the interface. A larger interface would mean more +dependence upon the characteristics of a particular CL, making it more +difficult to modify the CL and to support several different versions of the CL. +.PP +The IPC interface commands described in this section are a high level protocol +implemented entirely above the kernel routines to support execution of external +programs by the CL. If the parent process were not the CL and if a new IRAF +Main were implemented (the IRAF Main is an ordinary SPP procedure), then a +quite different protocol could be devised. +.PP +The \fBIRAF Main requests\fR, i.e., the IPC commands sent to the IRAF Main by +the parent process, are shown below in the order in which they are normally +sent to the child process. Italicized text denotes dummy parameters to be +replaced by the name or value of the actual parameter when the command is +issued. Keywords are shown in boldface. Optional characters or arguments are +delimited by square brackets. All commands are ASCII lines of text terminated +by the \fBnewline\fR character. +.sp +.in 1.0i +.KS +.ti -0.5i +\fBset\fR \fIvariable\fR = \fIstring\fR +.ti -0.5i +\fBset\fR @\fIfname\fR +.sp 0.04i +Set the value of an environment variable or set the environment from a file. +If the variable does not exist it is created; if it does exist the new value +silently replaces the old value. The \fBset\fR statement is used to pass +the environment list of the parent to the child process when the subprocess +is connected. The second form of the \fBset\fR statement reads a list of +\fBset\fR declarations from a text file, and is especially useful in debug +mode. +.KE +.sp +.KS +.ti -0.5i +\fB?\fR +.sp 0.04i +Print the names of all user programs linked into the process in tabular +form (i.e. print a menu) on the standard output. This command is not +currently used by the CL; it is most useful when debugging a process run +directly from the host command interpreter. +.KE +.sp +.ti -0.5i +[\fB$\fR] \fIprogram\fR [<[\fIfname\fR]], [[\fIstream\fR[(T|B)]]>[\fIfname\fR]], [[\fIstream\fR]>>[\fIfname\fR]] +.sp 0.04i +Execute the named program. The environment should have been initialized by +the time a program is run. If a dollar sign is prefixed to the command +name, the cpu and clock time consumed by the process are printed on the +standard error output when the task terminates. +If a pseudofile stream has been redirected by the parent or is to be +redirected by the child, this should be indicated on the command line. +Thus the IRAF Main command +.DS +count < +.DE +would run the program \fIcount\fR, informing the IRAF Main that the standard +input has already been redirected by the parent (some programs need to know). +If redirection to or from a named file is indicated, the IRAF Main will open +the file and redirect the indicated stream before running the program. +Pseudofiles streams are denoted by the numerals 1 through 6, corresponding +to STDIN, STDOUT, STDERR, STDGRAPH, STDIMAGE, and STDPLOT. If output is +being redirected into a new file and \fBT\fR or \fBB\fR appears in the +argument (e.g., "4B>file"), a text or binary file will be created as specified. +If the file type suffix is omitted and the output stream is STDOUT or STDERR +a text file will be created, otherwise a binary file is created. +For example, the command +.DS +count <, > file +.DE +directs the Main to flag the standard input as redirected, open the new text +file "file" as the standard output of the the program \fIcount\fR, and then +run the program. When the program terminates the Main will automatically +close the output file. +.sp +.KS +.ti -0.5i +\fBbye\fR +.sp 0.04i +Commands the subprocess to shutdown and exit. The subprocess must not read +or write the IPC channels once this command has been received; the CL +disconnects the subprocess immediately after sending \fBbye\fR. User +procedures posted with \fBonexit\fR are called during process shutdown. +If an irrecoverable error occurs during normal process shutdown it will cause +an immediate \fBpanic shutdown\fR of the process. The kernel writes an +error message to the process standard error channel (e.g. the user terminal) +when a panic shutdown occurs. +.KE +.sp +.in -1.0i +.PP +Although it might appear that initialization of the process environment +list via a sequence of \fBset\fR commands is inefficient, +the \fBset\fR commands are buffered and transmitted to the child process +in large binary IPC blocks to minimize the overhead. +The amount of data transmitted is not significantly +different than it would be if the environment list were transmitted as a +binary array, and matching of the internal environment list data structures in +the two processes is not required. Furthermore, the \fBset\fR command is +ideal when debugging a process or when running a process in batch mode +with a previously prepared command input file. +.PP +The IRAF Main commands are used both by the CL to run an external compiled +program and by the programmer when debugging a process at the host system +level. The IRAF Main knows whether it is being used interactively or not, +and modifies the interface protocol slightly when used interactively to +provide a better user interface. For example, the Main issues a command +prompt only when being used interactively. The form of a parameter request +and of a pseudofile read or write request is also slightly different in the +two cases. +.PP +The \fBCL requests\fR, i.e., the commands sent by a running program to the CL +(or any other parent process) are shown below. These are the only commands +which the child can legally send to the parent, and hence the only commands the +interpreter in the parent need recognize. The noninteractive syntax is shown. +If the parent process is not the CL a completely different protocol can be +used. When a subprocess is run interactively the \fBxmit\fR and \fBxfer\fR +requests are omitted (only the data is sent) and the newline is omitted after a +parameter read request. +.sp +.in 1.0i +.KS +.ti -0.5i +\fIparam\fR = +.sp 0.04i +The parent process is directed to print the single-line value of the +named parameter in ASCII on the child's input IPC channel. The child +decodes the response line and returns a binary value to the program. +.KE +.sp +.KS +.ti -0.5i +\fIparam\fR = \fIvalue\fR +.sp 0.04i +The parent process is directed to set the value of the named parameter to +the indicated ASCII value. The child does not expect a response, and parameter +write requests may be queued in the output IPC channel. +.KE +.sp +.KS +.ti -0.5i +\fBxmit\fR (\fIpseudofile\fR, \fInchars\fR) +.sp 0.04i +The parent process is directed to read exactly \fInchars\fR chars of binary +data from the IPC channel and transmit it without interpretation to the +indicated pseudofile. The child does not expect a response, and pseudofile +write requests may be queued in the output IPC channel. Pseudofiles are +denoted by the numerals 1 through 6, corresponding to STDIN, STDOUT, STDERR, +STDGRAPH, STDIMAGE, and STDPLOT. +.KE +.sp +.KS +.ti -0.5i +\fBxfer\fR (\fIpseudofile\fR, \fImaxchars\fR) +.sp 0.04i +The parent process is directed to read up to \fImaxchars\fR chars of binary +data from the indicated pseudofile and transmit it without interpretation to the +input IPC channel of the child. The binary data block should be preceded +by an ASCII integer count of the actual number of chars in the data block. +.KE +.sp +.KS +.ti -0.5i +\fBbye\fR +.sp 0.04i +Normal program termination. Control is transferred from the +child to the parent. The child returns to the interpreter loop in the +IRAF Main, awaiting the next command from the parent. +.KE +.sp +.KS +.ti -0.5i +\fBerror\fR (\fIerrnum\fR, "\fIerrmsg\fR") +.sp 0.04i +Abnormal program termination. +An irrecoverable error has occurred during the execution of the program +(or of the IRAF Main), and the CL is directed to take an error action for +error number \fIerrnum\fR. The child returns to the interpreter loop in the +IRAF Main, awaiting the next command from the parent. If the error is not +caught and handled by an error handler in a CL script, the error message +\fIerrmsg\fR is printed on the standard error output of the CL and the +child process is commanded to shutdown. +.KE +.sp +.in -1.0i +.NH 3 +Example +.PP +By this point process control probably sounds much more complicated than it +actually is. A brief example should illustrate the simplicity +of the CL/IPC interface. Consider the CL command +.DS +cl> \fBset | match tty\fR +.DE +which prints the values of all environment entries containing the substring +\fBtty\fR. The CL task \fBset\fR is a builtin function of the CL and +hence does not use the IPC interface. We assume that the process +\fBsystem$x_system.e\fR, which contains the program \fImatch\fR, +has already been connected so that it is not necessary to pass the +environment to the child. The traffic over the IPC channels is shown below. +If a running IRAF system is available the process side of this example can +be duplicated by typing \fBecho=yes\fR followed by the command shown above. +.sp 0.08i +.TS +center; +ci ci +l l. +CL Process +.sp +\fBmatch <\fR + \fBpattern=\fR +tty + \fBmetacharacters=\fR +yes + \fBstop=\fR +no + \fBxfer(1,1024)\fR +1024 +\fI(1024 chars of data sent to child)\fR + \fBxfer(1,1024)\fR +368 +\fI(368 chars of data sent to child)\fR + \fBxmit(2,63)\fR + \fI(63 chars of data sent to CL)\fR + \fBbye\fR +.TE +.sp 0.08i +.PP +Each line of text shown in the example is transmitted through the appropriate +IPC channel as a single distinct record. Commands are shown in boldface. +The italicized records represent raw data blocks. +The process \fBsystem$x_system.e\fR contains the fifty or so executable programs +in the \fBsystem\fR package and hence is a good example of the use of +multitasking and the process cache to minimize process connects (as well as +disk space for executable images). +.NH 3 +Background Jobs +.PP +IRAF process control does not support fully asynchronous subprocess execution +for the following reasons: +.sp +.RS +.IP \(bu +The parent and child processes are tightly bound, i.e., while an external +program is executing the CL process is subservient to the applications program. +The fact that the CL is a separate process is an irrelevant detail to +the applications program. From the point of view of the applications program +the CL is a database interface called by CLIO. Applications programs are not +fully functional unless connected to a CL at run time, and a synchronous, +interactive interface between the two processes is assumed. +.IP \(bu +From the point of view of the user or of a CL script, external programs are +subroutines. Subroutines execute serially in the context of the calling +program. In this case the context is defined by the state of the data +structures of the CL, i.e., the dictionary, environment list, loaded packages +and tasks, parameters, and so on. +.IP \(bu +The user does not care whether a task is a subprocess or a CL script, +and tends to think in terms of \fBcommand blocks\fR rather than individual +commands. A command block is a user specified sequence of commands to +be compiled and executed as a single unit. Asynchronous subprocesses +are not interesting; what we want is an asynchronous command block. +.IP \(bu +It is much more difficult to define a machine independent process control +interface for asynchronous subprocesses than for synchronous subprocesses. +The problem is similar to that of designing +a multiprocessing operating system, with the CL acting as the operating system +kernel and the user as the cpu. Asynchronous subprocess execution is +inconsistent with the conceptual model of subprocesses and users as command +files, and is extremely difficult to implement in a portable system in any case. +.RE +.sp +.PP +For these and other reasons, background job execution is implemented in +IRAF by spawning a copy of the foreground CL which executes as a +\fBdetached process\fR, rather than as a connected subprocess. +The child CL manages its own process cache independently of the parent. +All connected subprocesses execute synchronously, i.e., only one process +in a tree of connected processes may be active at a time. +Since the child is never connected to the parent, the background CL may +execute at any time (e.g. in a batch queue), and may continue to execute +after the parent process has terminated (if the host system permits). +.PP +The child CL inherits the data structures of the parent as they existed +immediately after translating the command block into metacode and just prior +to execution. The parent's data structures are propagated to the child by +writing them into a binary file which is subsequently opened and read by the +child. Open files are not inherited. The command block executes in the +child in exactly the same context as it would have had if executed in the +parent, with exactly the same results. +.PP +On many systems background job execution will be predominantly noninteractive, +particularly if background jobs are placed into a batch queue. +Even if a background job is run noninteractively, however, there is no +guarantee that the job will not require interaction during execution, +for example if the user forgot to set the value of a parameter when the +job was submitted. Rather than aborting a background job which needs to +query for a parameter, the CL provides a limited but portable method for +servicing queries from background jobs. Extensive interaction with background +jobs is beyond the capabilities of the portable IRAF system but is not ruled +out; interfacing to \fBwindow management\fR facilities is straightforward +if the host system provides such facilities, and is described in the next +section. +.PP +The CL has a builtin capability for generating and servicing queries from +noninteractive background jobs. Such queries might be normal and expected, +e.g. if a background job executes concurrently with the interactive CL and +limited interaction is desired, or might be a failsafe, e.g. if a background +job has consumed several hours of cpu time and the job would have to be +resubmitted if it were to abort because it could not satisfy a parameter +request. +.PP +The CL will automatically initiate a query request sequence whenever it is +executing in the background and an attempt to service a query by reading +from the process standard input returns EOF. To initiate a query request +the CL writes the query prompt into a \fBservice request file\fR, +writes a status message to the standard error output of the CL process +noting that the job is stopped waiting for parameter input, +and enters a loop waiting for the \fBquery response file\fR to be created. +When the query response file becomes accessible the CL opens it, +reads the contents to satisfy the original read request, +deletes the file, and continues normal execution. +.PP +If there is no response the background CL will eventually timeout, writing +a fatal error message to the standard error output of the process. +Queries from background jobs are normally satisfied from an interactive CL +using the builtin task \fBservice\fR, which types the service request file +on the terminal, deletes the file, reads the user's response from the terminal, +and writes the response into the query response file. +If the query response is unacceptable another query will be generated and +the interchange is repeated. The use of simple text files for interprocess +communication makes the technique very general, and in principle there is +nothing to prevent the technique from being used to service requests from +jobs run either as detached subprocesses or in batch queues. +.NH 3 +The Process and IRAF Mains +.PP +The roles of the Process and IRAF Mains should already be clear from the +previous sections. The process main is machine dependent and is called by +the host operating system when a process is executed. The IRAF Main is +a portable SPP procedure which is called by the process main +during process startup, which acts as a simple command interpreter during +process execution, and which returns control to the process main during +process shutdown. +.NH 4 +The Process Main +.PP +The \fBprocess main\fR is a part of the kernel, but unlike any other kernel +procedure it is not Fortran callable (in fact it is not necessarily a procedure +at all). The process main further differs from any other kernel procedure +in that it calls a high level procedure, the IRAF Main. Since the process +main is not Fortran callable, however, there is no possibility of recursion. +.PP +The primary functions of the process main are to open and initialize the +process i/o channels and to call the IRAF Main. +The process i/o channels are the standard input, standard output, and standard +error output of the process. The process or device to which the channels +are connected is both system dependent and dependent on how the process was +spawned. +.PP +The process main can be coded in assembler if necessary on almost any system. +Typically the host operating system will upon process entry transfer control +to a predefined address or external identifier, and this entry point should be +the process main. On many modern systems it will be possible to code the +main in a high level language; this is desirable provided the high level +language does not have a main of its own which necessitates loading a lot +of extraneous code which will never be used (since IRAF does all i/o via +the IRAF kernel). On a UNIX system, for example, the process main is +implemented as the C procedure "main" with no overhead, so there is nothing +to be gained by coding the process main in assembler. +.sp +.cs 1 18 +.nf +\fBprocedure\fR process_main + +input_chan: process standard input channel +output_chan: process standard output channel +errout_chan: process standard error output channel + +\fBbegin\fR + # Determine type of output device and connect channels. + + \fBif\fR (we are a connected subprocess) { + connect input_chan and output_chan to IPC channels + connect errout_chan to the user terminal (i.e, to the + standard error output channel of the parent process) + + } \fBelse if\fR (we are a detached process) { + \fBif\fR (window management facilities are available) + connect all channels to window manager + \fBelse\fR { + connect input_chan such that a read will return EOF + \fBif\fR (we are executing in a batch queue) + connect output channels to files + \fBelse\fR { + connect both output_chan and errout_chan to the user + terminal (i.e, to the standard error output channel + of the parent process, if the terminal can be + written to by multiple processes) + } + } + + } \fBelse if\fR (we were run from the host command interpreter) { + \fBif\fR (we were called interactively) + connect channels to user terminal + \fBelse\fR { + connect input_chan and output_chan to job input + and output files, and errout_chan to operator + console or system dayfile. + } + } + + # Call the IRAF Main, the command interpreter or driver of an + # IRAF process. + + call iraf_main, passing the channel numbers and identifying + the driver and protocol to be used by the Main + + # We get here only after the parent has commanded the IRAF + # Main to shutdown, and after shutdown has successfully + # completed. Fatal termination occurs elsewhere. + + close channels if necessary + normal exit, i.e., terminate process +\fBend\fR +.cs 1 +.fi +.sp +.PP +An IRAF process may easily be used in a completely batch mode by connecting +the process channels to text files. On an interactive system the channels +of a detached process may be connected directly to the user terminal, +but it can be annoying for the user if background processes are intermittently +writing to the terminal while the user is trying to do something else +(e.g. trying to edit a file using a screen editor). Having multiple processes +trying to simultaneously read from a terminal is disastrous. +.PP +The best solution to the problem of multiple processes trying to read or +write from the user terminal is some sort of \fBwindow manager\fR. +A simple window manager which can handle output from multiple simultaneous +IRAF processes but which will only allow a single process to read is not +difficult to code on many systems, provided one admits that the capability +is machine dependent. A full up window manager such as is provided on many +modern microcomputers is a much more difficult problem and should not be +attempted as an add-on, as it really needs to be integrated into the +operating system to work well. A better approach is to buy a microcomputer +which comes with a bit-mapped terminal and a fully integrated window manager, +or to buy a smart terminal which has window management capabilities. +.PP +If a window manager is to be provided as an add-on to a system which does +not already have one, it should be implemented as a single process handling all +i/o to the terminal. The CL will be run from the window manager process +and detached processes will talk directly to the window manager process +using multiplexed IPC channels. Such an add-on window manager is unlikely +to be fully usable for non-IRAF processes (e.g. the host system screen editor) +unless the host operating system is modified in fundamental ways. If the +window manager has to be built from scratch consider coding it as an IRAF +process with an extended system interface, so that it will be at least +partially portable. +.NH 4 +The IRAF Main +.PP +The IRAF Main is the "main program" of an IRAF process. The primary function +of the Main is to interpret and execute commands from the standard input +of the CL process (the stream CLIN) until either EOF is seen or the command +\fBbye\fR is received by the Main (as opposed to a program called by the Main). +The Main is mechanically generated by the SPP compiler when the \fBtask\fR +statement is encountered in an SPP program; the source is in the file +\fBmain.x\fR in the logical directory \fBsys$system\fR. +.PP +The secondary functions of the Main are to initialize the IRAF i/o system +and participate in error recovery. The first time the Main is called it +initializes the i/o system and posts a default set of \fBexception handlers\fR. +The Main can only be called again (without recursion) during an \fBerror +restart\fR. If an irrecoverable error occurs during error restart, +a panic exit occurs, i.e., the process dies. +.PP +Error restart takes place when a uncaught hardware or software exception +occurs, or when an error action is taken by a program and no user +\fBerror handler\fR is posted. All exceptions and errors may ideally be +caught and processed by a user exception handler or error handler, without error +restart occurring. When error restart occurs the hardware stack is +reset and control transfers to the marked position within the process main. +The process main calls the IRAF Main, which knows that it has been called +during error restart. +.PP +When the IRAF Main is called during error restart the first thing it does +is call any user procedures posted with \fBonerror\fR. If an irrecoverable +error occurs during execution of an \fBonerror\fR error recovery procedure, +\fBerror recursion\fR occurs and a panic exit results. +When the \fBonerror\fR procedures have successfully executed the Main sends +the \fBerror\fR statement to the CL (i.e., to the stream CLOUT) and reenters +its interpreter loop, awaiting the next command from the CL. +If no user error handler is posted at the CL level (error handling was not +implemented at the CL level at the time when this was written), then the +CL will direct the child process to shutdown to ensure that dynamic memory +space is reclaimed, and to ensure that a user program is not left in a bad +state by the error. +.NH 3 +Process Control Primitives +.PP +We are now in a position to define and understand the kernel primitives +necessary to implement process control. There are 9 such primitives, +excluding the process main and the exception handling primitives. +The mnemonic "pid" refers to the \fBprocess id\fR, a unique magic integer +assigned by the host operating system at process creation time. +.sp 0.08i +.TS +center; +cb s +n l. +Process Control Primitives +.sp +zopcpr \&(process, inchan, outchan, pid) open connected subprocess +zclcpr \&(pid, exit_status) close connected subprocess +zintpr \&(pid, exception, status) interrupt connected subprocess +.sp +zopdpr \&(process, bkgfile, jobnum) open or queue detached process +zcldpr \&(jobnum, killflag, exit_status) close or dequeue detached process +.sp +zgtpid \&(pid) get process id of current process +zpanic \&(errcode, errmsg) panic exit +zsvjmp \&(jumpbuf, status) save process status +zdojmp \&(jumpbuf, status) restore process status +.TE +.sp 0.08i +.PP +Separate sets of primitives are defined for connected and detached +subprocesses. A subprocess is connected with \fBzopcpr\fR, which spawns +the subprocess and opens the IPC channels. The child is assumed +to inherit the current working directory of the parent. +Connection of the IPC channels to FIO and transmission of the environment +list to the subprocess is left to the high level code. +.PP +A connected subprocess is disconnected with \fBzclcpr\fR, which waits +(indefinitely) for the subprocess to exit and returns the exit status code, +e.g. OK. The high level code must command the subprocess to shutdown +before calling \fBzclcpr\fR or deadlock will occur. +The high level code guarantees that \fBzclcpr\fR will be called to close +any subprocess opened with \fBzopcpr\fR. The \fBzintpr\fR primitive +raises the interrupt exception X_INT in a connected subprocess. +.PP +A detached process is spawned or submitted to a batch queue with \fBzopdpr\fR. +It is up to \fBzopdpr\fR to pass the name of the background file on to the +child by some means (the background file tells the detached process what +to do). A detached process may be killed or removed from the batch queue +by a call to \fBzcldpr\fR. The high level code will call \fBzcldpr\fR if +the detached process terminates while the parent is still executing, +but there is no guarantee that a detached process will be closed. +.PP +The remaining primitives are used by all processes. The \fBzgtpid\fR primitive +returns the process id of the process which calls it; this is useful for +constructing unique temporary file names. The \fBzpanic\fR primitive is +called when error recovery fails, i.e., when an error occurs during error +recovery, causing error recursion. A panic shutdown causes immediate process +termination, posting an error message to the process standard error output +and returning an integer error code to the parent process. +.PP +The IRAF main calls \fBzsvjmp\fR to save the process control status for +error restart. The process status is saved in \fIjumpbuf\fR, +allowing several jump points to be simultaneously defined. +A subsequent call to \fBzdojmp\fR restores +the process status, causing a return from the matching \fBzsvjmp\fR call +\fIin the context of the procedure which originally called \fBzsvjmp\fR. +The \fIstatus\fR argument is input to \fBzdojmp\fR and output by \fBzsvjmp\fR, +and is zero on the first call to \fBzsvjmp\fR, making it possible for the +procedure which calls \fBzsvjmp\fR to determine how it was entered. +These extremely machine dependent routines are patterned after the UNIX +\fBsetjmp\fR and \fBlongjmp\fR primitives, but are Fortran callable. +They will almost certainly have to be written in assembler since they fiddle +with the hardware stack and registers. +.PP +On a \fBmultiple processor\fR system it should be possible to spawn both +connected and detached processes on a remote processor. For example, +if the parent process resides on a diskless node in a cluster, it may be +desirable to run subprocesses that do heavy i/o on the remote file server +processor which has a high i/o bandwidth to disk. On such a system +advice on the optimal processor type should be encoded as extra information +in the process file name passed to \fBzopcpr\fR or \fBzopdpr\fR; this will +require modification of the CL \fBtask\fR statement for such processes. + +.NH 2 +Exception Handling +.PP +An exception is an asynchronous event, i.e., an interrupt. +Typical \fBhardware exceptions\fR are an attempt to access an unmapped region +of memory, illegal instruction, integer overflow, or divide by zero. +A hardware exception occurs when the hardware detects an error condition +while executing a hardware instruction. Typical \fBsoftware exceptions\fR are +interrupt and kill. A software exception occurs when a program, e.g., +the terminal driver or an applications program like the CL, sends an +interrupt or \fBsignal\fR to a process. When an exception occurs program +execution is interrupted and control transfers to an \fBexception handler\fR, +i.e., to a previously posted system or user procedure. +.PP +The ability to post an exception handler or to send a signal to a process +is fundamental in any multiprocessing operating system, but regrettably there +are still some older systems that do not make such facilities available to +applications code. Hopefully yours is not such a system. Even if a system +provides exception handling facilities, the set of exceptions defined for +a particular computer or operating system is very system dependent. +Exception handling can be subtly machine dependent, e.g., it is not always +possible to disable an exception, and it is not always possible to resume +program execution (restart the interrupted instruction) following an exception. +.PP +The IRAF Main posts a default set of exception handlers during process startup. +All host system exceptions that might occur during the execution of an IRAF +process should be catchable by one of the default exception handlers. +If an exception is not caught and is instead handled by the host, +the process will almost certainly die without the knowledge of the CL, +leading at best to a cryptic "write to a subprocess with no reader" error +message, and at worst to deadlock. Since error recovery and process shutdown +will be skipped if an uncatchable exception occurs, disk data structures may +be corrupted. +.PP +The virtual system recognizes only four classes of exceptions; all possible +host system exceptions should either be mapped into one of these exceptions +or caught in the kernel and mapped into ERR. +.sp 0.08i +.TS +center box; +cb s s +ci | ci | ci +l | c | l. +Virtual Machine Exceptions +_ +exception code meaning += +X_ACV 501 access violation +X_ARITH 502 arithmetic error +X_INT 503 interrupt +X_IPC 504 write to IPC with no reader +.TE +.sp 0.08i +.PP +The largest class of exceptions on many systems will be the access violations. +This class includes such things as illegal memory reference, illegal +instruction, illegal system call, and so on. +Arithmetic exceptions include divide by zero, integer overflow, and the like. +Interrupt is the exception raised by \fBzintpr\fR or by the +host system terminal driver when the interrupt sequence is typed (e.g. ctrl/c). +.sp 0.08i +.TS +center; +cb s +n l. +Exception Handling Primitives +.sp +zxwhen \&(exception, handler, old_handler) post an exception +zxgmes \&(os_exception, outstr, maxch) get OS code and message +.TE +.sp 0.08i +.PP +An exception handler is posted for a virtual exception with the primitive +\fBzxwhen\fR. All host exceptions in the indicated virtual exception class +are affected. The argument \fIhandler\fR is either the entry point address +of the new user exception handler or the magic value X_IGNORE (null). +The address of the old handler or X_IGNORE is returned as the third argument, +making it possible for the high level code to chain exception handlers +or repost old exception handlers. The calling sequence for a user exception +handler is as follows: +.DS +user_handler (exception, next_handler) +.DE +.LP +The user exception handler is called with the integer code for the actual +virtual exception as the first argument. The integer code of the last +machine exception and a packed character string describing the exception +may be obtained by a subsequent call to \fBzxgmes\fR. A program which uses +a machine exception code is machine dependent, but machine exception codes +can be parameterized and some programs need to know. +The CL, for example, has to be able to recognize the machine exception for +a write to a process (an IPC channel) with no reader. +.PP +When an exception occurs control actually transfers to the \fBkernel exception +handler\fR, which maps the machine exception into a virtual exception, +looks at the kernel exception table to determine what type of action is +required, and then calls the user exception handlers. A user exception +handler is expected to handle the exception in some application dependent +way and then either change the process context by calling \fBzdojmp\fR or +\fBzrestt\fR, or return control to the kernel exception handler. +If control returns to the kernel handler the output argument \fBnext_handler\fR +will contain either the entry point address of the next exception handler +or X_IGNORE. The high level code assumes that once an exception handler +is posted it stays posted, i.e., is not reset when an exception occurs. +.PP +Few programs actually post exception handlers; most just post an error handler +with \fBonerror\fR. Such an error handler will be called by the IRAF Main +either when an exception occurs or when an error action is taken, i.e., +when a program is aborted for whatever reason. If a user exception handler +is not posted the default handler will be called, causing error restart of the +Main, calls to all \fBonerror\fR procedures, and transmission of the \fBerror\fR +statement to the CL. If the CL is interrupted while executing an external +program it passes the interrupt on to the child with \fBzintpr\fR and then +resumes normal processing. The external program retains control, and therefore +can choose to either ignore the interrupt or take some application dependent +action. + +.NH 2 +Memory Management +.PP +The IRAF system relies heavily on memory management for dynamic buffer +allocation in both system and applications software. +Both stack and heap storage are provided at the program interface level. +The \fBstack\fR is used primarily for "automatic" storage allocation, +i.e., for buffers which are allocated upon entry to a procedure and deallocated +upon exit from the procedure. Stack management incurs very little overhead +for small buffers. The \fBheap\fR is a more general storage mechanism; +buffers may be allocated and deallocated in any order, and allocation and +deallocation may occur in different procedures. A heap buffer may be +reallocated, i.e., changed in size. The stack is implemented portably in terms +of the heap, and hence need not concern us further here. +.sp 0.08i +.TS +center; +cb s +n l. +Memory Management Primitives +.sp +zmaloc \&(buffer, nbytes, status) allocate a buffer +zmfree \&(buffer, status) deallocate a buffer +zraloc \&(buffer, nbytes, status) reallocate a buffer +zlocva \&(variable, address) get address of a variable +zawset \&(bestsize, newsize, oldsize, textsize) adjust working set size +.TE +.sp 0.08i +.PP +Buffer space is allocated on the heap by the primitive \fBzmaloc\fR. +The address of a buffer at least \fInbytes\fR in size is returned +as the argument \fIbuffer\fR. Nothing is assumed about the alignment of +the buffer. The contents of the buffer are not assumed to be initialized. +.PP +The buffer address returned by \fBzmaloc\fR is in units of SPP \fBchars\fR +rather than in physical units. The \fBzlocva\fR primitive returns the +address of a \fBcsilrd\fR variable, array, or array element in the same +units. By using char address units and by doing all pointer dereferencing +by subscripting Fortran arrays, we avoid building knowledge of the memory +addressing characteristics of the host system into SPP programs. +The zero point of a char address is undefined; negative addresses are +possible depending on the implementation. It must be possible to store an +address in an integer variable, and it must be possible to perform +\fIsigned integer\fR comparisons and arithmetic on addresses. +.PP +A buffer allocated with \fBzmaloc\fR may be reallocated with \fBzraloc\fR. +In this case the \fIbuffer\fR argument is used both for input and for output. +If the input value is NULL a new buffer should be allocated, otherwise the +size of the buffer should be either increased or decreased depending on the +value of \fInbytes\fR. The buffer may be moved if necessary, provided the +contents of the buffer are preserved. This primitive may be implemented as +a call to \fBzmaloc\fR followed by an array copy and a call to \fBzmfree\fR +if desired, saving one kernel primitive, with significant loss of efficiency +in some applications. +.PP +A buffer allocated with \fBzmaloc\fR is deallocated with \fBzmfree\fR. +Deallocation need not involve physically returning memory pages to the +operating system; if the buffer is small this will not be possible. The buffer +being deallocated need not be at the end of the process address space. +.PP +The \fBzlocva\fR primitive returns the address in char units of the first +argument as the integer value of the second argument. Since Fortran is +call by reference, this is a simple matter of copying the pointer to the +first argument (as opposed to the value pointed to) to the integer location +pointed to by the second argument. +Only arguments of datatypes \fBcsilrd\fR are permitted in calls to \fBzlocva\fR. +Arguments of Fortran type COMPLEX, CHARACTER, and EXTERNAL are sometimes passed +using more than one physical argument (depending on the host compiler) +and hence cannot be used in procedures that operate upon an arbitrary datatype. +.PP +The \fBzawset\fR primitive is used both to determine and to change the amount +of physical memory in machine bytes available to a process, i.e., the +\fBworking set size\fR on a virtual memory machine. +If called with a \fIbestsize\fR of zero the current working set size and text +segment size is returned. If called with nonzero \fIbestsize\fR on a +virtual memory machine the working set size will be adjusted up or down +as indicated, returning the actual new working set size in \fInewsize\fR +and the old working set size in \fIoldsize\fR. +It is not an error if the amount of memory requested cannot be allocated; +the high level code will ask for what it wants but take what it gets. +High level routines which need lots of memory rely on this primitive to +avoid running out of memory on nonvirtual machines and to avoid thrashing +on virtual machines. +.PP +The high level code (\fBmalloc\fR) converts the address returned +by the kernel primitives into an integer valued offset (array index) into +the \fBMem\fR common. +The dynamically allocated buffer (which has nothing to do with the Mem common) +is referenced by indexing off the end of an \fBMem\fR array. +The portable MEMIO code ensures alignment between the physical buffer and +the "pointer" returned to the user (index into Mem). This technique should +work on any machine which permits referencing off the end of an array. +.PP +There is one place in the system code, however, which does something trickier +and which should be checked on a new system. +The \fBstropen\fR routine in FIO uses the +same pointer technique (for efficiency reasons) to reference a \fIstatically\fR +allocated \fBchar\fR array in the user program. If the compiler does not +guarantee that a statically allocated \fBchar\fR array will be aligned with +the array \fBMemc\fR in the Mem common this will not work, +and \fBstropen\fR will have to be modified. +.NH 2 +Procedure Call by Reference +.PP +Fortran allows an external procedure to be passed by reference to a +subprogram via the subprogram argument list. An external procedure passed +as an argument to a subprogram may be called by the subprogram but may not be +saved and called at some later time. IRAF (e.g. FIO and IMIO) requires the +capability to save a reference to a procedure in an integer variable for +execution at some later time. +.PP +The \fBzlocpr\fR primitive is used to determine the entry point address +(EPA) of an external procedure. IRAF assumes that the EPA of a procedure +may be stored in an integer variable and that two procedures with the same +EPA are identically the same procedure. No other operations are permitted +on EPA values, e.g., signed comparisons and arithmetic are not permitted. +.sp 0.08i +.TS +center; +cb +n. +Call by Reference Primitives +.sp +zlocpr \&(proc, entry_point_address) get address of a procedure +zcall1 \&(procedure, arg1) +zcall2 \&(procedure, arg1, arg2) +zcall3 \&(procedure, arg1, arg2, arg3) +zcall4 \&(procedure, arg1, arg2, arg3, arg4) +zcall5 \&(procedure, arg1, arg2, arg3, arg4, arg5) +.TE +.sp 0.08i +.PP +A \fBzcall\fIn\fR primitive is used to call an external subroutine +referenced by the integer variable \fIprocedure\fR, the entry point address +of the procedure returned in a prior call to \fBzlocpr\fR. +Only subroutines may be called by reference; there is no comparable facility +for functions. The datatypes of the arguments are unspecified but are +restricted to the SPP datatypes \fBcsilrd\fR. + +.NH 2 +Date and Time +.PP +Kernel primitives are required to read the system clock, to determine the +amount of cpu time consumed by a process (for performance measurements), +and to generate time delays. +.sp 0.08i +.TS +center; +cb s +n l. +Date and Time Primitives +.sp +zgtime \&(local_time, cpu_time) get clock time and cpu time +ztslee \&(delay) countdown timer +.TE +.sp 0.08i +.PP +The \fBzgtime\fR primitive returns two long integer arguments. The local +standard time in integer seconds since midnight on January 1, 1980 is +returned as the first argument (the "clock" time). The second argument +is the total cpu time consumed by the process since process execution, +in units of milliseconds. The countdown timer primitive \fBztslee\fR +suspends execution of the calling process for the specified number of +integer seconds. There is currently no provision for generating delays +of less than one second. + +.NH 2 +Sending a Command to the Host OS +.PP +The ability to send an explicitly machine dependent command to the host +system command interpreter is required by the CL and by some of the system +utilities. Any program which uses this command is bypassing the system +interface and is system dependent. Nonetheless it is very useful for the +\fIuser\fR to be able to send a command to the host without leaving the +IRAF environment, and certain of the system utilities are much easier to +code given the capability (e.g., \fBdiskspace\fR and \fBspy\fR). These +utilities help provide a consistent user interface on all systems, and in +many cases such a utility program can be built in a few minutes for a new +system. No science program or essential system utility bypasses the system +interface in this fashion. +.sp 0.08i +.TS +center; +cb s +n l. +Host OS Command Primitive +.sp +zoscmd \&(cmd, stdout, stderr, status) send a command to the host OS +.TE +.sp 0.08i +.PP +The command \fIcmd\fR may be any packed string acceptable to the host +system. The call does not return until the command has been executed. +The status OK or ERR is returned indicating success or failure. +If either of the filename strings \fIstdout\fR or \fIstderr\fR is nonnull +the associated output stream of the command will be directed (if possible) +to the named text file. + +.NH +Bit and Byte Primitives +.PP +The bit and byte primitives are not considered true kernel procedures since +they are purely numerical and are only potentially machine dependent. +These primitives are more properly part of the \fBprogram interface\fR than +the kernel, since they are callable from ordinary applications programs. +Both SPP or Fortran and C versions of most of the routines are supplied +with the system which will port to most modern minicomputers and some large +computers. The source directory is \fBsys$osb\fR. +The following classes of routines are required: +.sp 0.05i +.DS +\(bu bitwise boolean operations (and, or, etc.) +\(bu bitfield insertion and extraction +\(bu byte primitives (copy, swap, string pack/unpack) +\(bu type conversion for byte, unsigned short datatypes +\(bu machine independent integer format conversions +.DE +.sp 0.05i +.PP +The IRAF system uses 8 standard datatypes in compiled SPP programs, +as shown in the table below. Variables and arrays may be declared and +accessed conventionally using any of these datatypes. Data may additionally +be stored on disk, in images, and in memory in packed char or integer arrays +in the exotic datatypes \fBunsigned byte\fR, \fBunsigned short\fR, +and \fBpacked string\fR. +.sp 0.08i +.TS +center box; +cb s s +ci | ci | ci +lb | c | l. +Standard SPP Datatypes +_ +name suffix Fortran equivalent += +bool b LOGICAL +char c nonstandard +short s nonstandard +int i INTEGER +long l nonstandard +real r REAL +double d DOUBLE PRECISION +complex x COMPLEX +.TE +.sp 0.08i +.PP +The char and short datatypes are commonly implemented as INTEGER*2, +and long as INTEGER*4, but all could be implemented as the standard +INTEGER if necessary. To save space char may be implemented using a +signed byte datatype if the host Fortran compiler provides one, +provided the special datatype chosen may be equivalenced with the +standard datatypes (the minimum precision of a char is 8 bits signed). +IRAF assumes that the 7 types \fBcsilrdx\fR may be equivalenced in common +(e.g. in \fBMem\fR). The standard type suffixes \fBbcsilrdx\fR are +commonly appended to procedure names to identify the datatype or datatypes +upon which the procedure operates. +.NH 2 +Bitwise Boolean Primitives +.PP +The bitwise boolean primitives are used to set and clear bits or bitfields +in integer variables. The practice is portable provided the minimum +precision of an integer variable (16 bits) is not exceeded. Primitives +are provided for the 3 integer datatypes, i.e., short, int, and long, +denoted by the suffix \fB[sl]\fR in the table below. In other words, +the notation \fBand[sl]\fR refers to the procedures \fBands\fR and \fBandl\fR. +These quasi-primitives, unlike the true kernel primitives, are user callable +and are implemented as \fIfunctions\fR. +.sp 0.08i +.TS +center; +cb s +n n. +Bitwise Boolean Primitives +.sp +and,and[sl] \&(a, b) int = and \&(a, b) +or,or[sl] \&(a, b) int = or \&(a, b) +xor,xor[sl] \&(a, b) int = xor \&(a, b) +not,not[sl] \&(a, b) int = not \&(a, b) +.TE +.sp 0.08i +.PP +Bitwise boolean primitives are provided in many Fortran compilers +as integer intrinsic functions. If this is the case it suffices (and +is more efficient) to place a \fBdefine\fR statement in \fBiraf.h\fR to +map the IRAF name for the function to that recognized by the host Fortran +compiler. For example, +.DS +\fBdefine\fR and iand +.DE +would cause all occurrences of the identifier \fBand\fR in SPP programs to +be replaced by \fBiand\fR in the Fortran output, which the host compiler +would hopefully compile using inline code. +.NH 2 +Bitfield Primitives +.PP +A \fBbitfield\fR is an unsigned integer segment of a bit array, where the +number of bits in the segment must be less than or equal to NBITS_INT, +the number of bits in an integer. A \fBbit array\fR is a sequence of +bits stored one bit per bit in a char or integer array. The essential +thing about a bit array is that byte and word boundaries are irrelevant, +i.e., a bitfield may straddle a word boundary. +.sp 0.08i +.TS +center; +cb s +n n. +Bitfield Primitives +.sp +bitpak \&(intval, bit_array, bit_offset, nbits) integer \(-> bitfield +int = bitupk \&(bit_array, bit_offset, nbits) bitfield \(-> integer +.TE +.sp 0.08i +.PP +Bit offsets range from 1, not 0, to MAX_INT. A bitfield is zero-extended +when unpacked by \fBbitupk\fR, and unset bits are zeroed when an integer +is packed into a bitfield by \fBbitpak\fR. If the integer is too large +to fit in the bitfield it is truncated. These primitives should be +implemented in assembler on a machine like the VAX which has bitfield +instructions. +.NH 2 +Byte Primitives +.PP +The byte primitives are difficult to use portably in high level code +without building knowledge of the sizes of the SPP datatypes in bytes +into the code. Fortunately the byte primitives are rarely used; the most +common usage is in programs used to transport data between machines (e.g., +a magtape reader program). A number of machine constants are defined +in \fBiraf.h\fR to allow parameterization of programs which operate on +data in units of bytes. +.sp 0.08i +.TS +center box; +cb s +ci | ci +l | l. +Machine Parameters for Byte Data +_ +name definition += +SZB_CHAR machine bytes per char +NBITS_BYTE nbits in a machine byte +SZ_\fItype\fR size of datatype \fItype\fR (upper case) in chars +.TE +.sp 0.08i +.PP +On most machines the byte primitives can be written in Fortran by +representing a byte array as an array of CHARACTER*1. This suffices for +programs which merely move bytes around, but not for programs which +do numerical comparisons and arithmetic operations upon character data +using CHAR and ICHAR, because the collating sequence for CHARACTER data +in Fortran is not necessarily ASCII. +.PP +Nonetheless CHAR and ICHAR can be used on most machines to operate upon bytes, +i.e., upon non-CHARACTER data stored in CHARACTER*1 arrays. +Of course we are asking for trouble using CHARACTER for non-CHARACTER +operations, so routines which do so are potentially machine dependent. +Both Fortran and C versions of most of the byte primitives are supplied. +The \fBbytmov\fR primitive should be written in assembler on a machine such +as the VAX which can perform the operation in a single instruction +(it is even more important to perform this optimization for the \fBamov\fR +vector operators, which are more widely used). +.sp 0.08i +.TS +center; +cb s +n l. +Byte Primitives +.sp +bytmov \&(a, aoff, b, boff, nbytes) move an array of bytes +bswap2 \&(a, b, nbytes) swap every pair of bytes +bswap4 \&(a, b, nbytes) swap every 4 bytes +chrpak \&(a, aoff, b, boff, nchars) pack chars into bytes +chrupk \&(a, aoff, b, boff, nchars) unpack bytes into chars +strpak \&(a, b, maxchars) SPP string \(-> byte-packed string +strupk \&(a, b, maxchars) byte-packed string \(-> SPP string +.TE +.sp 0.08i +.PP +The \fBbytmov\fR primitive moves a portion of a byte array into a portion +of another byte array. The move is nondestructive, i.e., if the input +and output arrays overlap data must not be destroyed. The \fBzlocva\fR +primitive may be used to determine if the arrays will overlap. +Byte swapping is performed by the \fBbswap2\fR and \fBbswap4\fR primitives, +which swap every 2 bytes or every 4 bytes, respectively, regardless of the +number of bytes per short or long integer on the host machine. These routines +are used primarily to swap bytes in interchange data before is it unpacked into +host integers (or after packing into interchange format), hence the primitives +are defined independently of the host word size. A 2 byte swap interchanges +successive pairs of bytes; a 4 byte swap of two 4 byte integers rearranges +the bytes as 12345678 \(-> 43218765. +.PP +The \fBchrpak\fR and \fBchrupk\fR primitives pack and unpack SPP chars +into bytes, performing sign extension in the unpacking operation. +The mapping is nondestructive, i.e., the input and output arrays may +be the same, and the numeric value of a character is not changed +by the mapping (the collating sequence is not changed by the mapping). +If SZB_CHAR is 1, \fBchrpak\fR and \fBchrupk\fR are equivalent, and if +the input and output arrays are the same or do not overlap they are +equivalent to \fBbytmov\fR. +.PP +The \fBstrpak\fR and \fBstrupk\fR primitives pack and unpack SPP strings +into packed strings. A packed string is a sequence of zero or more characters, +packed one character per byte, delimited by end-of-string (EOS). +While SPP strings are always ASCII the collating sequence of a packed string +is whatever is used for character data by the host machine. +The mapping is nondestructive in the sense that the input and output arrays +may be the same. Since the collating sequence may be changed in the mapping +and the mapping need not be one-to-one, information may be lost if an +arbitrary string is packed and later unpacked. +.PP +A packed string is not the same as a Fortran CHARACTER variable or constant. +Many Fortran compilers use two physical arguments to pass a Fortran CHARACTER +argument to a subprocedure, while a packed string is always passed by reference +like an ordinary integer array. There is no machine independent way to fake +a Fortran string in an argument list. Furthermore, packed strings are heavily +used in the kernel for machine dependent filenames, and these file names +typically contain characters not permitted by the restrictive Fortran standard +character set. The packed string format is equivalent to that expected by +the C language. +.NH 2 +Vector Primitives +.PP +Nearly all of the operators in the vector operators package +(VOPS, \fBsys$vops\fR) are machine independent. The exceptions are the +\fBacht\fR primitives used to change the datatype of a vector to or from +one of the special datatypes \fBunsigned byte\fR and \fBunsigned short\fR. +An \fBacht\fR operator is provided for every possible type conversion +in the set of datatypes \fBcsilrdx\fR plus unsigned byte (\fBB\fR) and +unsigned short (\fBU\fR), for a total of 9 squared or 81 operators in all. +The \fBbool\fR datatype is not supported by VOPS. +.PP +Two type suffixes are used to specify the type conversion performed by an +operator; for example, \fBachtir\fR will convert an integer array into a +real array. In the table below the underscore stands for the set of +datatypes \fBUBcsilrdx\fR, hence each the operators shown is actually +a generic operator consisting of 9 type specific operators. +Both C and Fortran sources are provided for all primitives, the C sources +being more efficient. The Fortran operators will work on many hosts +but are potentially machine dependent and should be checked. The C versions +are more efficient since Fortran does not support the unsigned datatypes +and a masking operation must be performed to undo sign extension when +converting from unsigned to signed. +.sp 0.08i +.TS +center; +cb s +n l. +Machine Dependent Vector Primitives +.sp +acht_b \&(a, b, npix) SPP datatype \(-> unsigned byte +acht_u \&(a, b, npix) SPP datatype \(-> unsigned short +achtb_ \&(a, b, npix) unsigned byte \(-> SPP datatype +achtu_ \&(a, b, npix) unsigned short \(-> SPP datatype +.TE +.sp 0.08i +.PP +Many of the conversions do not preserve precision, i.e., double to real +or integer to unsigned byte. The imaginary part of a complex number is +discarded when converting to some other datatype, and the imaginary part +is set to zero when converting a non-complex datatype to complex. +All type conversion operators allow the conversion to be performed in +place, i.e., the input and output arrays may be the same. +.NH 2 +MII Format Conversions +.PP +The Machine Independent Integer format (MII) is used to transport binary +integer data between computers. The format is independent of the transmission +medium, and hence might be used to transport data via magnetic tape, over a +local area network, or over a modem. The MII integer format is equivalent +to that defined by the FITS image interchange format. The MII primitives are +used in the IRAF FITS reader and writer programs and will probably be used +in the GKS (Graphical Kernel System) software to implement a machine +independent VDM (Virtual Device Metafile). +.PP +MII defines 3 integer datatypes, 8 bit unsigned integer, 16 bit twos-complement +signed integer, and 32 bit twos-complement signed integer. An integer array +in MII format may be thought of as a stream of 8-bit bytes. In each 2 and +4 byte integer successive bytes are written in order of decreasing significance. +The sign bit is in the first byte of each 2 or 4 byte integer. For example, +two 16 bit integers would be represented in MII format as the following +sequence of 4 bytes. +.sp 0.08i +.TS +center; +ci ci +l l. +byte significance +.sp +1 high byte of first integer, including sign bit +2 low byte of first integer +3 high byte of second integer, including sign bit +4 low byte of second integer +.TE +.PP +The order of the bits within a byte is (must be) standardized at the +hardware level, else we would not be able to transmit character data via +cardimage tapes and modems. Hence the sign bit is bit 200B (octal) of the +first byte of an MII integer, the most significant bit is bit 100B of the +first byte, and so on. +.sp 0.08i +.TS +center; +cb s +n l. +MII Primitives +.sp +miipak \&(spp, mii, nelems, spp_type, mii_type) SPP \(-> MII +miiupk \&(mii, spp, nelems, mii_type, spp_type) MII \(-> SPP +intlen = miilen \&(n_mii_elements, mii_type) get size of array +.TE +.sp 0.08i +.PP +SPP or Fortran integer data is converted to MII format with \fBmiipak\fR, +and MII data is converted to SPP format with \fBmiiupk\fR. +The argument \fIspp\fR refers to an SPP integer array of datatype +\fIspp_type\fR, and \fImii\fR refers to an MII byte stream of MII datatype +\fImii_type\fR. The legal integer values of \fImii_type\fR are 8, 16, +and 32. MII data is stored in an SPP array of type \fBint\fR. +The length of the SPP integer array required to store \fIn_mii_elements\fR +of MII type \fImii_type\fR is returned by the primitive \fBmiilen\fR. +.PP +An SPP implementation of the MII primitives which should work for all +host machines with 16 or 32 bit twos-complement signed integer datatypes +is supplied with the system. Most modern minicomputers fall into this class. +All one need do to use the supplied MII primitives is determine whether or +not byte swapping is necessary. If the parameter BYTE_SWAP2 is defined +as YES in \fBiraf.h\fR then \fBbswap2\fR will be called to swap 2 byte +MII integers, producing an SPP \fBshort\fR as output. If the parameter +BYTE_SWAP4 is defined as YES then \fBbswap4\fR will be called to swap 4 +byte MII integers, producing an SPP \fBlong\fR as output. +.NH 2 +Machine Constants for Mathematical Libraries +.PP +The most often used machine constants are parameterized in include files +for use within SPP programs. Defined constants are the most readable +and efficient way to represent machine constants, but not the most accurate +for floating point quantities. Furthermore, SPP defined constants cannot +be used within Fortran procedures; functions returning the machine constants +are often used instead. The most widely used set of such functions appears +to be those developed at Bell Laboratories for the \fIPort\fR mathematical +subroutine library. +.sp 0.08i +.TS +center; +cb s +n l. +Mathematical Machine Constants +.sp +int = i1mach \&(parameter) get INTEGER machine constants +real = r1mach \&(parameter) get REAL machine constants +double = d1mach \&(parameter) get DOUBLE PRECISION machine constants +.TE +.sp 0.08i +.PP +These routines are used in many numerical packages, including the IEEE +signal processing routines and the NCAR graphics software. Documentation +is given in the Fortran sources; values of the constants have already been +prepared for most of the computers used at scientific centers. The integer +codes of the machine parameters are parameterized in \fBlib$mach.h\fR for +use in SPP programs. + +.NH +System Parameterization and Tuning +.PP +All machine dependent system and language parameters are defined in the two +SPP include files \fBlib$iraf.h\fR and \fBlib$config.h\fR, in the C include +file \fBcl$config.h\fR, and in the CL script file \fBlib$clpackage.cl\fR. +Additional machine dependent include files will often be used (\fIshould\fR +be used) to implement the kernel for a particular machine but these are too +host specific to be described here. +.PP +The include file \fBlib$iraf.h\fR is automatically loaded by the SPP whenever +an SPP source file is preprocessed, hence the defines in \fBiraf.h\fR are +effectively part of the SPP language. This global include file defines +the language parameters (e.g., EOF, ERR) as well as many machine constants. +The two configuration files \fBlib$config.h\fR and \fBcl$config.h\fR define +additional constants pertaining to the host OS as well as various size limiting +and heuristic parameters used to tune IRAF for optimum performance on a given +host system. The CL script file \fBlib$clpackage.cl\fR contains \fBset +environment\fR declarations for all system directories and default devices. +.PP +Documentation for the individual machine constants and system tuning parameters +is maintained directly in the source files to ensure that it is up to date. +Some of the parameters in \fBconfig.h\fR pertain only to the inner workings +of the program interface and changes can be expected in successive releases +of the IRAF system, without corresponding changes to the external +specifications of the program interface. + +.NH +Other Machine Dependencies +.PP +In the ideal world all of the machine dependence of the system would be +concentrated into the kernel and a few include files. While this has been +achieved for the scientific software some of the system utilities currently +bypass the system interface and are machine dependent. +This is not necessarily a bad thing; if a certain capability is only needed +by one or two system utilities the machine dependence of the system will often +be less if we take the simple way out and write a system dependent program +than if we further expand the formal system interface. +.PP +The machine dependent utilities are in the packages \fBsystem\fR and +\fBsoftools\fR. All machine dependent procedures are listed in the README +files in the package directories. The string MACHDEP is placed in the source +files to mark any machine dependent code segments. The machine dependent +utilities are not essential to the use of the system, but are useful for +maintaining the system. Examples of machine dependent software utilities +include \fBmake\fR, \fBxcompile\fR, and the generic preprocessor. These +utilities will all eventually be replaced by portable programs. +Machine dependent system utilities include \fBallocate\fR and \fBdeallocate\fR, +\fBedit\fR (the interface to the host editor), and \fBdiskspace\fR. +These utilities are actually just command level interfaces to the host +system command interpreter, and are easy to modify for a new host. +.NH 2 +Machine Dependencies in the CL +.PP +As noted earlier, from a structural design point of view the Command Language +is an IRAF applications program; as such it is highly portable. The CL is not +completely portable because it is written in C. Since the CL is written in +C it cannot reference the standard include files \fBiraf.h\fR and +\fBconfig.h\fR, and therefore has its own machine dependent \fBconfig.h\fR +include file instead. Since the CL requires file i/o, process control and +exception handling, formated i/o, the TTY interface, etc., it is interfaced +to the IRAF program interface (the CL has a special Main of its own but this +is portable). +.PP +The C code in the CL is purely numeric, like the Fortran in SPP based +applications programs. All communication with the host system is via the +IRAF program interface. The program interface is written in SPP, i.e., +Fortran, and Fortran procedures +cannot portably be called from C (see \(sc3.1.2). To render the bulk of the +code portable a special C callable subset of the program interface is +defined for the CL, and all CL calls to program interface routines are via +this interface. Efficiency is not a problem because the CL does little i/o; +the CL is the control center of the system, and tends to be compute bound when +it is not idle waiting for a command. +.PP +In summary, to interface the CL to a new system it is necessary to first edit +the \fBcl$config.h\fR, which parameterizes the characteristics of the host +system and which contains the system tuning parameters affecting the CL. +The CL interface to the subset program interface consists of a set of +rather simple interface procedures in the file \fBcl$machdep.h\fR. +If you are lucky these will not have to be changed to port the CL to your host +computer, but even if the routines have to be modified they are few in number +and quite simple in nature. +.NH +Specifications for the Kernel Procedures +.PP +The remainder of this document consists of a summary of the machine dependent +procedures, followed by the detailed technical specifications for each +procedure. Only the specifications for the kernel primitives are given; +the bitwise boolean primitives are part of the program interface and are +documented elsewhere. Most likely either the Fortran or C code supplied for +the bitwise primitives will be usable on a new host system without significant +modification. +.PP +While the kernel consists of quite a few procedures, this does not necessarily +mean that it is going to be harder to implement than if there were only a +quarter or a third as many procedures. Our design goal was to minimize the +complexity and size of the kernel, and we felt that it was more important to +define simple, single function primitives than to minimize the \fInumber\fR +of primitives. +.PP +A large part of the kernel consists of device driver +subroutines; on a system which provides device independent i/o these may map +to the same low level procedures and a count of the number of driver +subroutines will have little meaning. On a system which does not have device +independent i/o it will be easier to implement separate procedures for each +device than to try to make the host system look like it has device independent +i/o (FIO already does that anyhow). Furthermore, the provision for separate +drivers makes it easy to optimize i/o for a particular device, and makes it +possible to dynamically interface new devices to FIO without modifying the +basic system. +.PP +All kernel procedures are called by virtual operating system procedures +in the program interface. The kernel procedures are \fInot\fR callable +directly from applications code. Extensive error checking is performed by +the high level code before a kernel procedure is called, hence error +checking in kernel procedures is largely redundant and should be omitted +if it will significantly compromise performance. Do not get clever +with kernel procedures; \fIkeep it simple\fR. +.sp 0.08i +.TS +center box; +cb s s +ci | ci | ci +l | c | l. +Summary of Kernel Constants +_ +name value usage += +APPEND 4 write at EOF +BINARY_FILE 12 +BOF \(mi3 beginning of file +EOF \(mi2 end of file +EOS '\\\\0' end of string delimiter +ERR \(mi1 function was unsuccessful +FI_DIRECTORY 2 directory file (\fBzfinfo\fR) +FI_EXECUTABLE 3 executable file +FI_REGULAR 1 ordinary file +FI_SPECIAL 4 special file +FSTT_BLKSIZE 1 device block size +FSTT_FILSIZE 2 file size, bytes +FSTT_MAXBUFSIZE 4 maximum transfer size +FSTT_OPTBUFSIZE 3 optimum transfer size +LEN_JUMPBUF ?? integer length of \fBzsvjmp\fR buffer +NEW_FILE 5 create a new file +NO 0 no (false) +OK 0 function successfully completed +PR_CONNECTED 1 connected subprocess +PR_DETACHED 2 detached process +PR_HOST 3 process spawned by host +QUERY_PROTECTION 2 query file protection (\fBzfprot\fR) +READ_ONLY 1 file access modes +READ_WRITE 2 +REMOVE_PROTECTION 0 remove file protection (\fBzfprot\fR) +SET_PROTECTION 1 set file protection (\fBzfprot\fR) +SZ_LINE 161 default textfile line length +TEXT_FILE 11 file types +WRITE_ONLY 3 +X_ACV 501 access violation +X_ARITH 502 arithmetic error +X_INT 503 interrupt +X_IPC 504 write to IPC with no reader +YES 1 yes (true) +.TE +.sp 0.08i + + +.bp +.LG +.ce +\fBSummary of Machine Dependent Procedures\fR +.NL +.sp 2 +.TS +center; +cb s +n l. +Kernel Primitives +.sp +\fBzawset\fR \&(bestsize, newsize, oldsize, textsize) adjust working set size +\fBzcall\fIn\fR \&(procedure, arg1,...,arg\fIn\fR) call by reference +\fBzclcpr\fR \&(pid, exit_status) close connected subprocess +\fBzcldir\fR \&(chan, status) close directory +\fBzcldpr\fR \&(jobcode, killflag, exit_status) close or dequeue detached process +\fBzdojmp\fR \&(jumpbuf, status) restore process status +\fBzfacss\fR \&(osfn, mode, type, status) access file +\fBzfaloc\fR \&(osfn, nbytes, status) preallocate a binary file +\fBzfchdr\fR \&(new_directory, status) change directory +\fBzfdele\fR \&(osfn, status) delete a file +\fBzfgcwd\fR \&(osdir, maxch, status) get current working directory +\fBzfinfo\fR \&(osfn, out_struct, status) get info on a file +\fBzfmkcp\fR \&(old_osfn, new_osfn, status) make null copy of a file +\fBzfpath\fR \&(osfn, pathname, maxch, status) osfn to pathname +\fBzfprot\fR \&(osfn, prot_flag, status) file protection +\fBzfrnam\fR \&(old_osfn, new_osfn, status) rename a file +\fBzfsubd\fR \&(osdir, subdir, new_osdir, maxch, nchars) get subdirectory name +\fBzfxdir\fR \&(osfn, osdir, maxch, status) extract OS directory prefix +\fBzgfdir\fR \&(chan, osfn, maxch, status) get next OSFN from directory +\fBzgtime\fR \&(local_time, cpu_time) get clock time and cpu time +\fBzgtpid\fR \&(pid) get process id of current process +\fBzintpr\fR \&(pid, exception, status) interrupt connected subprocess +\fBzlocpr\fR \&(proc, entry_point_address) get EPA of a procedure +\fBzlocva\fR \&(variable, address) get address of a variable +\fBzmaloc\fR \&(buffer, nbytes, status) allocate a buffer +\fBzmfree\fR \&(buffer, status) deallocate a buffer +\fBzopcpr\fR \&(process, inchan, outchan, pid) open connected subprocess +\fBzopdir\fR \&(osfn, chan) open a directory +\fBzopdpr\fR \&(process, bkgfile, jobcode) open or queue detached process +\fBzoscmd\fR \&(cmd, stdout, stderr, status) send a command to the host JCL +\fBzpanic\fR \&(errcode, errmsg) panic exit +\fBzraloc\fR \&(buffer, nbytes, status) reallocate a buffer +\fBzsvjmp\fR \&(jumpbuf, status) save process status +\fBztslee\fR \&(delay_in_seconds) countdown timer +\fBzxgmes\fR \&(os_exception, errmsg, maxch) get exception code and message +\fBzxwhen\fR \&(exception, new_handler, old_handler) post an exception +.TE +.sp 2 +.TS +center box; +cb s s s s s s s s s +ci | ci | ci ci ci ci ci ci ci ci +l | c | c c c c c c c c. +Text File Device Drivers +_ +device code opn cls get put fls not sek stt += +normal (disk) tx * * * * * * * * +terminal ty * * * * * * +.TE +.sp 2 +.TS +center box; +cb s s s s s s s +ci | ci | ci ci ci ci ci ci +l | c | c c c c c c. +Binary File Device Drivers +_ +device code opn cls ard awr awt stt += +normal (disk) bf * * * * * * +line printer lp * * * * * +IPC pr * * * * +static file sf * * * * * * +magtape mt * * * * * * +.TE +.sp 2 +.TS +center; +cb s +n l. +Magtape Device Primitives +.sp +\fBzzopmt\fR \&(drive, density, mode, oldrec, oldfile, newfile, chan) open +\fBzzclmt\fR \&(chan, mode, nrecords, nfiles, status) close +\fBzzrdmt\fR \&(chan, buf, maxbytes) aread +\fBzzwrmt\fR \&(chan, buf, nbytes) awrite +\fBzzwtmt\fR \&(chan, nrecords, nfiles, status) await +\fBzzrwmt\fR \&(chan, status) arewind +.TE +.sp 2 +.TS +cb s +n l. +Bit and Byte Primitives +.sp +\fBand,and[sl]\fR \&(a, b) bitwise and +\fBor,or[sl]\fR \&(a, b) bitwise or +\fBxor,xor[sl]\fR \&(a, b) exclusive or +\fBnot,not[sl]\fR \&(a, b) complement +\fBbitpak\fR \&(intval, bit_array, bit_offset, nbits) integer \(-> bitfield +int = \fBbitupk\fR \&(bit_array, bit_offset, nbits) bitfield \(-> integer +\fBbytmov\fR \&(a, aoff, b, boff, nbytes) move an array of bytes +\fBbswap2\fR \&(a, b, nbytes) swap every pair of bytes +\fBbswap4\fR \&(a, b, nbytes) swap every 4 bytes +\fBchrpak\fR \&(a, aoff, b, boff, nchars) pack chars into bytes +\fBchrupk\fR \&(a, aoff, b, boff, nchars) unpack bytes into chars +\fBstrpak\fR \&(a, b, maxchars) SPP string \(-> byte-packed string +\fBstrupk\fR \&(a, b, maxchars) byte-packed string \(-> SPP string +\fBacht_b\fR \&(a, b, npix) SPP datatype \(-> unsigned byte +\fBacht_u\fR \&(a, b, npix) SPP datatype \(-> unsigned short +\fBachtb_\fR \&(a, b, npix) unsigned byte \(-> SPP datatype +\fBachtu_\fR \&(a, b, npix) unsigned short \(-> SPP datatype +\fBmiipak\fR \&(spp, mii, nelems, spp_type, mii_type) SPP \(-> MII +\fBmiiupk\fR \&(mii, spp, nelems, mii_type, spp_type) MII \(-> SPP +intlen = \fBmiilen\fR \&(n_mii_elements, mii_type) get length of MII array +int = \fBi1mach\fR \&(parameter) get int machine constants +real = \fBr1mach\fR \&(parameter) get real machine constants +double = \fBd1mach\fR \&(parameter) get double machine constants +.TE -- cgit