C Compiler User's Guide

From NitrOS-9
Revision as of 01:32, 31 May 2010 by Glaw16 (Talk | contribs) (System Calls)

Jump to: navigation, search

Contents

The C Compiler System

Introduction

The C programming language is rapidly growing in popularity and seems destined to become one of the most popular programming languages used for microcomputers. The rapid rise in the use of C is not surprising. C is an incredibly versatile and efficient language that can handle tasks that previously would have required complex assembly language programming.

C was originally developed at the Bel Telephone Laboratories as an implementation language for the UNIX operating system by Brian Kernighan and Dennis Ritchie. They also wrote a book titled The C Programming Language which is universally accepted as the standard for the language. It is an interesting reflection on the language that although no formal industry-wide "standard" was ever developed for C, programs written in C tend to be far more portable between radically different computer systems as compared to so-called "standardized" languages such as BASIC, COBOL, and PASCAL. The reason C is so portable is that the language is so inherently expandable that if some special function is required, the user can create a portable extension to the language, as opposed to the common practice of adding additional statements to the language. For example, the number of special-purpose BASIC dialects defies all reason. A lesser factor is the underlying UNIX operating system, which is also sufficiently versatile to discourage nonstandardization of the language. Indeed, standard C compilers and UNIX are intimately related.

Fortunately, the 6809 microprocessor, the OS-9 operating system, and the C language form an outstanding combination. The 6809 was specifically designed to efficiently run high-level languages, and its stack-oriented instruction set and versatile repertoire of addressing modes handle the C language very well. As mentioned previously, UNIX and C are closely related, and because OS-9 is derived from UNIX, it also supports C to the degree that almost any application written in C can be transported from a UNIX system to an OS-9 system, recompiled, and corrected executed.

The Language Implementation

OS-9 C is implemented almost exactly as described in The C Programming Language by Kernighan and Ritchie (hereafter referred to as K&R). A copy of this book, which serves as the language reference manual, is included with each software package.

Although this version of C follows the specification faithfully, there are some differences. The differences mostly reflect parts of C that are obsolete or the constraints imposed by memory size limitations.

Differences From the K&R Specification

  • Bit fields are not supported.
  • Constant expressions for initializers may include arithmetic operators only if all the operands are of type int or char.
  • The older forms of assignment operators, =+ or =*, which are recognized by some C compilers, are not supported. You must use the newer forms, +=, *=, etc.
  • "#ifdef (#ifndef) ... [#else...] #endif" is supported but "#if <constant expression>" is not.
  • It is not possible to extend macro definitions or strings over more than one line of source code.
  • The escape sequence for newline '\n' refers to the ASCII carriage return character (used by OS-9 for end-of-line), not linefeed (hex 0A). Programs which use '\n' for end-of-line (which includes all programs in K&R) will still work properly.

Enhancements and Extensions

The "Direct" Storage Class

The 6809 microprocessor instruction for accessing memory via an index register or the stack pointer can be relatively short and fast when they are used in C programs to access "auto" (function local) variables or function arguments. The instructions for accessing global variables are normally not so nice and must be four-bytes long and correspondingly slow. However, the 6809 has a nice feature which helps considerably. Memory, anywhere in a single page (256 byte block), may be accessed with fast, two byte instructions. This is called the "direct page", and at any time its location is specified by the contents of the "direct page register" within the processor. The linkage editor sorts out where this should be, and it need not concern the program, who only needs to specify for the compiler which variables should be in the direct page to give the maximum benefit in code size and execution speed.

To this end, a new storage class specifier is recognized by the compiler. In the manner of K&R page 192, the sc-specifier list is extended as follows:

Sc-specifier: auto
              static
              extern
              register
              typedef
              direct        (extension)
              extern direct (extension)
              static direct (extension)

The new keyword may be used in place of one of the other sc-specifiers, and its effect is that the variable will be placed in the direct page. direct creates a global direct page variable. extern direct references an external-type direct page variable and static direct creates a local direct page variable. These new classes may not be used to declare function arguments. "Direct" variables can be initialized but will, as with other variables not explicitly initialized, have the value zero at the start of program execution. 255 bytes are available in the direct page (the linker requires one byte). If all the direct variables occupy less than the full 255 bytes, the remaining global variables will occupy the balance and memory above if necessary. If too many bytes of storage are requested in the direct page, the linkage editor will report an error, and the programmer will have to reduce the use of direct variables to fit the 256 bytes addressable by the 6809.

It should be kept in mind that direct is unique to this compiler, and it may not be possible to transport programs written using direct to other environments without modification.

Embedded Assembly Language

As versatile as C is, occasionally there are some things that can only be done (or done at maximum speed) in assembly language. The OS-9 C compiler permits user-supplied assembly-language statements to be directly embedded in C source programs.

A line beginning with #asm switches the compiler into a mode which passes all subsequent lines directly to the assembly-language output, until a line beginning with #endasm is encountered. #endasm switches the mode back to normal. Care should be exercised when using this directive so that the correct code section is adhered to. Normal code from the compiler is in the PSECT (code) section. If your assembly code uses the VSECT (variable) section, be sure to put an ENDSECT directive at the end to leave the state correct for following compiler generated code.

Control Character Escape Sequences

The escape sequence for non-printing characters in character constants and strings (see K&R page 181) are extended as follows:

    linefeed (LF): \l (lowercase 'ell')

This is to distinguish LF (hex OA) from \n which on OS-9 is the same as \r (hex OD).

    bit patterns: \NNN (octal constant)
                  \dNNN (decimal constant)
                  \xNN (hexadecimal constant)

For example, the following all have the value 255 (decimal):

    \377    \xff    \d255

Implementation-Dependent Characteristics

K&R frequently refer to characteristics of the C language whose exact operations depend on the architecture and instruction set of the computer actually used. This section contains specific information regarding this version of C for the 6809 processor.

Data Representation and Storage

Each variable type requires a specific amount of memory for storage. The sizes of the basic types in bytes are as follows:

Data Type Size Internal Representation
char 1 two's complement binary
int 2 two's complement binary
unsigned 2 unsigned binary
long 4 two's complement binary
float 4 binary floating point (see below)
double 8 binary floating point (see below)

This compiler follows the PDP-11 implementation and format in that char is converted to int by sign extension, short or short int means int, long int means long, and long float means double. The format for double values is as follows:

(low byte)                              (high byte)
+-+------------------------------------+----------+
| |     seven byte                     |  1 byte  |
| |      mantissa                      | exponent |
+-+------------------------------------+----------+
 ^ sign bit

The form of the mantissa is sign and magnitude with an implied "1" bit at the sign bit position. The exponent is biased by 128. The format of a float is identical, except that the mantissa is only three bytes long. Conversion from double to float is carried out by truncating the least significant (right-most) four bytes of the mantissa. The reverse conversion is done by padding the least significant four mantissa bytes with zeros.

Register Variables

One register variable may be declared in each function. The only types permitted for register variables are int, unsigned, and pointer. Invalid register variable declarations are ignored; i.e., the storage class is made auto. For further details see K&R page 81.

A considerable saving in code size and speed can be made by judicious use a register variable. The most efficient use is made of it for a pointer or a counter for a loop. However, if a register variable is used in a complex arithmetic expression, there is no savings. The "U" register is assigned to register variables.

IMPORTANT NOTE: Upper- and lowercase letters cannot be mixed as in Basic09. For example, Prog.c and prog.c are distinct names. Since the Color Computer is usually used in uppercase only, it is necessary to enter the following commands to use upper- and lowercase: TMODE -UPC and CLEAR<0>.

Access to Command Line Parameters

The standard C arguments argc and argv are available to main as described in K&R page 110. The startup routine for C programs ensures that the parameter string passed to it by the parent process is converted into null-terminated strings as expected by the program. In addition, it will run together as a single argument any strings enclosed between single or double quotes ("'" or '"'). If either is part of the string required, then the other should be used as a delimiter.

System Calls and the Standard Library

Operating System Calls

The system interface supports almost all the system calls of both OS-9 and UNIX. In order to facilitate the portability of programs from UNIX, some of the calls use UNIX names rather than OS-9 names for the same function. There are a few UNIX calls that do not have exactly equivalent OS-9 calls. In these cases, the library function simulates the function of the corresponding UNIX call. In cases where there are OS-9 calls that do not have UNIX equivalents, the OS-9 names are used. Details of the calls and a name cross-reference are provided in the C System Calls section of this manual.

The Standard Library

The C compiler includes a very complete library of standard functions. It is essential for any program which uses functions from the standard library to have the statement:

    #include <stdio.h>

See the C Standard Library section of this manual for details on the standard library functions provided.

IMPORTANT NOTE: If output via printf(), fprintf(), or sprintf() of long integers is required, the program must call pflinit() at some point; this is necessary so that programs not involving longs do not have te extra longs output code appended. Similarly, if floats or doubles are to be printed, pffinit() must be called. These functions do nothing; existence of calls to them in a program informs the linker that the relevant routines are also needed.

Run-Time Arithmetic Error Handling

K&R leave the treatment of various arithmetic errors open, merely saying that it is machine dependent. This implementation deals with a limited number of error conditions in a special way; it should be assumed that the results of other possible errors are undefined.

Three new system error numbers are defined in <errno.h>:

    #define EFPOVR  40 /* floating point overflow or underflow */
    #define EDIVERR 41 /* division by zero */
    #define EINTERR 42 /* overflow on conversion of floating point to long integer */

If one of these conditions occur, the program will send a signal to itself with the value of one of these errors. If not caught or ignored, this will cause termination of the program with an error return to the parent process. However, the program can catch the interrupt using signal() or intercept() (see C System Calls), and in this case the service routine has the error number as its argument.

Achieving maximum Program Performance

Programming Considerations

Because the 6809 is an 8/16 bit microprocessor, the compiler can generate efficient code for 8 and 16 bit objects (char, int, etc.). However, code for 32 and 64 bit values (long, float, double) can be at least four times longer and slower. Therefore don't use long, float, or double where int or unsigned will do.

The compiler can perform extensive evaluation of constant expressions provided they involve only constants of type char, int, and unsigned. There is no constant expression evaluation at compile-time (except single constants and casts of them) where there are constants of type long, float, or double, therefore, complex constant expressions involving these types are evaluated at run time by the compiled program. You should manually compute the value of constant expressions of these types if speed is essential.

The Optimizer Pass

The optimizer pass automatically occurs after the compilation passes. It reads the assembler source code text and removes redundant code and searches for code sequences that can be replaced by shorter and faster equivalents. The optimizer will shorten object code by about 11% with a significant increase in program execution speed. The optimizer is recommended for production versions of debugged programs. Because this pass takes additional time, the -O compiler option can be used to inhibit it during error-checking-only compilation.

The Profiler

The profiler is an optional method used to determine the frequency of execution of each function in a C program. It allows you to identify the most frequently used functions where algorithmic or C source code programming improvements will yield the greatest gains.

When the -P compiler option is selected, code is generated at the beginning of each function to call the profiler module (called _prof), which counts invocations of each function during program execution. When the program has terminated, the profiler automatically prints a list of all functions and the number of times each was called. the profiler slightly reduces program execution speed. See prof.c source for more information.

C Compiler Component Files and File Usage

Compilation of a C program by cc requires that the following files be present in the current execution direction (CMDS).

OS-9 Level I Systems:

cc1 compiler executive program
c.prep macro pre-processor
c.pass1 compiler pass 1
c.pass2 compiler pass 2
c.opt assembly code optimizer
c.asm relocating assembler
c.link linkage editor

OS-9 Level II Systems:

cc2 compiler executive program
c.prep macro pre-processor
c.comp compiler proper
c.asm relocating assembler
c.link linkage editor

In addition a file called clib.l contains the standard library, math functions, and system library. The file cstart.r is the setup code for compiled programs. Both of these files must be located in a directory named LIB on drive /D1. The DEFS directory must also be on /D1.

If, when specifying #include files for the processor to read in, the programmer uses angle brackets, < and >, instead of parentheses, the file will be sought starting at the DEFS directory.

Temporary Files

A number of temporary files are created in the current data directory during compilation, and it is important to ensure that enough space is available on the disk drive. As a rough guide, at least three times the number of blocks in the largest source file (and its include files) should be free.

The identifiers etext, edata, and end are predefined in the linkage editor and may be used to establish the address of the end of executable text, initialized data, and uninitialized data respectively.

Running the Compiler

There are two commands which invoke distinct versions of the compiler. cc1 is for OS-9 Level I which uses a two pass compiler, and cc2 is for Level II which uses a single pass version. Both versions of the compiler work identically, the main difference is that cc1 has been divided into two passes to fit the smaller memory size of OS-9 Level I systems. In the following text, cc refers to either cc1 or cc2 as appropriate for your system. The syntax of the command line which calls the compiler is:

   cc [ option-flags ] file {file}

One file at a time can be compiled, or a number of files may be compiled together. The compiler manages the compilation through up to four stages: pre-processor, compilation to assembler code, assembly to relocatable module, and linking to binary executable code (in OS-9 memory module format).

The compiler accepts three types of source files, provided each name on the command line has the relevant postfix as show below. Any of the above file types may be mixed on the command line.

File Name Suffix Conventions

Suffix Usage
.c C source file
.a assembly language source file
.r relocatable module
none executable binary (OS-9 memory module)

There are two modes of operation: multiple source file and single source file. The compiler selects the mode by inspecting the command line. The usual mode is single source and is specified by having only one source file named on the command line. Of course, more than one source file may be compiled together by using the #include facility in the source code. In this mode, the compiler will use the name obtained by removing the postfix from the name supplied on the command line, and the output file (and the memory module produced) will have this name. For example:

    cc prg.c

will leave an executable file called prg in the current execution directory.

The multiple source mode is specified by having more than one source file name on the command line. In this mode, the object code output file will have the name output in the current execution directory, unless a name is given using the -f= option (see below). Also, in multiple source mode, the relocatable modules generated as intermediate files will be left int he same directories as their corresponding source files with the postfixes changed to .r. For example:

    cc prg1.c /d0/fred/prg2.c

will leave an executable file called output in the current execution directory, one called prg1.r in the current data directory, and prg2.r in /d0/fred.

    CC -E=3 FNAME.C -F=PROG

compiles the file called FNAME.C into an executable object file named PROG and sets the module revision level to 3.

    CC PROG.C -DIDENTIFIER=VALUE

compiles the program with a definition identifier being passed to the compiler. The definition being passed is used within the source to control compilation via #ifdef/#ifndef functions.

Compiler Option Flags

The compiler recognizes several command-line option flags which modify the compilation process where needed. All flags are recognized before compilation commences so the flags may be placed anywhere on the command line. Flags may be ran together as in -ro, except where a flag is followed by something else; see -f= and -d for examples:

-A Suppresses assembly, leaving the output as assembler code in a file whose name is postfixed .a.
-E=number Sets the edition number constant byte to the number given. This is an OS-9 convention for memory modules.
-O Inhibits the assembly code optimizer pass. The optimizer will shorten object code by about 11% with a comparable increase in speed and is recommended for production versions of debugged programs.
-P Invokes the profiler to generate function invocation frequency statistics after program execution.
-R Suppresses linking library modules into an executable program. Outputs are left in files with postfixes .r.
-M=memory size Instructs the linker to allocate memory size for data, stack, and parameter area. Memory size may be expressed in pages (an integer) or in kilobytes by appending k to an integer. For more details of the use of this option, see the Memory Management section of this manual.
-L=filename Specifies a library to be searched by the linker before the Standard Library and system interface.
-F=path Overrides the above output file naming. The output file will be left with filename as its name. This flag does not make sense in multiple source mode, and either the -a or -r flag is also present. The module will be called the last name in path.
-C Outputs the source code as comments with the assembler code.
-S Stops the generation of stack-checking code. -S should only be used with great care when the application is extremely time-critical and when the use of the stack by compiler generated code is fully understood.
-D identifier Equivalent to #define identifier written in the source file. -D is useful where different versions of a program are maintained in one source file and differentiated by means of the #ifdef or #ifndef pre-processor directives. If the identifier is used as a macro for expansion by the pre-processor, 1 will the expanded value unless the form -d identifier=string is used in which case the expansion will be string.

Command Line and Option Flag Examples

command line action output file(s)
cc prg.c compile to an executable program prg
cc prg.c -a compile to assembly language source code prg.a
cc prg.c -r compile to relocatable module prg.r
cc prg1.c prg2.c prg3.c compile to executable program prog1.r, prg2.r, prg3.r, output
cc prg1.c prg2.a prg3.r compile prg1.c, assemble prg2.a and combine all into an executable program prg1.r, prg2.r
cc prg1.c prg2.c -a compile to assembly language source code prg1.a, prg2.a
cc prg1.c, prg2.c -f=prg compile to executable program prg

Characteristics of Compiled Programs

The Object Code Module

The compiler produces position-independent, reentrant 6809 code in a standard OS-9 memory module format. The format of an executable program module is shown below. Detailed descriptions of each section of the module are given on the following pages.

     Module                                               Section
     Offset                                             Size (bytes)
                  +-----------------------------+
     $00          |                             |
                  |       Module Header         |            8
                  |                             |
                  +-----------------------------+
     $09          |      Execution Offset       |---+        2
                  +-----------------------------+   |
     $0B          |   Permanent Storage Size    |   |        2
                  +-----------------------------+   |
     $0D          |         Module Name         |   |
                  |.............................|   |
                  |                             |<--+
                  |       Executable Code       |
                  |.............................|
                  |       String Literals       |
                  |                             |
                  +-----------------------------+
                  |   Initializing Data Size    |            2
                  +-----------------------------+
                  |                             |
                  |      Initializing Data      |
                  |                             |
                  +-----------------------------+
                  | Data-text Reference Count   |            2
                  +-----------------------------+
                  |                             |
                  | Data-text Reference Offsets |
                  |                             |
                  +-----------------------------+
                  | Data-data Reference Count   |            2
                  +-----------------------------+
                  |                             |
                  | Data-data Reference Offsets |
                  |                             |
                  +-----------------------------+
                  |       CRC Check Value       |            3
                  +-----------------------------+

Module Header

This is a standard module header with the type/language byte set to $11 (Program + 6809 Object Code), and the attribute/revision byte set to $81 (Reentrant + 1).

Execution Offset

Used by OS-9 to locate where to start execution of the program.

Storage Size

Storage size is the initial default allocation of memory for data, stack, and parameter area. For a full description of memory allocation, the section entitled Memory Management located elsewhere in this manual.

Module Name

Module name is used by OS-9 to enter the module in the module directory. The module name is followed by the edition byte encoded in cstart. If this situation is not desired it may be overriden by the -E= option in cc.

Information

Any strings preceded by the directive info in an assembly code file will be placed here. A major use of this facility is to place in the module the version number and/or a copyright notice. Note that the #asm pre-compiler instruction may be used in a C source file to enable the inclusion of this directive in the compiler-generated assembly code file.

Executable Code

The machine code instructions of the program.

String Literals

Quoted strings in the C source are placed here. They are in the null-terminated form expected by the functions in the Standard Library. NOTE: the definition of the C language assumes that strings are in the DATA area and are therefore subject to alteration without making the program non-reentrant. However, in order to avoid the duplication of memory requirements which would be ncessary if they were to be in the data area, they are placed in the TEXT (executable) section of the module. Putting the strings in the executable section implies that no attempt should be made by a C programmer to alter string literals. They should be copied out first. The exception that proves the rule is the initialization of an array of type char like this:

    char message[] = "Hello world\n";

The string will be found in the array message in the data area and can be altered.

Initialization Data and its Size

If a C program contains initializers, the data for the initial values of the variables is placed in this section. The definition of C states that all uninitialized global and static variables have the value zero when the program starts running, so the startup routine of each C program first copies the data from the module into the data area and then clears the rest of the data memory to nulls.

Data References

No absolute addresses are known at compile time under OS-9, so where there are pointer values in the initializing data, they must be adjusted at run time so that they reflect the absolute values at that time. The startup routine uses the two data reference tables to locate the values that need alteration and adjusts them by the absolute values of the bases of the executable code and data respectively.

For example, suppose there are the following statements in the program being compiled:

    char *p = "I'm a string!";
    char **q = &p;

These declarations tell the compiler that there is to be a char pointer variable, p, whose initial value is the address of the string and a pointer to a char pointer, q, whose initial value is the address of p. The variables must be in the DATA section of memory at run time because they are potentially alterable, but absolute addresses are not known until run time, so the values that p and q must have are not known at compile time. The string will be placed by the compiler in the TEXT section and will not be copied out to DATA memory by the startup routine. The initializing data section of the program module will contain entries for p and q. They will have as values the offsets of the string from the base of the TEXT section and the offset of the location of p from the base of the DATA section respectively.

The startup routine will first copy all the entries in the initializing data section into their allotted places in the DATA section. then it will scan the data-text reference table for the offsets of values that need to have the addresses of the base of the TEXT section added to them. Among thee will be p which, after updating, will point to the string which is in the TEXR section. Similarly, after a scan of the data-data references, q will point to (contain the absolute address of) p.

Memory Management

The C compiler and its support programs have default conditions such that the average programmer need not be concerned with details of memory management. However, there are situations where advanced programmers may wish to tailor the storage allocation of a program for special situations. The following information explains in detail how a C program's data area is allocated and used.

Typical C Program Memory Map

A storage area is allocated by OS-9 when the C program is executed. The layout of this memory is as follows:

                  high addresses
               |                  | <- SBRK() adds more
               |                  |    memory here
               |                  |
               +------------------+ <- memend
               |    parameters    |
               +------------------+
               |                  |
Current stack  |       stack      | <- sp register
reservation -> +..................+
               |         v        |
               |                  | <- standard I/O buffers
               |    free memory   |    allocated here
Current top    |                  |
of data     -> |..................| <- IBRK() changes this
               |                  |    memory bound upward
               | requested memory |
               +------------------+ <-- end
               |   uninitialized  |
               |       data       |
               +------------------+ <- edata
               |    initialized   |
               |       data       |
               +------------------+
          ^    |    direct page   |
        dpsiz  |     variables    |
          v    |------------------+ <- y,dp registers
                   low addresses

The overall size of the this memory area is defined by the storage size value stored in the program's module header. This can be overridden to assign the program additional memory if the OS-9 Shell # command is used.

The parameter area is where the parameter string from the calling process (typically the OS-9 Shell) is placed by the system. The initializing routine for C programs converts the parameter into null-terminated strings and makes pointers to them available to main() via argc and argv.

The stack area is the currently reserved memory for exclusive use of the stack. As each C function is entered, a routine in the system interface is called to reserve enough stack space for the use of the function with an addition of 64 bytes. The 64 bytes are for the use of user-written assembly code functions and/or the system interface and/or arithmetic routines. A record is kept of the lowest address so far granted for the stack. If the area requested would not being this lower, the C function is allowed to proceed. If the new lower limit would mean that the stack area would overlap the data area, the program stops with the message:

     **** STACK OVERFLOW ****

on the standard error output. Otherwise, the new lower limit is set, and the C function resumes as before.

the direct page variables area is where variables reside that have been defined with the storage class direct in the C source code or in the direct segment in assembly language code source. Notice that the size of this area is always at least one byte (to ensure that no pointer to a variable can have the value NULL or 0) and that it is not necessarily 256 bytes.

The uninitialized data area is where the remainder of the uninitialized program variables reside. These two areas are, in fact, cleared to all zeros by the program entry routine. The initialized data area is where the initialized variables of the program reside. There are two globally defined values which may be referred to: edata and end, which are the addresses of one byte higher than the initialized data and one byte higher than the uninitialized data respectively. Note that these are not variables; the values are accessed in C using the & operator as in:

    high = &end;
    low = &edata;

and in assembler:

    leax end,y
    stx  high,y

The Y register points to the base of the data area and variables are addresses using Y-offset indexed instructions.

When the program starts running, the remaining memory is assigned to the "free" area. A program may call ibrk() to request additional working memory (initialized to zeros) from the free memory area. Alternatively, more memory can be dynamically obtained using the sbrk() which requests additional memory from the operating system and returns its lower bound. If this fails because OS-9 refuses to grant more memory for each reason sbrk() will return -1.

Compile Time Memory Allocation

If not instructed otherwise, the linker will automatically allocate 1k bytes more than the total size of the program's variables and strings. This size will normally be adequate to cover the parameter area, stack requirements, and Standard Library file buffers. The allocation size may be altered when using the compiler by using the -m option on the command line. The memory requirements may be stated in pages, for example,

    cc prg.c =m-2

which allocates 512 bytes extra, or in kilobytes, for example:

    cc prg.c -m=10k

The linker will ignore the request if the size is less than 256 bytes.

The following rules can serve as a rough guide to estimate how much memory to specify:

  1. The parameter area should be large enough for any anticipated command line string.
  2. The stack should not be less than 128 bytes and should take into account the depth of function calling chains and any recursion.
  3. All function arguments and local variables occupy stack space and each function entered needs 4 bytes more for the return address and temporary storage of the calling function's register variable.
  4. Free memory is requested by the Standard Library I/O functions for buffers at the rate of 256 bytes per accessed file. This does not apply to the lower level service request I/O functions such as open(), read(), or write() nor to stderr which is always unbuffered, but it does apply to both stdin and stdout (see the Standard Library documentation).

A good method for getting the feel of how much memory is needed by your program is to allow the linker to set the memory size to its usually conservative default value. Then, if the program runs with a variety of input satisfactorily but memory is limited on the system, try reducing the allocation at the next compilation. If a stack overflow occurs or an ibrk() call return -1, then try increasing the memory next time. You cannot damage the system by getting it wrong, but data may be lost if the program runs out of space at a crucial time. It pays to be in error on the generous side.

System Calls

This section of the C compiler manual is a guide to the system calls available from C programs.

It is not intended as a definitive description of OS—9 service requests as these are described in the OS—9 System Programmer's Manual. However, for most calls, enough information is available here to enable the programmer to write system calls into programs without looking further.

The names used for the system calls are chosen so that programs transported from other machines or operating systems should compile and run with as little modification as possible. However, care should be taken as the parameters and returned values of some calls may not be compatible with those on other systems. Programmers that are already familiar with OS—9 names and values should take particular care. Some calls do not share the same names as the OS—9 assembly language equivalents. The assembly language equivalent call is shown, where there is one, on the relevant page of the C call description, and a cross—reference list is provided for those already familiar with OS—9 calls.

The normal error indication on return from a system call is a returned value of —1. The relevant error will be found in the predefined int errno. Errno always contains the error from the last erroneous system call. Definitions for the errors for inclusion in the program are in <errno.h>.

In the See Also sections on the following pages, unless otherwise stated, the references are to other system calls.

Where #include files are shown, it is not mandatory to include them, but it might be convenient to use the manifest constants defined in them rather than integers; it certainly makes for more readable programs.


abort - Stop the program and produce a core dump

Usage

abort()

Description

This call causes a memory image to be written out to the file core in the current directory, and then the program exits with a status of 1.

abs - Absolute value

Usage

int abs(i)
int i;

Description

Abs returns absolute value of its integer operand.

Caveats

You get what the hardware gives on the largest negative number.

access - Give file accessibility

Usage

access(fname,perm)
char *fname;
int perm

Description

Access returns 0 if the access modes specified in perm are correct for the user to access fname. -1 is returned if the file cannot be accessed.

The value for perm may be any legal OS-9 mode as used for open() or creat(), it may be zero, which tests whether the file exists, or the path to it may be searched.

Caveats

Note that the perm value is not compatible with other systems.

Diagnostics

The appropriate error indication, if a value of -1 is returned, may be found in errno.

chain - Load and execute a new program

Usage

chain(modname, paramsize, paramptr, type, lang, datasize)
char *modname, *paramptr;

Assembler Equivalent

os9 F$Chain

Description

The action of F$Chain is described fully in the OS-9 documentation. Chain implements the service request as described with one important exception: chain will never return to the caller. If there is an error, the process will abort and return to its parent process. It might be wise, therefore, for the program to check the existence and access permissions of the module before calling chain. Permissions may be checked by using modlink() or modload() followed by munlink().

modname should point to the name of the desired module. paramsize is the length of the parameter string (which should normally be terminated with a '\n'), and paramptr points to the parameter string. type is the module type as found in the module header (normally 1: program), and lang should match the language nibble in the module header (C programs have 1 for 6809 machine code here). datasize may be zero, or it may contain the number of 256 byte pages to give to the new process as initial allocation of data memory.

chdir, chxdir - Change directory

Usage

chdir(dirname)
char *dirname;
chxdir(dirname)
char *dirname;

Assembler Equivalent

os9 I$ChgDir

Description

These calls change the current data directory and the current execution directory, respectively, for the running task. dirname is a pointer to a string that gives a pathname for a directory.

Diagnostics

Each call returns 0 after a successful call, or -1 if dirname is not a directory path name, or it is not searchable.

See Also

OS-9 shell commands chd and chx.

chmod - Change access permissions of a file

Usage

  1. include <modes.h>
chmod(fname, perm)
char *fname;

Description

chmod changes the permission bits associated with a file. fname must be a pointer to a file name, and perm should contain the desired bit pattern.

The allowable bit patterns are defined in the include file as follows:

    /* permissions */
    #define S_IREAD   0x01  /* owner read */
    #define S_IWRITE  0x02  /* owner write */
    #define S_EXEC    0x04  /* owner execute */
    #define S_IOREAD  0x08  /* public read */
    #define S_IOWRITE 0x10  /* public write */
    #define S_IOEXEC  0x20  /* public execute */
    #define S_ISHARE  0x40  /* sharable */
    #define S_IFDIR   0x80  /* directory */

Only the owner or the super user may change the permissions of a file.

Diagnostics

A successful call returns NULL (0). A -1 is returned if the caller is not entitled to change permissions or fname cannot be found.

See Also

OS-9 command attr

chown - Change the ownership of a file

Usage

chown(fname, ownerid)
char *fname;

Description

This call is available only to the super user. fname is a pointer to a file name, and ownerid is the new user-id.

Diagnostics

Zero is returned from a successful call. -1 is returned on error.

close - Close a file

Usage

close(pn)

Assembler Equivalent

os9 I$Close

Description

close takes a path number, pn, as returned from system calls open(), creat(), or dup(), and closes the associated file.

Termination of a task always closes all open file automatically, but it is necessary to close files where multiple files are opened by the task, and it is desired to reuse path numbers to avoid going over the system or process path number limit.

See Also

creat(), open(), dup()

crc - Compute a cyclic redundancy count

Usage

crc(start, count, accum)
char *start, accum[3]

Assembler Equivalent

os9 F$CRC

Description

This call accumulates a CRC into a three-byte array at accum for count bytes starting at start. All three bytes of acum should be initialized to 0xFF before the first call to crc(). However, repeated calls can be subsequently made to cover an entire module. If the result is to be used as an OS-9 module CRC, it should have its bytes complemented before insertion at the end of the module.

creat - Create a new file

Usage

  1. include <modes.h>
creat(fname, perm)
char *fname;

Assembler Equivalent

os9 I$Creat

Description

creat() returns a path number to a new file available for writing, giving it the permissions specified in perm and making the task user the owner. If, however, fname is the name of an existing file, the file is truncated to zero length, and the ownership and permissions remain unchanged. Note that unlike the OS-9 assembler service request, creat() does not return an error if the file already exists. access() should be used to establish the existence of a file if it is important that a file should not be overwritten.

It is unnecessary to specify writing permissions in perm in order to write to the file in the current task.

The permissions allowed are defined in the include file as follows:

    /* permissions */
    #define S_IPRM    0xFF  /* mask for permission bits */
    #define S_IREAD   0x01  /* owner read */
    #define S_IWRITE  0x02  /* owner write */
    #define S_EXEC    0x04  /* owner execute */
    #define S_IOREAD  0x08  /* public read */
    #define S_IOWRITE 0x10  /* public write */
    #define S_IOEXEC  0x20  /* public execute */
    #define S_ISHARE  0x40  /* sharable */

Directories may not be created with this call; use mknod() instead.

Diagnostics

This call returns -1 if there are too many files open, if the pathname cannot be search, if permission to write is denied, or if the file exists and is a directory.

See Also

write(), close(), chmod()

defdrive - Get default system drive

Usage

char *defdrive()

Description

A call to defdrive() returns a pointer to a string containing the name of the default system drive. The method used is to consult the Init module for the default directory name. The name is copied to a static data area and a pointer to it is returned.

Diagnostics

-1 is returned if the Init module cannot be linked.

dup - Duplicate an open path number

Usage

dup(pn)

Assembler Equivalent

os9 I$Dup

Description

dup() takes the path number, pn, as returned from open() or creat() and returns another path number associated with the same file.

Diagnostics

A -1 is returned if the call fails because there are too many files open or the path number is invalid.

See Also

open(), creat(), close()

exit, _exit - Task termination

Usage

exit(status)
_exit(status)

Assembler Equivalent

os9 F$Exit

Description

exit() is the normal means of terminating a task. exit() does any cleaning up operations required before terminating, such as flushing out any file buffers (see Standard I/O), but _exit() does not.

A task finishing normally, that is returning from main(), is equivalent to a call to exit(0).

The status passed to exit() is available to the parent task if it is executing a wait().

See Also

wait()

getpid - Get the task id

Usage

getpid()

Assembler Equivalent

os9 F$ID

Description

A number unique to the current running task is often useful in creating names for temporary files. This call returns the task's system id (as returned to its parent by os9fork()).

See Also

os9fork(), mktemp()

getstat - Get file status

Usage

  1. include <sgstat.h>
getstat(code, filenum, buffer) /* code 0 */
char *buffer;
getstat(code, filenum) /* codes 1 and 6 */
getstat(code, filenum, size) /* code 2 */
long *size;
getstat(code, filenum, pos) /* code 5 */
long *pos;

Assembler Equivalent

os9 I$GetStt

Description

A full description of getstat can be found in the OS-9 System Programmer's Manual.

code must be the value of one of the standard codes for the getstat service request. filenum must be the path number of an open file.

The form of the call depends on the value of code.

Code 0 buffer must be the address of a 32-byte buffer into which the relevant status packet is copied. The header file has the definitions of the various file and device structures for use by the program.
Code 1 Code 1 only applies to SCF devices and to test for data available. The return value is zero if there is data available. -1 is returned if there is no data.
Code 2 size should be the address of a long integer into which the current file size is placed. The return value of the function is -1 on error and 0 on success.
Code 5 pos should be the address of a long integer into which the current file size is placed. The return value of the function is -1 on error and 0 on success.
Code 6 Returns -1 on EOF and error and 0 on success.

Note that when one of the previous calls returns -1, the actual error is returned in errno.

getuid - Return user id

Usage

getuid()

Assembler Equivalent

os9 F$ID

Description

getuid() returns the real user id of the current task (as maintained in the password file).

intercept - Set function for interrupt processing

Usage

intercept(func)
int (*func)(); /* i.e. "func" is a pointer to a function returning an int */

Assembler Equivalent

os9 F$Icpt

Description

intercept() instructs OS-9 to pass control to func when an interrupt (signal) is received by the current process.

If the interrupt processing function has an argument, it will contain the value of the signal received. On return from func, the process resumes at the point in the program where it was interrupted by the signal. interrupt() is an alternative to the use of signal() to process interrupts.

As an example, suppose we wish to ensure that a partially completed output file is deleted if an interrupt is received. The body of the program might include:

    char *temp_file = "temp"; /* name of temporary file */
    int pn = 0;               /* path number */
    int intrupt();            /* predeclaration */

    ...

    intercept(intrupt);       /* route interrupt processing */
    pn = creat(temp_file, 3); /* make a new file */

    ...

    write(pn, string, count); /* write string to temp file */

    ...

    close(pn);
    pn = 0;

    ...

The interrupt routine might be coded:

    intrupt(sig)
    {
        if(pn)
        {
            /* only done if pn refers to an open file */
            close(pn);
            unlink(temp_file); /* delete */
        }

        exit(sig)
    }

Caveats

intercept() and signal() are mutually incompatible so that calls to both must not appear in the same program. The linker guards against this by giving an "entry name clash - _sigint" error if it is attempted.

See Also

signal()

kill - Send an interrupt to a task

Usage

  1. include <signal.h>
kill(tid, interrupt);

Description

kill() sends the interrupt type interrupt to the task with id tid.

Both tasks, sender and receiver, must have the same user id unless the user is the super user.

The include file contains definitions of the defined signals as follows:

/* OS-9 signals */
#define SIGKILL 0    /* system abort (cannot be caught or ignored) */
#define SIGWAKE 1    /* wake up */
#define SIGQUIT 2    /* keyboard abort */
#define SIGINT 3     /* keyboard interrupt */

Other user-defined signals may, of course, be sent.

Diagnostics

kill() returns 0 from a successful call and -1 if the task does not exist, the effective user ids do not match, or the user is not system manager.

See Also

signal, OS-9 shell command kill

lseek - Position a file

Usage

long lseek(pn, position, type)
long position;

Assembler Equivalent

os9 I$Seek

Description

The read or write pointer for the open file with the path number, pn, is positioned by lseek() to the specified place in the file. The type indicates from where position is to be measured: if 0, from the beginning of the file; if 1, from the current location; or, if 2, from the end of the file.

Seeking to a location beyond the end of a file open for writing and then writing to it creates a hole in the file which appears to be filled with zeros from the previous end to the position sought.

The returned value is the resulting position in the file unless there is an error, so to find out the current position use

    lseek(pn, 0l, 1);

Caveats

The argument position must be a long integer. Constants should be explicitly made long by appending an "l", as above, and other types should be converted using a cast:

    lseek(pn, (long) pos, 1);

Notice also that the return value from lseek() is itself a long integer.

Diagnostics

-1 is returned if pn is a bad path number, or attempting to seek to a position before the beginning of a file.

See Also

open(), creat(), fseek()

mknod - Create a directory

Usage

  1. include <modes.h>
mknod(fname, desc)
char *fname;

Assembler Equivalent

os9 I$MakDir

Description

This call may be used to create a new directory. fname should point to a string containing the desired name of the directory. desc is a descriptor specifying the desired mode (file type) and permissions of the new file.

The include file defines the possible values for desc as follows:

#define S_IREAD   0x01   /* owner read */
#define S_IWRITE  0x02   /* owner write */
#define S_IEXEC   0x04   /* owner execute */
#define S_IOREAD  0x08   /* public read */
#define S_IOWRITE 0x10   /* public write */
#define S_IOEXEC  0x20   /* public execute */
#define S_ISHARE  0x40   /* sharable */

Diagnostics

Zero is returned if the directory has been successfully made; -1 if the file already exists.

See Also

OS-9 command makdir

modload, modlink - Return a pointer to a module structure

Usage

  1. include <module.h>
mod_exec *modlink(modname, type, language)
char *modname;
mod_exec *modload(filename, type, language)
char *filename;

Assembler Equivalent

os9 F$Link
os9 F$Load

Description

Each of these calls return a pointer to an OS-9 memory module.

modlink() will search the module directory for a module with the same name as modname and, if found, increment its link count.

modload() will open the file which has the path list specified by filename and loads modules from the file adding them to the module directory. The returned value is a pointer to the first module loaded.

Above, each is shown as returning a pointer to an executable module, but it will return a pointer to whatever type of module is found.

Diagnostics

-1 is returned on error.

See Also

munlink()

munlink - Unlink a module

Usage

  1. include <module.h>
munlink(mod)
mod_exec *mod;

Assembler Equivalent

os9 F$UnLink

Description

This call informs the system that the module pointed to by mod is no longer required by the current process. Its link count is decremented, and the module is removed from the module directory if the link count reaches zero.

See Also

modlink(), modload()

_os9 - System call interface from C programs

Usage

  1. include <os9.h>
_os9(code, reg)
char code;
struct registers *reg;

Description

_os9() enables a programmer to access virtually any OS-9 system call directly from a C program without having to resort to assembly language routines.

Code is one of the codes that are defined in os9.h. os9.h contains codes for the F$ and I$ function/service requests, and it also contains getstt, setstt, and error codes.

The input registers (reg) for the system calls are accessed by the following structure that is defined in os9.h:

    struct registers {
        char rg_cc, rg_a, rg_b, rg_dp;
        unsigned rg_x, rg_y, rg_u;
    };

An example program that uses _os9() is presented on the following page.

Diagnostics

-1 is returned if the OS-9 call failed. 0 is returned on success.

Program Example

    #include <os9.h>
    #include <modes.h>

    /* this program does an I$GetStt call to get file size */
    main(argc, argv)
    int argc;
    char **argv;
    {
        struct registers reg;
        int path;

        /* tell linker we need longs */
        pflinit();

        /* low level open (file name is first command line param) */
        path = open(*++argv, S_IREAD);

        /* set up regs for call to OS-9 */
        reg.rg_a = path;
        reg.rg_b = SS_SIZE;

        if(_os9(I_GETSTT, &reg) == 0)
            printf("filesize = %1x\n", (long) (reg.rg_x << 16) + reg.rg_u);
        else
            printf("OS9 error #%d\n", reg.rg_b & 0xFF); /* failed */

        dumpregs(&reg); /* take a look at the registers */
    }

    dumpregs(r)
    register struct registers *r;
    {
        printf("cc=%02x\n", r->rg_cc & 0xFF);
        printf(" a=%02x\n", r->rg_a & 0xFF);
        printf(" b=%02x\n", r->rg_b & 0xFF);
        printf("dp=%02x\n", r->rg_dp & 0xFF);
        printf(" x=%04x\n", r->rg_x);
        printf(" y=%04x\n", r->rg_y);
        printf(" u=%04x\n", r->rg_u);
    }

open - Open a file for read/write access

Usage

open(fname, mode)
char *fname;

Assembler Equivalent

os9 I$Open

Description

This call opens an existing file for reading if mode is 1, writing if mode is 2, or reading and writing if mode is 3. Note that these values are OS-9 specific and are not compatible with other systems. fname should point to a string representing the pathname of the file.

open() returns an integer as path number which should be used by I/O system calls referring to the file.

The position where read and writes start is at the beginning of the file.

Diagnostics

-1 is returned if the file does not exist, if the pathname cannot be searched, if too many files are already open, or if the file permissions deny the requested mode.

See Also

creat(), read(), write(), dup(), close()

os9fork - Create a process

Usage

os9fork(modname, paramsize, paramptr, type, lang, datasize)
char *modname, *paramptr;

Assembler Equivalent

os9 F$Fork

Description

The action of F$Fork is described fully in the OS-9 System Programmer's Manual. os9fork will create a process that will run concurrently with the calling process. When the forked process terminates, it will return to the calling process.

modname should point to the name of the desired module. paramsize is the length of the parameter string which should normally be terminated with a '\n', and paramptr points to the parameter string. type is the module type as found in the header (normally 1:program) and lang should match the language nibble in the module header (C programs have 1 for 6809 machine code here). datasize may be zero, or it may contain the number of 256 byte pages to give to the new process as initial allocation of memory.

Diagnostics

-1 will be returned on error, or the Id number of the child process will be returned on success.

pause - Halt and wait for interrupt

Usage

pause()

Assembler Equivalent

os9 F$Sleep with a value of 0

Description

pause may be used to halt a task until an interrupt is received from kill.

pause always returns -1.

See Also

kill(), signal(), OS-9 shell command kill

prerr - Print error message

Usage

prerr(filnum, errcode)

Assembler Equivalent

os9 F$PErr

Description

prerr prints an error message on the output path as specified by filnum which must be the path number of an open file. The message depends on errcode which will normally be a standard OS-9 error code.

read, readln - Read from a file

Usage

read(pn, buffer, count)
char *buffer;
readln(pn, buffer, count)
char *buffer;

Assembler Equivalent

os9 I$Read
os9 I$ReadLn

Description

The path number, pn, is an integer which is one of the standard path numbers 0, 1, or 2, or the path number should have been returned by a successful call to open(), creat(), or dup(). buffer is a pointer to space with at least count bytes of memory into which read will put the data from the file.

It is guaranteed that at most count bytes will be read, but often less will be, either because, for readln, the file represents a terminal and input stops at the end of a line, or for both, end-of-file has been reached.

readln causes "line-editing" such as echoing to take place and returns once the first "\n" is encountered in the input or the number of bytes requested has been read. readln is the preferred call for reading from the user's terminal.

read does not cause any such editing. See the OS-9 manual for a fuller description of the actions of these calls.

Diagnostics

read and readln return the number of bytes actually read (0 at end-of-file) or -1 for physical I/O errors, a bad path number, or a ridiculous count.

Note that end-of-file is not considered an error, and no error indication is returned. Zero is returned on EOF.

See Also

open(), creat(), dup()

sbrk, ibrk - Request additional working memory

Usage

char *sbrk(increase)
char *ibrk(increase)

Description

sbrk requests an allocation from free memory and returns a pointer to its base.

sbrk requests the system to allocate "new" memory from outside the initial allocation.

Users should read the Memory Management section of this manual for a fuller explanation of the arrangement.

ibrk requests memory from inside the initial memory allocation.

Diagnostics

sbrk and ibrk return -1 if the requested amount of contiguous memory is unavailable.

setptr - Set process priority

Usage

setpr(pid, priority)

Assembler Equivalent

os9 F$$SPrior

Description

setpr sets the process identified by pid (process id) to have a priority of priority. The lowest priority is 0 and the highest is 255.

Diagnostics

The call will return -1 if the process does not have the same user id as the caller.

setime, getime - Set and get system time

  1. include <time.h>
setime(buffer)
getime(buffer)
struct sgtbuf *buffer; /* defined in time.h */

Assembler Equivalent

os9 F$STime
os9 F$GTime

Description

getime returns system time in buffer.

setime sets system time from buffer.

setuid - Set user id

Usage

setuid(uid)

Assembler Equivalent

os9 F$SUser

Description

This call may be used to set the user id for the current task. setuid only works if the caller is the super user (user id 0).

Diagnostics

Zero is returned from a successful call, and -1 is returned on error.

See Also

getuid()

setstat - Set file status

Usage

  1. include <sgtstat.h>
setstat(code, filnum, buffer) /* code 0 */
char *buffer
setstat(code, filenum, size) /* code 2 */
long size

Assembler Equivalent

os9 F$SetStt

Description

For a detailed explanation of this call, see the OS-9 System Programmer's Manual.

filenum must be the path number of a currently open file. the only values for code at this time are 0 and 2. When code is 0, buffer should be the address of a 32 byte structure which is written to the options section of the path descriptor of the file. The header file contains definitions of various structures maintained by OS-9 for use by the programmer. When code is 2, size should be a long integer specifying the new file size.

signal - Catch or ignore interrupts

Usage

  1. include <signal.h>
(*signal(interrupt, address))()
(*address)();
Which means signal returns a pointer to a function, address is a pointer to a funtion.

Description

This call is a comprehensive method of catching or ignoring signals sent to the current process. Notice that kill() does the sending of signals, and signal() does the catching.

Normally, a signal sent to a process causes it to terminate with the status of the signal. If, in advance of the anticipated signal, this system call is used, the program has the choice of ignoring the signal or designating a function to be executed when it is received. Different functions may be designated for different signals.

The values for address have the following meansings:

0 reset to the default i.e. abort when received
1 ignore; this will apply until reset to another value
otherwise taken to be the address of a C function which is to be executed on receipt of the signal

If the latter case is chosen, when the signal is received by the process the address is reset to 0, the default, before the function is executed. This means that if the next signal received should be caught then another call to signal() should be made immediately. This is normally the first action taken by the interrupt function. The function may access the signal number which caused its execution by looking at its argument. On completion of this function the program resumes at the point at which it was interrupted by the signal.

An example should help to clarify all this. Suppose a program needs to create a temporary file which should be deleted before exiting. The body of the program might contain fragments like this:

    pn = creat("temp", 3);              /* create a temporary file */
    signal(2, intrupt);                 /* ensure tidying up */
    signal(3, intrupt);
    write(pn, string, count);           /* write to temporary file */
    close(pn);                          /* finished writing */
    unlink(pn);                         /* delete it */
    exit(0);                            /* normal exit */

The call to signal() will ensure that if a keyboard or quit signal is received then the funtion intrupt() will be executed and this might be written:

    intrupt(sig)
    {
        close(pn);                      /* close it if open */
        unlink("temp");                 /* delete it */
        exit(sig);                      /* received signal as exit status */
    }

In this case, as the function will be exiting before another signal is received, it is unnecessary to call signal() again to reset its pointer. Note that either the function intrupt() should in the source code before the call to signal(), or it should be predeclared.

The signals used by OS-9 are defined in the header file as follows:

    /* OS-9 signals */
    #define SIGKILL  0    /* system abort (cannot be caught or ignored) */
    #define SIGWAKE  1    /* wake up */
    #define SIGQUIT  2    /* keyboard abort */
    #define SIGINT   3    /* keyboard interrupt */

    /* special addresses */
    #define SIG_DFL  0    /* reset to default */
    #define SIG_IGN  1    /* ignore */

Please note that there is another method of trapping signals, namely intercept(). However, since signal() and intercept() are mutually incompatible, calls to both of these must not appear in the same program. The link-loader will prevent the creation of an executable program in which both are called by aborting with an "entry name clash" error for _sigint.

See Also

intercept(), kill(), OS-9 shell command kill

stacksize, freemem - Obtain stack reservation size

Usage

stacksize()
freemem()

Description

For a description of the meaning and use of this call, the user is referred to the Memory Management section of this manual.

If the stack check code is in effect, a call to stacksize will return the maximum number of bytes of stack used at the time of the call. This call can be used to determine the stack size required by a program.

freemem will return the number of bytes of the stack that has not been used.

See Also

ibrk(), sbrk(), freemem(), Global variable memend and value end

_strass - Byte by byte copy

Usage

_strass(s1, s2, count)
char *s1, *s2;

Description

Until such time as the compiler can deal with structure assignment, this function is useful for copying one structure to another.

count bytes are copied from memory location at s2 to memory at s1 regardless of the contents.

tsleep - Put process to sleep

Usage

tsleep(ticks)

Description

tsleep deativates the calling process for the specified number of system ticks or indefinitely if ticks is zero. A tick is system dependent but is usually 100ms.

For a fuller description of this call, see the OS-9 System Programmer's Manual.

unlink - Remove directory entry

Usage

unlink(fname)
char *fname;

Assembler Equivalent

os9 i$Delete

Description

unlink deletes the diretory entry whose name is pointed to by fname. If the entry was the last link to the file, the file itself is deleted and the disk space occupied made available for re-use. If, however, the file is open, in any active task, the deletion of the actual file is delayed until the file is closed.

Errors

Zero is returned from a successful call, -1 if the file does not exist, if the directory is write-protected, or cannot be searched, if the file is a non-empty directory or a device.

See Also

link(), Os-9 command kill

wait - Wait for task termination

Usage

wait(status)
int *status;
wait(0)

Description

wait is used to halt the current task until a child task has terminated.

The call returns the task id of the terminating task and places the status of that task in the integer pointed to by status unless status is 0. A wait must be executed for each child task spawned.

The status will contain the argument of the exit or _exit call in the child task or the signal number if it was interrupted. A normally terminating C program with no call to exit or _exit has an implied call of exit(0).

Caveats

Note that the status is the OS-9 status code and is not compatible with codes on other systems.

Diagnostics

-1 is returned i there is no child to be waited for.

See Also

fork(), signal(), exit(), _exit()

write, writeln - Write to a file or device

Usage

write(pn, buffer, count)
char *buffer;
writeln(pn, buffer, count)
char *buffer;

Assembler Equivalent

os9 I$Write
os9 I$WritLn

Description

pn must be a value returned by open, creat, or dup or should be 0 (stdin), 1 (stdout), or 2 (stderr).

buffer should point to an area of memory from which count bytes are to be written. write returns the actual number of bytes written, and if this is different from count, an error has occurred.

Writes in multiples of 256 bytes to file offset boundaries of 256 bytes are the most efficient.

write causes no "line-editing" to occur on output. writeln causes line-editing and only writes up to the first '\n' in the buffer if this is found before count is exhausted. For a full description of the actions of these calls, the reader is referred to the OS-9 documentation.

Diagnostics

-1 is returned if pn is a bad path number, if count is ridiculous, or on physical I/O error.

See Also

creat(), open(), dup()

Standard Library