

            














                                  UUUssseeerrr'''sss GGGuuuiiidddeee fffooorrr ttthhheee
                                 GGGeeeooorrrgggiiiaaa TTTeeeccchhh CCC CCCooommmpppiiillleeerrr

                                     SSSeeecccooonnnddd EEEdddiiitttiiiooonnn












                                 Daniel H. Forsyth, Jr.
                                     Edward J. Hunt
                                    Jeanette T. Myers
                                    Arnold D. Robbins












                       School of Information and Computer Science
                             Georgia Institute of Technology
                                 Atlanta, Georgia  30332


                                      October, 1984








            




            


                                        FFFooorrreeewwwooorrrddd


                 The  Georgia  Tech  C  compiler and run time support library
            provide a C programming environment on  Prime  computer  systems.
            The  Georgia  Tech C Compiler runs under and rrreeeqqquuuiiirrreeesss the Georgia
            Tech Software Tools Subsystem, Version 9 or later.  Both  run  on
            PRIME 400, 500 and 50-series computers.

                 This  guide documents the second version of the Georgia Tech
            C compiler and run time library which is released with Version  9
            of  the  Software  Tools  Subsystem.   The eight chapters of this
            guide

                  1) explain the use of the compiler,
                  2) describe   the   machine-dependent   features   of   the
                     implementation,
                  3) describe the compile time environment provided,
                  4) detail the behavior of the run time package,
                  5) enumerate problems of conversion from other systems,
                  6) document known compiler bugs and shortcomings,
                  7) provide some technical information on the implementation
                     and performane of the C compiler, and
                  8) outline actions necessary to manage the C system.

                 A   complete  description  of  C  can  be  found  in  _T_h_e  _C
            _P_r_o_g_r_a_m_m_i_n_g  _L_a_n_g_u_a_g_e  by  Brian  W.   Kernighan  and  Dennis  M.
            Ritchie (Prentice-Hall, 1978).  Further information on individual
            commands  in the C system can be obtained from the _S_o_f_t_w_a_r_e _T_o_o_l_s
            _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l, accessible both on paper and  through
            the  Subsystem  'help'  command.   The C run time library is only
            documented here.  There are no 'help' entries for the  individual
            subroutines.

                 Wherever  a  routine  or  facility has been changed from the
            first release of the C compiler, it will be explicitly  noted  as
            such.

                 It is to be noted that wherever it appears in this document,
            the term "Unix" is a trademark of AT&T Bell Laboratories, Inc.


















                                         - vi -                              




            C User's Guide                                                   


                                     ___GGG___eee___ttt___ttt___iii___nnn___ggg___ ___SSS___ttt___aaa___rrr___ttt___eee___ddd




                                      PPPrrreeerrreeeqqquuuiiisssiiittteeesss


                 We  assume that you are already familiar with the Subsystem;
            that you can create, delete, edit and list files; redirect  input
            and  output;  obtain  on-line documentation, etc.  We also assume
            that you are familiar with the C programming  language.   If  you
            are  not,  you should examine the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _U_s_e_r_'_s
            _G_u_i_d_e and _T_h_e _C _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e  by  Kernighan  and  Ritchie
            before continuing in this guide.

                 Throughout  this  guide, we boldface user input in our exam-
            ples, as is the convention in the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _U_s_e_r_'_s
            _G_u_i_d_e.



                                 CCCaaalllllliiinnnggg ttthhheee CCC CCCooommmpppiiillleeerrr


                 There are several commands that call the C compiler:

                      cc      - compile a C program
                      ccl     - compile and load a C program
                      ucc     - "Unix-like" C compile and load
                      compile - general purpose compiler interlude

            We follow  with  a  brief  description  of  each.   For  detailed
            information  and  examples  refer to the Reference Manual entries
            for each command, e.g.:

                      ] hhheeelllppp cccccc



            CCCccc --------- cccooommmpppiiillleee aaa CCC ppprrrooogggrrraaammm

                 'Cc' behaves much like the other Subsystem  compiler  inter-
            faces.  It is a program that takes a file whose name ends in ".c"
            and calls the programs necessary to convert it into a relocatable
            object program in a file whose name ends in ".b".  'Cc' calls two
            major  programs:   the  compiler  front  end  'c1',  and the code
            generator 'vcg'.  If you have  no  compile-time  errors  in  your
            program,  you  will  not  see  _a_n_y  messages  at  all from either
            program.  'Cc' automatically "includes" the file "=cdefs=" (which
            is "=incl=/swt_def.c.i")  containing  macros  and  external  data
            declarations  for  the C Standard I/O Library and for interfacing
            with the Subsystem.





                                          - 1 -                              




            C User's Guide                                                   


            CCCccclll --------- cccooommmpppiiillleee aaannnddd llloooaaaddd aaa CCC ppprrrooogggrrraaammm

                 'Ccl' compiles a ".c" file in the same way as 'cc'; it  then
            calls  'ld',  the  Subsystem  loader  interface,  to  produce  an
            executable program in a file with no suffix.  Unfortunately,  the
            Prime loader is somewhat noisy, so you receive a good bit of out-
            put during the execution of 'ld'.


            UUUcccccc --------- cccooommmpppiiillleee aaannnddd llloooaaaddd aaa CCC ppprrrooogggrrraaammm

                 'Ucc'  is  a "Unix-style" C compiler and loader.  It is nnnooottt,
            however, exactly  like  Unix's  'cc'  or  any  other  known  Unix
            program!   'Ucc' recognizes file naming conventions for Subsystem
            supported languages and will  use  the  appropriate  preprocessor
            and/or  compiler to process non-C files.  Consequently, it can be
            used to compile and load several  files  of  different  languages
            into  an executable program, as long as the main program is writ-
            ten in C.  'Ucc' now depends on the new 'compile' program  to  do
            most  of  its  work.   It is just smart enough to arrange to call
            'compile' properly; it no longer knows about all the  details  of
            the C compiler, or how to go about compiling other languages.


            CCCooommmpppiiillleee --------- gggeeennneeerrraaalll pppuuurrrpppooossseee cccooommmpppiiillleee aaannnddd llloooaaaddd

                 'Compile' is a general purpose compiler interlude.  It knows
            about  the  Subsystem  naming  convention  for  the  more popular
            languages available under SWT and Primos.   It  will  arrange  to
            call  the  proper  compiler  for  each  source file, based on the
            suffix.  You may tell it to pass options  on  to  each  different
            compiler  or preprocessor, and also to tell it what is the "main"
            language, in order for it to load any necessary libraries  and/or
            start-off routines.  'Ucc' now just rearranges its arguments, and
            calls 'compile'.



                          CCC PPPrrrooogggrrraaammm DDDeeevvveeelllooopppmmmeeennnttt --------- AAAnnn EEExxxaaammmpppllleee


                 For  this example, the file "inout.c" contains the following
            C program:

                      main ()         /* copy input to output until EOF */
                      {
                              int c;
                      
                              while ((c = getchar()) != EOF)
                                      putchar (c);
                      }

            We can compile and load (i.e., link-edit) "inout" with  the  com-
            mand




                                          - 2 -                              




            C User's Guide                                                   


                      ] cccccclll iiinnnooouuuttt...ccc

            Consistent with Subsystem convention, 'ccl' places the executable
            version  of  "inout.c"  in a file named "inout".  You can execute
            "inout" as follows:

                      ] iiinnnooouuuttt
                      aaa
                      a
                      eeeccchhhooo mmmeee iiifff yyyooouuu dddaaarrreee
                      echo me if you dare
                      <<<cccooonnntttrrrooolll---ccc>>>
                      ]













































                                          - 3 -                              




            C User's Guide                                                   


                               ___FFF___eee___aaa___ttt___uuu___rrr___eee___sss___ ___ooo___fff___ ___GGG___eee___ooo___rrr___ggg___iii___aaa___ ___TTT___eee___ccc___hhh___ ___CCC




                                  SSStttaaannndddaaarrrddd IIImmmpppllleeemmmeeennnttteeeddd


                 The Georgia Tech C compiler is based on  the  specifications
            contained in _T_h_e _C _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e by Brian W. Kernighan and
            Dennis M. Ritchie, Prentice-Hall, 1978.



                                   AAAddddddiiitttiiiooonnnaaalll FFFeeeaaatttuuurrreeesss


                 The   Georgia   Tech   C  compiler  provides  the  following
            extensions to C:
            
            1.  Unions may be initialized.  The first type entry in the union
                will be used to determine the format of the data.  For  exam-
                ple,  "union  {int a; double b;} x = 1;" would initialize "x"
                as an int, not a double.
                
            2.  Except for external names, all characters in  all  names  are
                significant.   External  names  are  up  to  8  characters in
                length, with no case significance.  To allow access to Primos
                system calls, the dollar sign ("$") is also a legal character
                in identifiers.   The  external  names  in  the  object  code
                produced  by the compiler can be up to 32 characters long; it
                is the SEG loader that restricts their lengths to  8  charac-
                ters.   The  'bind' EPF loader _d_o_e_s pay attention to the full
                32 character names.
                
            3.  The late Unix Version 7  enhancements,  structure  assignment
                and   "enum"  types,  are  implemented  (but  not  thoroughly
                tested).
                
            4.  C functions can call Fortran, PL/1, etc.  routines, and  vice
                versa.   C  uses the same calling sequence as all other Prime
                supported languages.  SHORTCALL procedure  calls  (using  the
                JSXB instruction) are not supported by Georgia Tech C.
                
            5.  The  Ratfor/Algol68  radix  notation  may  be used to specify
                integer constants.  In addition to  using  a  leading  0  for
                specifying  octal  and  0x  for  hexadecimal,  Georgia Tech C
                recognizes the Ratfor radix syntax for integer  constants  up
                to base 36.  (For instance, "7r123" is 123 base 7, i.e.  66.)
                
            6.  Single quotes may be used to specify packed character strings
                as  in  Fortran.  The Georgia Tech C compiler treats a single
                character enclosed in apostrophes as  a  character  constant,
                while  more  than  one  character  enclosed in apostrophes is
                considered a pointer to an array  of  integers  containing  a
                packed "hollerith" character constant.


                                          - 4 -                              




            C User's Guide                                                   


                
            7.  The  data type "long unsigned" is supported, giving access to
                32-bit unsigned numbers.
                
            8.  Initialization of automatic aggregates  is  supported.   (The
                code generator is not particularly smart about it, though, so
                initializing  huge  automatic  arrays  is  incredibly  space-
                inefficient.)
                
            9.  Macro definitions ("#define"s) can be specified on  the  com-
                mand line using the "-D" compiler option.
                
            10. Directories to be searched for include files may be specified
                on the command line using the "-I" compiler option.
                
            11. The special macros "__FILE__" and "__LINE__" are supported to
                provide access to the source file name and source line number
                (as a string constant and an integer constant), respectively.








































                                          - 5 -                              




            C User's Guide                                                   


                                 ___CCC___ooo___mmm___ppp___iii___lll___eee___ ___TTT___iii___mmm___eee___ ___FFF___aaa___ccc___iii___lll___iii___ttt___iii___eee___sss




                                IIInnncccllluuudddeee FFFiiillleee OOOrrrgggaaannniiizzzaaatttiiiooonnn


                 The  C  compiler  package comes with several standard header
            files which perform a number of functions for the  C  programmer.
            All include files are kept in the directory =incl=.

                 To maintain compatibility with the previous release of the C
            compiler,  the  file "=cdefs=" which the C compiler automatically
            includes  (unless   you   use   the   "-f"   option)   is   still
            "=incl=/swt_def.c.i".   This  is also in accordance with the Sub-
            system naming convention  for  other  "standard"  include  files.
            However,  _a_l_l  other  C include files end in ".h" (for "header"),
            which is the Unix convention (this should  make  porting  code  a
            little easier as well).

                 The  "=cdefs=" file itself has been considerably reorganized
            for the second release.  This organization is discussed below.


            ===iiinnnccclll===///ssswwwttt___dddeeefff...ccc...iii

                 This  file  now  contains  very  few   actual   definitions.
            Instead,  it  ###iiinnncccllluuudddeees  separate files to provide the same func-
            tionality as it previously did.

                 We have reorganized the include files to both  increase  the
            available  functionality,  and  to  separate  the  features  into
            appropriate,  self-contained,  "modules".    So   that   previous
            programs  which  depend  on  "=cdefs=" to contain everything need
            from breaking, "=cdefs=" includes the files it  needs.   All  the
            include  files  have  been organized so that they may be included
            more than once.  The definitions will only take effect the  first
            time.

                 The  following  identifiers are defined in "=cdefs=" for use
            in determining what kind of hardware and software environment the
            program will run in.  This is useful for writing code designed to
            be ported to more than one  computing  system.   The  identifiers
            are:

                      #define gtswt   1       /* using Software Tools */
                      #define primos  1       /* os is primos */
                      #define prime   1       /* hardware is prime */
                      #define pr1me   1       /* another name for prime */

            We  have  ###dddeeefffiiinnneeed  the  identifier "gtswt" instead of just plain
            "swt", since "swt" is the name of the routine you have to call in
            order to exit to the Subsystem.




                                          - 6 -                              




            C User's Guide                                                   


                 You would use these identifiers for tailoring your  code  to
            different environments.  For instance

                      #ifdef gtswt
                              /* code to do nifty stuff for Software Tools */
                      #else
                      #ifdef unix
                              /* code to do nifty stuff for Unix */
                      #else
                              /* code to do nifty stuff in a generic environment */
                      #endif
                      #endif


                 "=cdefs="  then includes the following four files (discussed
            below).

                      #include "=incl=/stdio.h"
                      #include "=incl=/ctype.h"
                      #include "=incl=/swt.h"
                      #include "=incl=/ascii.h"

            Following the discussion of these four  main  files,  we  briefly
            discribe the other include files which are available.


            ===iiinnnccclll===///ssstttdddiiiooo...hhh

                 This  file  contains the declarations and definitions needed
            to use the C Standard I/O Library.

                 The following functions, macros, and symbolic constants  are
            available  for  the  programmer to use.  (There are others, whose
            names begin with '_', which the programmer  should  not  need  to
            use, so they aren't discussed here).

            typedef ... FILE;   The standard type FILE.

            /* declaration of functions */
            extern long ftell();
            extern FILE *fopen(), *fdopen(),  *freopen(), *popen();
            extern char *fgets(), *gets();
            extern char *strcat(), *strcpy(), *strncpy(), *strpbrk(), *strtok();
            extern char *strchr(), *strrchr(), *index(), *rindex();

            stdin         Standard Input.
            stdout        Standard Output.
            stderr        Standard Error Output (Standard Output 3).
            stdin1        Subsystem name for stdin.
            stdout1       Subsystem name for stdout.
            stdin2        Standard Input Port 2.
            stdout2       Standard Output Port 2.
            stdin3        Standard Input Port 3.
            stdout3       Standard Output Port 3 (Error Output).
            tty           File pointer which is _a_l_w_a_y_s the terminal.
            errin         Another name for stdin3.


                                          - 7 -                              




            C User's Guide                                                   


            errout        Subsystem name for stderr.

            EOF           End of file indicator (not a valid character).
            NULL          The empty pointer.
            BUFSIZ        A convenient buffer size (used a lot on Unix).
            TRUE          Represents logical true.
            FALSE         Represents logical false.

            L_cuserid     The length of a string to hold a user id.
            L_ctermid     The length of a string to hold a terminal name.
            L_tmpnam      The length of a string to hold a temporary file name.
            P_tmpdir      The (string) name of a directory for temporary files.

            getchar()     Get a character from stdin.
            putchar(ch)   Put a character on stdout.

            feof(fp)      Did EOF happen on this file?
            ferror(fp)    Did an error occur on this file?
            clearerr(fp)  Clear all error flags for this file.
            fileno(fp)    Give the SWT file descriptor for the FILE pointer.

                 Any  functions  which  don't  return  iiinnnttt, and which are not
            declared in "=incl=/stdio.h", should be declared  before  they're
            used.   (The  type  of each function in the C library is given in
            the chapter on the run time environment, below.)


            ===iiinnnccclll===///ccctttyyypppeee...hhh

                 This file defines the character testing macros discussed  in
            the  chapter  on the run time environment.  These macros are very
            useful, and are often faster than writing an explicit test  (e.g.
            islower(c)  should  be  faster than (c >= 'a' && c <= 'z')).  The
            macros have been rewritten to only evaluate their argument  _o_n_c_e,
            so  that  they  won't  bite  you if the argument has side effects
            (.e.g.  islower(*c++)).


            ===iiinnnccclll===///ssswwwttt...hhh

                 This file provides most of the functionality that the Ratfor
            programmer obtains from "=incl=/swt_def.r.i".  Some of the Ratfor
            specific  declarations  have  been  deleted  (for  example,   the
            "dynamic memory" routines).  The programmer is referred to Appen-
            dix  D  of  the  _U_s_e_r_'_s _G_u_i_d_e _f_o_r _t_h_e _R_a_t_f_o_r _P_r_e_p_r_o_c_e_s_s_o_r and the
            "swt.h" file itself for details.

                 One thing that may need clarifying:   The  SET_OF_?*  macros
            are used in the following way:









                                          - 8 -                              




            C User's Guide                                                   


                          .
                          .
                      switch (c = getchar()) {
                      case SET_OF_UPPER_CASE:
                              /* stuff for upper case */
                              break;
                      
                      case SET_OF_LOWER_CASE:
                              /* stuff for lower case */
                              break;
                      
                      case SET_OF_DIGITS:
                              /* stuff for digits */
                              break;
                      
                      default:
                              /* stuff for default */
                              break;
                      }
                          .
                          .

            In  other  words,  you  supply  the leading cccaaassseee and the trailing
            colon; the macro supplies everything else.


            ===iiinnnccclll===///aaasssccciiiiii...hhh

                 This file contains definitions for the ASCII  mnemonics,  as
            well  as  for  the control characters.  E.g.  Both BEL and CTRL_G
            are defined as octal 0207.  The synonyms  BACKSPACE,  TAB,  BELL,
            RHT, and RUBOUT for other characters are also defined.


            ===iiinnnccclll===///aaasssssseeerrrttt...hhh

                 This   file   defines   the  'assert'  macro.   It  must  be
            specifically included in order to use it.  See the chapter on the
            run time environment for what the 'assert' macro does.


            ===iiinnnccclll===///dddeeebbbuuuggg...hhh

                 This file declares a macro "debug" which is useful for  put-
            ting debugging code into your programs.  For instance:

                      #include <debug.h>
                      ...
                      debug (fprintf (stderr, "i == %d\n", i));
                      /* note the balanced parentheses */
                      ...

            If  the  symbol  "DEBUG"  has  been  defined  _b_e_f_o_r_e <debug.h> is
            included, then whatever occurs as  an  argument  to  the  "debug"
            macro  will  be  placed into the source code.  Otherwise, "debug"
            becomes a null macro.  The easiest way to turn debugging on is to


                                          - 9 -                              




            C User's Guide                                                   


            put "debug" statements in your code, and then do a  "-DDEBUG"  on
            the compiler command line.  For larger blocks of code, you can do

                      #ifdef DEBUG
                              /*
                               * a lot of debugging code
                               */
                      #endif



            ===iiinnnccclll===///kkkeeeyyysss...hhh

                 This  file  declares  the  symbolic keys for the Primos file
            system.  It is the analogue of "=incl=/keys.r.i".


            ===iiinnnccclll===///llliiibbb___dddeeefff...hhh

                 This  file  is  analogous  to  the   Ratfor   include   file
            "=incl=/lib_def.r.i".   It contains symbolic constants and macros
            which are useful for dealing with the low  level  Software  Tools
            Library routines.


            ===iiinnnccclll===///mmmaaattthhh...hhh

                 This  file  contains  declarations  for all the mathematical
            routines in the C library.  These routines all return dddooouuubbbllleee.


            ===iiinnnccclll===///mmmeeemmmooorrryyy...hhh

                 This file contains declarations of mem?*  functions.   These
            functions  are  similar  to  the  str?*  functions,  but  work on
            arbitrary areas of memory, and do not care about the  zero  word,
            '\0'.   This  file should be included before using the functions,
            although you can always just declare each function  before  using
            it.


            ===iiinnnccclll===///ssseeetttjjjmmmppp...hhh

                 This file _m_u_s_t be included if you intend to use the 'setjmp'
            and 'longjmp' non-local goto functions.


            ===iiinnnccclll===///ssswwwttt___cccooommm...hhh

                 This  file  contains the necessary ###dddeeefffiiinnneees and declarations
            for accessing the Software Tools common blocks from a C  program.
            It  has  not  been  extensively  tested.   See  the file for more
            details.





                                         - 10 -                              




            C User's Guide                                                   


            ===iiinnnccclll===///vvvaaarrraaarrrgggsss...hhh

                 This file contains definitions which allow you  to  portably
            write functions which expect a variable number of arguments.  The
            macros  are  discussed below, in the chapter dealing with the run
            time environment.  They have not been extensively tested, but  do
            seem to work.



                           LLLoooaaadddiiinnnggg CCC PPPrrrooogggrrraaammmsss FFFooorrr BBBaaarrreee PPPrrriiimmmooosss


                 Several  of  the  routines  in  the  C Library depend on the
            shared Subsystem libraries to do some of their work.

                 In order for you to write  C  programs  to  run  under  bare
            Primos, we have provided a second run time library with alternate
            versions  of  these  few subroutines, as well as a second C start
            off routine.  Most routines perform the same under both the  Sub-
            system and bare Primos.  Those few which behave differently under
            bare  Primos  are detailed in the chapter on run time facilities.
            In particular, they always return the  value  that  indicates  an
            error has occurred.

                 The  alternate  C start off routine and run time library are
            in  the  files  =lib=/nc$main  and  =lib=/nciolib,  respectively.
            Since  loading  programs for bare Primos is not simple, 'ld' does
            not have an option for loading C programs for running without the
            Subsystem.  You must do it yourself, by hand.

                 To load a C program for use with bare  Primos,  follow  this
            procedure:

              1) Load  the  file  =lib=/nc$main.   This is the alternate
                 startoff routine, which does some extra initialization.

              2) Load your C binaries.

              3) Load =lib=/nciolib.  This library contains versions  of
                 the  few  routines  which  act  differently  under bare
                 Primos.  This library also contains a  special  version
                 of  'getarg',  to  allow  'argc'  and  'argv'  to  work
                 properly.  The environment pointer, 'envp' (see below),
                 will be set to NULL when a program is loaded  for  run-
                 ning under bare Primos.

              4) Load =lib=/ciolib.  This contains the rest of the C run
                 time library.

              5) Load  =lib=/vswtmath, if your C program uses the C math
                 routines.






                                       - 11 -                           




            C User's Guide                                              


              6) Load =lib=/nvswtlib.  This is the non-shared version of
                 the Subystem library, which does most of the real work.

              7) Load any system libraries, e.g.  the Fortran library.


                 You should actually  be  able  to  use  'ld'  to  load  your
            program, following this outline:

                      ] lllddd ---dddnnnuuu ---lll nnnccc$$$mmmaaaiiinnn <<<bbbiiinnnaaarrriiieeesss>>> ---lll nnnccciiiooollliiibbb ---lll ccciiiooollliiibbb ___
                         [[[---lll vvvssswwwtttmmmaaattthhh]]] ---lll nnnvvvssswwwtttlllbbb ---ttt ---mmm ---ooo <<<eeexxxeeecccuuutttaaabbbllleee___fffiiillleee>>>


                 You will probably not have too many programs to be run under
            bare Primos, but we have provided for this possibility.











































                                         - 12 -                              




            C User's Guide                                                   


                                  ___RRR___uuu___nnn___ ___TTT___iii___mmm___eee___ ___EEE___nnn___vvv___iii___rrr___ooo___nnn___mmm___eee___nnn___ttt




                          CCCaaalllllliiinnnggg PPPrrriiimmmooosss aaannnddd SSSuuubbbsssyyysssttteeemmm RRRooouuutttiiinnneeesss


                 C  programs  have  access  to  all Primos system and library
            subroutines and Software Tools library routines.  Georgia Tech  C
            follows  Prime's  established  conventions for parameter passing,
            thus allowing C routines to call or be called by programs written
            in other high-level languages or in assembly language.  For exam-
            ple the following C program uses the  Ratfor  subroutine  'putch'
            for output:

                      main ()      /* copy input to output until EOF */
                      {
                              int c;
                      
                              while ((c = getchar()) != EOF)
                                      putch (c, STDOUT);
                      }

            'Ccl'  and  'ucc'  both  use the Subsystem loader interface 'ld'.
            When loading C programs, 'ld' automatically includes the C  Stan-
            dard I/O Library, "ciolib", the SWT math library, "vswtmath", the
            shared  shell library, "vshlib", and the shared Subsystem I/O and
            utility  library  "vswtlb".   However,  if  another  library   is
            required, e.g.  one of your own making, "mylib", then the follow-
            ing command must be used:

                      ] cccccclll <<<ppprrrooogggrrraaammm___nnnaaammmeee>>> ---lll mmmyyyllliiibbb




                                    TTThhheee MMMaaaiiinnn PPPrrrooogggrrraaammm


                 All  complete  C programs must have a function named 'main',
            which is where execution will  begin.   The  'main'  function  in
            Georgia  Tech  C  Programs  may  have  zero,  one,  two, or three
            arguments.  If there are arguments,  the  first  is  an  integer,
            which  indicates  the number of command line arguments there were
            (including the command name).  The second  is  a  pointer  to  an
            array  of character strings containing the text of the arguments.
            The final element in the array will be equal to NULL.  The  third
            argument  is  a  similar pointer to an array of character strings
            containing a list of _n_a_m_e===_v_a_l_u_e  pairs.   These  are  your  shell
            variables  and  their  values.   (This  is  just  like  the  Unix
            environment pointer, although shell variables aren't  as  heavily
            used  under  Software  Tools.)   Try this sample program (call it
            junk.c):




                                         - 13 -                              




            C User's Guide                                                   


                      main (argc, argv, envp)
                      int argc;               /* argument count */
                      char **argv;            /* argument values */
                      char **envp;            /* environment pointer */
                      {
                              int i;
                      
                              for (i = 0; i < argc; i++)
                                      printf ("%s\n", argv[i]);
                      
                              for (i = 0; envp[i] != NULL; i++)
                                      printf ("%s\n", envp[i]);
                      }

            Compile and run it with:

                      ] cccccclll jjjuuunnnkkk...ccc
                      ] jjjuuunnnkkk fffoooooo bbbaaarrr bbbaaazzz

            You should see something like:

                      junk
                      foo
                      bar
                      baz
                      HOME=/uc/arnold
                      _prt_dest=LPB
                      _search_rule=^int,^var,&,=ubin=/&,=lbin=/&,=bin=/&

            The program printed its arguments, and then the names and  values
            of any shell variables you may have set.



                                   CCC RRRuuunnn TTTiiimmmeee LLLiiibbbrrraaarrryyy


                 The  Georgia Tech C Run Time Library, "ciolib", is a version
            of the C Standard I/O library.  It is automatically loaded with C
            programs by 'ccl' and 'ucc'.  This section describes the routines
            available in "ciolib".

                 We have attempted to provide almost all the routines in Sec-
            tion 3 of the _U_N_I_X _U_s_e_r_'_s _M_a_n_u_a_l, for Release 1 of UNIX System V.
            In particular, "ciolib" contains all of the routines marked  "3S"
            (the Standard I/O Library), most of the routines marked "3M" (the
            Math  library),  as  many as possible of the routines marked "3C"
            (routines automatically loaded with  every  C  compilation),  and
            even  some of the routines marked "3X" (routines from specialized
            libraries).  In addition, there are routines to emulate  some  of
            the more useful (and easy to implement) Unix system calls.  These
            should help when porting programs originally written to run under
            Unix.   Finally,  there are a few routines which are not provided
            under Unix at all, but which allow access to certain features  of
            Primos, or which are just generally useful.



                                         - 14 -                              




            C User's Guide                                                   


                 NNNOOOTTTEEE:::   The  calling sequences of two routines, 'c$ctov' and
            'c$vtoc', have changed since the first release of the C compiler.
            The original motivation for these routines was that the C end-of-
            string character ('\0') was different  from  the  Subsystem  EOS.
            Since  they  are  now  the same, these routines have been brought
            closer in line with the behavior of the other C string  routines.
            If you need them the old way, take a look at 'ctov' and 'vtoc' in
            section  2  of the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l.  No
            other routines have been changed in how they are called, although
            the functionality and/or implementation of  a  routine  may  have
            changed.

                 In  the following, NULL denotes the null pointer (defined in
            "=incl=/stdio.h" as "(char *) 0").  Note  that,  on  the  Primes,
            ASCII  NUL  is  represented  as  octal 0200, while '\0', the zero
            character, has the octal value 0.

                 Finally,  remember  that  "=cdefs="   includes   the   files
            "=incl=/stdio.h",     "=incl=/ctype.h",    "=incl=/swt.h",    and
            "=incl=/ascii.h", so their contents are automatically  available,
            unless you specify the "-f" option.


            UUUNNNIIIXXX SSSyyysssttteeemmm CCCaaallllllsss

                 This  section  describes  the routines in "ciolib" which are
            not part of the Standard I/O Library per se,  but  which  emulate
            Unix system calls.

                 The  Unix  i/o system calls operate on integers, called file
            descriptors.  Due to the  similarity  with  Software  Tools  file
            descriptors,  these  routines  usually act as interludes to their
            SWT counterparts, but return the values  described  in  the  Unix
            User's Manual.


              ...  ccchhhdddiiirrr --------- ccchhhaaannngggeee dddiiirrreeeccctttooorrryyy

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int chdir (path)
                      char *path

                 'Chdir' is used to change the current working directory.  It
                 uses  the  SWT routine 'getto' to actually change directory.
                 'Chdir' returns 0 if it succeeded, -1 if it failed.

                 Note that under Primos, if a program  does  a  'chdir',  you
                 will  be  in  the  new directory when the program exits, not
                 where you were when the program started.








                                         - 15 -                              




            C User's Guide                                                   


              ...  ccclllooossseee --------- ccclllooossseee aaannn ooopppeeennn fffddd

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int close (fd)
                      int fd;

                 'Close' closes a file associated with  the  file  descriptor
                 'fd'  returned  by  'creat'  or 'open'.  'Close' flushes any
                 data buffers associated with the file and returns  0  if  it
                 was  successful.   If  an  error occurs, 'close' returns -1.
                 This is not the same as SWT's 'close'  (it's  a  macro),  so
                 "=incl=/stdio.h"  must  be  included  for 'close' to work as
                 described.

              ...  cccrrreeeaaattt --------- cccrrreeeaaattteee aaa fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int creat (name, mode)
                      char *name;
                      int mode;   /* protection mode; not used on Prime */

                 'Creat' creates and opens the file 'name' with WRITE  access
                 and  returns a file descriptor.  The new file has protection
                 keys of "a/" (owner  has  all  permissions).   If  the  file
                 'name'  already  exists,  'creat'  opens  it for writing and
                 truncates it to length 0.  An existing file must have either
                 "wt/" or "a/" protection keys  (owner  has  bbbooottthhh  write  and
                 truncate  permission).   A return value of -1 indicates that
                 the file cannot be created or that an attempt  was  made  to
                 'creat'  an  existing  file  with the wrong protection keys.
                 'Mode' is ignored in this implementation.

              ...  ooopppeeennn --------- ooopppeeennn aaa fffiiillleee,,, rrreeetttuuurrrnnn aaa SSSWWWTTT fffddd

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int open (name, mode)
                      char *name;
                      int mode;

                 'Open' provides a "Unix-style" call to open a file for read-
                 ing and/or writing and returns a file descriptor.  'Mode'  =
                 0  specifies  read  access,  1 specifies write access, and 2
                 specifies read/write access.  A return value of -1 indicates
                 that the file does not exist (as determined  by  filtst(2)),
                 or  cannot  be opened (access mode does not match protection
                 keys, or no free file descriptors  are  available)  or  that
                 'mode'  was  invalid.  The C 'open' is not the same as SWT's
                 'open' (it's a macro), and requires that "=incl=/stdio.h" be
                 included to function correctly.






                                         - 16 -                              




            C User's Guide                                                   


              ...  eeexxxiiittt --------- eeexxxiiittt fffrrrooommm ttthhhiiisss ppprrrooogggrrraaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int exit (exit_val)
                      int exit_val;   /* not used on the Primes */

                 'Exit' closes all open files and returns  to  the  Subsystem
                 (or  to  bare  Primos).   Temporary files that may have been
                 created  during  program  execution  remain   in   directory
                 "=temp=".  'Exit_val' is unused.

              ...  gggeeetttpppiiiddd --------- rrreeetttuuurrrnnn ttthhheee cccuuurrrrrreeennnttt ppprrroooccceeessssss nnnuuummmbbbeeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int getpid()

                 'Getpid'  returns  the  current process number.  It uses the
                 Subsystem routine 'date' to retrieve this  information  from
                 Primos.

              ...  lllssseeeeeekkk --------- pppooosssiiitttiiiooonnn tttooo aaa dddeeesssiiigggnnnaaattteeeddd wwwooorrrddd iiinnn fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      long lseek (fd, offset, origin)
                      int fd, origin;
                      long offset;

                 'Lseek'  positions  the  read/write  pointer  for  the  file
                 associated with file descriptor 'fd' (returned by 'creat' or
                 'open') to the word designated by 'offset' and 'origin'.  If
                 'origin' = 0, 'offset' is  the  number  of  words  from  the
                 beginning  of  the  file.   If 'origin' = 1, 'offset' is the
                 number of words forward(backward) from the current position.
                 If  'origin'  =  2,  'offset'  is  the   number   of   words
                 past(before)  the  end of the file.  See 'fseek' for further
                 discussion.
                 
                 If 'lseek' succeeds, it returns the current  file  position;
                 otherwise  it returns -1.  'lseek' calls 'markf', which will
                 flush the buffers associated with 'fd'.















                                         - 17 -                              




            C User's Guide                                                   


              ...  rrreeeaaaddd --------- rrreeeaaaddd rrraaawww wwwooorrrdddsss fffrrrooommm aaa fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int read (fd, buf, nw)
                      int fd, nw;
                      char *buf;

                 'Read' reads words from the file associated  with  the  file
                 descriptor  'fd'  (returned by 'creat' or 'open') until 'nw'
                 words have been read or until it encounters the end of file.
                 If 'fd' is attached to a terminal device, 'read'  will  col-
                 lect characters until it encounters a NEWLINE.
                 
                 If   an   error  occurred,  'read'  returns  -1;  if  'read'
                 encounters the end of the file or if a disk error  occurred,
                 it  returns  0,  so  both  -1 and 0 should be taken as error
                 returns.  Otherwise, 'read'  returns  the  number  of  words
                 transferred to 'buf'.

              ...  uuunnnllliiinnnkkk --------- dddeeellleeettteee aaa fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int unlink (path)
                      char *path;

                 Since  Primos  does  not  support  links  to files, 'unlink'
                 always removes the file.  If the file is open by  any  other
                 user,  or  if the file does not have protection keys "t/" or
                 "a/" (owner has truncate  permission)  'unlink'  will  fail.
                 'Unlink' returns -1 on failure and 0 otherwise.

              ...  wwwrrriiittteee --------- wwwrrriiittteee rrraaawww wwwooorrrdddsss tttooo aaa fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int write (fd, buf, nw)
                      int fd, nw;
                      char *buf;

                 'Write'  writes 'nw' words from 'buf' to the file associated
                 with a file descriptor 'fd' (returned by 'creat' or 'open').
                 If an error occurs or if 'fd' is  attached  to  "/dev/null",
                 'write'  returns  -1.  Otherwise, 'write' returns the number
                 of words written.


            TTThhheee CCC SSStttaaannndddaaarrrddd III///OOO LLLiiibbbrrraaarrryyy

                 The following routines are those listed as "3S",  i.e.   the
            actual  Standard  I/O  Library.   Input/Output  operations in the
            Standard I/O Library occur on objects of  type  "FILE *".   These
            are known variously as file pointers, or I/O streams.




                                         - 18 -                              




            C User's Guide                                                   


                 The routines are listed below in roughly alphabetical order.
            However,   logically  associated  routines  (and/or  macros)  are
            grouped together.

              ...  cccttteeerrrmmmiiiddd --------- rrreeetttuuurrrnnn aaa fffiiillleeennnaaammmeee fffooorrr aaa ttteeerrrmmmiiinnnaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *ctermid (s)
                      char *s;

                 'Ctermid' returns the standard  Georgia  Tech  SWT  terminal
                 name  "/dev/tty".  If 's' is not NULL, then 'ctermid' copies
                 "/dev/tty" into it, and returns 's'.  'S' should be at least
                 'L_ctermid' characters  long.   'L_ctermid'  is  defined  in
                 "=incl=/stdio.h".

              ...  cccuuussseeerrriiiddd --------- rrreeetttuuurrrnnn ttthhheee uuussseeerrr'''sss lllooogggiiinnn nnnaaammmeee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *cuserid (s)
                      char *s;

                 'Cuserid'  returns  the  user's  login  name  consisting  of
                 'L_cuserid' - 1 or fewer lower case non-blank ASCII  charac-
                 ters   followed   by   '\0'.   ('L_cuserid'  is  defined  in
                 "=incl=/stdio.h".)

              ...  fffccclllooossseee --------- ccclllooossseee aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fclose (stream)
                      FILE *stream;

                 'Fclose' closes the file and flushes the  buffer  associated
                 with 'stream'.  'Fclose' returns 0 if the close was success-
                 ful, EOF (-1) otherwise.

              ...  fffeeerrrrrrooorrr  ---------  iiinnndddiiicccaaattteee  iiifff  aaannn  eeerrrrrrooorrr hhhaaasss oooccccccuuurrrrrreeeddd ooonnn aaa gggiiivvveeennn
                 ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int ferror (stream)
                      FILE *stream;

                 'Ferror' returns TRUE if an error has occurred  while  doing
                 i/o  on  'stream.'   It  returns  FALSE  otherwise.  This is
                 actually a macro in "=incl=/stdio.h".







                                         - 19 -                              




            C User's Guide                                                   


              ...  fffeeeooofff --------- iiinnndddiiicccaaattteee iiifff EEEOOOFFF hhhaaasss oooccccccuuurrrrrreeeddd ooonnn aaa gggiiivvveeennn ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int feof (stream)
                      FILE *stream;

                 'Feof' returns TRUE if EOF has  occurred  on  'stream',  and
                 FALSE  otherwise.   'Feof' should be used to find out if EOF
                 has actually occurred, particularly when using  'fread'  and
                 'fwrite'.  This is actually a macro in "=incl=/stdio.h".

              ...  cccllleeeaaarrreeerrrrrr  ---------  cccllleeeaaarrr  aaannnyyy  eeerrrrrrooorrrsss  aaassssssoooccciiiaaattteeeddd  wwwiiittthhh  aaa gggiiivvveeennn
                 ssstttrrreeeaaammm...

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int clearerr (stream)
                      FILE *stream;

                 'Clearerr' will  clear  all  of  the  error  and  EOF  flags
                 associated  with  'stream'.   This  is  actually  a macro in
                 "=incl=/stdio.h".

              ...  fffiiillleeennnooo --------- rrreeetttuuurrrnnn aaa SSSuuubbbsssyyysssttteeemmm fffiiillleee dddeeessscccrrriiippptttooorrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fileno (stream)
                      FILE *stream;

                 'Fileno' is a macro in "=incl=/stdio.h"  which  returns  the
                 Software  Tools  Subsystem  file  descriptor associated with
                 'stream'.  (Each FILE structure contains  a  Subsystem  file
                 descriptor, along with other information that the programmer
                 should  not  need  to access.)  This permits you to use Sub-
                 system routines that require a file descriptor rather than a
                 file pointer, for instance:

                              FILE *fp;
                              ...
                              fp = fopen ("file", "w");
                              /* do formatted i/o with a Subsystem routine */
                              print (fileno (fp), "i = *d*n", i);














                                         - 20 -                              




            C User's Guide                                                   


              ...  ffffffllluuussshhh --------- fffllluuussshhh aaallllll bbbuuuffffffeeerrrsss fffooorrr aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fflush (stream)
                      FILE *stream;

                 'Fflush' ensures that the contents and position of the  open
                 file reflect all output and positioning operations performed
                 by the program.  In other words, any in-memory C library and
                 operating  system  buffers  are flushed to disk, so that the
                 permanent file matches the "logical" file (the file that the
                 program has been working with).  This is analogous to making
                 changes to a file with the screen editor, and then issuing a
                 "w" command to force the changes back out to  the  permanent
                 file.

                 Please  note  that  'fflush'  called on a disk file anywhere
                 other than after a NEWLINE has  been  read  or  written  may
                 cause   undesirable  results,  since  Primos  measures  file
                 positions in words and the i/o library writes  in  units  of
                 bytes.   Flushing  in  the  middle  of  a line can cause the
                 compressed-blank count to be lost on an input  file  or  can
                 cause an additional '\0' (padding the last word) to be writ-
                 ten  to  an  output  file.  'Fflush' also dumps the stream's
                 'ungetc' buffer.

                 'Fflush' returns EOF (-1) if the flush failed, 0 if  it  was
                 successful.

              ...  fffooopppeeennn --------- ooopppeeennn aaannn iii///ooo ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      FILE *fopen (name, mode)
                      char *name, *mode;

                 'Fopen'  opens a file 'name' and returns a pointer to an i/o
                 stream.  If the file does not exist, 'fopen' will create it.
                 The stream has the mode specified in 'mode':

                      _M_o_d_e     _e_q_u_i_v_a_l_e_n_t _S_W_T _m_o_d_e

                      "r"      read, file not truncated
                      "r+"     read/write, file not truncated
                      "w"      write, file truncated
                      "w+"     read/write, file truncated
                      "a"      append for writing, file not truncated
                      "a+"     read/append for writing, file not truncated

                 Opening a file for write ("w", "w+")  access  truncates  the
                 file  to  length 0, while opening it for read ("r", "r+") or
                 append ("a", "a+") access does not.   The  file  pointer  is
                 positioned  to  the  beginning of the file for both read and
                 write access, and to the end of the file for append  access.
                 Append  mode  forces  all  writes to occur on the end of the


                                         - 21 -                              




            C User's Guide                                                   


                 file, even if the file was opened for reading as  well,  and
                 it is not currently at the end of the file.

                 'Fopen'  returns  NULL  if  no  streams are available, if an
                 invalid mode is supplied, if any of the arguments  are  bad,
                 or  if  the access mode does not match the Primos protection
                 keys.

              ...  fffrrreeeooopppeeennn --------- aaassssssoooccciiiaaattteee aaa nnneeewww fffiiillleee wwwiiittthhh aaannn ooopppeeennneeeddd ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      FILE *freopen (name, mode, stream)
                      char *name, *mode;
                      FILE *stream;

                 'Freopen'  closes  the  file   currently   associated   with
                 'stream', opens the file 'name' with mode 'mode' (same as in
                 'fopen'),  and  associates  it with 'stream'.  This function
                 finds use in  associating  named  files  with  the  standard
                 stream identifiers 'stdin', 'stdout', and 'stderr'.

                 'Freopen'  returns  NULL if the mode specified is invalid or
                 if the file 'name' cannot be opened.  If the file  does  not
                 exist, 'freopen' will create it.  In any case, 'stream' will
                 be closed first.

                 Use  of  this routine is normally not possible in a non-Unix
                 environment; Software Tools is an exception, since its  file
                 descriptors  are  very  similar  to  those  used by Unix i/o
                 system calls.

              ...  fffdddooopppeeennn --------- aaassssssoooccciiiaaattteee aaa ssstttrrreeeaaammm wwwiiittthhh aaannn ooopppeeennneeeddd fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      FILE *fdopen (fd, mode)
                      int fd;
                      char *mode;

                 'Fdopen' gets an i/o stream and associates it with the  file
                 descriptor  'fd'  returned by 'creat' or 'open'.  The stream
                 has the mode specified in 'mode'; 'mode' may take  the  same
                 values  as the 'mode' argument to 'fopen'.  This implementa-
                 tion of 'fdopen' dddoooeeesss nnnooottt check to make sure that  modes  of
                 the file descriptor and the stream are the same.

                 The function returns NULL if an invalid mode is specified or
                 if  there  are  no  free  i/o streams.  Successful execution
                 returns a pointer to the newly assigned stream.








                                         - 22 -                              




            C User's Guide                                                   


              ...  fffrrreeeaaaddd --------- rrreeeaaaddd rrraaawww wwwooorrrdddsss fffrrrooommm aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fread (ptr, itemsize, nitems, stream)
                      char *ptr;
                      int itemsize, nitems;
                      FILE *stream;

                 'Fread' reads 'nitems' * 'itemsize' words from 'stream' into
                 the  buffer  addressed  by  'ptr'.    ('Itemsize'   may   be
                 determined using the sssiiizzzeeeooofff operator.)  The function returns
                 the  number  of items of size 'itemsize' read without error.
                 If an error occurs or if it encounters end-of-file,  'fread'
                 returns  0.   Results  are  unpredictable  if more words are
                 requested than there is space in the buffer.

              ...  fffwwwrrriiittteee --------- wwwrrriiittteee rrraaawww wwwooorrrdddsss tttooo aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fwrite (ptr, itemsize, nitems, stream)
                      char *ptr;
                      int itemsize, nitems;
                      FILE *stream;

                 'Fwrite' writes 'itemsize' * 'nitems'  words  onto  'stream'
                 from  the  buffer  pointed to by 'ptr'.  If an error occurs,
                 'fwrite' returns 0; otherwise it returns the number of  suc-
                 cessfully written items of size 'itemsize'.

              ...  fffssseeeeeekkk --------- pppooosssiiitttiiiooonnn tttooo aaa dddeeesssiiigggnnnaaattteeeddd wwwooorrrddd iiinnn aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fseek (stream, offset, origin)
                      FILE *stream;
                      long offset;
                      int origin;

                 'Fseek'  first  flushes  the  stream  buffers (including the
                 'ungetc' buffer) to clear up any pending i/o on 'stream' and
                 then positions the read/write pointer to the word  specified
                 by  'offset' and 'origin'.  If 'origin' = 0, 'offset' is the
                 number of words from the beginning of the file.  If 'origin'
                 = 1, 'offset' is the number of words forward (backward) from
                 the current position.  If 'origin' = 2, 'offset' is the num-
                 ber of words past (before) the end  of  the  file.   'Fseek'
                 returns -1 if an error occurs or 0 if it succeeds.

                 There  are  several things to note about 'fseek'.  First, it
                 is not possible to seek past the end of a Primos file;  zero
                 words  ('\0's)  must be written to extend the file.  Second,
                 positioning to the end of a  Primos  sequential-format  file
                 requires  Primos to read all of the blocks in the file (i.e.
                 'origin' = 2 can be quite slow).  Third, since  Primos  text


                                         - 23 -                              




            C User's Guide                                                   


                 files contain blank compression and '\0' padding, an 'fputs'
                 of  a  30-character string will probably not change the file
                 pointer's position by 30; 'ftell' at the beginning of a line
                 is the only reliable way to obtain a file position of a line
                 in a text file.  Finally, flushing the  stream  buffers  may
                 have  undesirable  results if it occurs during the formation
                 of a line (i.e.  before 'fputs', 'fprintf', etc.   have  put
                 out a complete line).

              ...  rrreeewwwiiinnnddd --------- rrreeewwwiiinnnddd tttooo bbbeeegggiiinnnnnniiinnnggg ooofff ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int rewind (stream)
                      FILE *stream;

                 'Rewind'  positions  the  read/write pointer associated with
                 'stream' to the beginning of the file.  It is equivalent  to
                 "fseek  (stream, 0L, 0)".  Returns 0 if it was successful or
                 -1 if an error occurred.  (Under Unix, 'rewind'  returns  no
                 value).

              ...  fffttteeellllll --------- rrreeetttuuurrrnnn aaabbbsssooollluuuttteee pppooosssiiitttiiiooonnn iiinnn aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      long ftell (stream)
                      FILE *stream;

                 'Ftell'  returns the current word position in 'stream' after
                 flushing the stream buffers (and  the  'ungetc'  buffer)  to
                 clear any pending i/o on the stream.

                 Under  Primos,  'ftell'  may  actually corrupt (slightly) an
                 output text file when it flushes  the  stream  buffers.   On
                 text  files, 'markf' is the only reasonable way to determine
                 the position of the beginning of a line.  See  the  comments
                 under 'fseek'.  'Ftell' returns -1 if an error occurs.

              ...  gggeeetttccc --------- gggeeettt aaa ccchhhaaarrraaacccttteeerrr fffrrrooommm aaa ssstttrrreeeaaammm

              ...  gggeeetttccchhhaaarrr --------- gggeeettt aaa ccchhhaaarrraaacccttteeerrr fffrrrooommm '''ssstttdddiiinnn'''

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int getc (stream)
                      FILE *stream;

                      int getchar()

                 'Getc'  obtains  the next character from 'stream'.  If there
                 are no more  characters,  or  if  an  error  occurs,  'getc'
                 returns EOF (-1).

                 'Getchar'  is  a  macro;  it  is defined as 'getc(stdin)' in
                 "=incl=/stdio.h".


                                         - 24 -                              




            C User's Guide                                                   


              ...  fffgggeeetttccc --------- gggeeettt nnneeexxxttt ccchhhaaarrraaacccttteeerrr fffrrrooommm ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fgetc (stream)
                      FILE *stream;

                 'Fgetc' is another function which does what 'getc' does.  It
                 was initially created to serve as a real function  that  one
                 could  take the address of etc., since under Unix, 'getc' is
                 a macro.  On the prime, both 'getc' and  'fgetc'  are  func-
                 tions.

              ...  gggeeetttwww --------- gggeeettt aaa mmmaaaccchhhiiinnneee wwwooorrrddd fffrrrooommm aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int getw (stream)
                      FILE *stream;

                 'Getw'  returns  a  single  16-bit word from a stream or EOF
                 (-1) if  an  error  occurred  or  no  more  characters  were
                 available.   If  'stream'  is attached to a terminal, 'getw'
                 returns EOF when a NEWLINE is encountered.  Since EOF  could
                 be an actual word value, 'feof' should be used to see if end
                 of file has actually occurred.

              ...  gggeeetttsss --------- gggeeettt aaa ssstttrrriiinnnggg (((uuuppp tttooo aaa nnneeewwwllliiinnneee))) fffrrrooommm '''ssstttdddiiinnn'''

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *gets (s)
                      char *s;

                 'Gets'  copies the next line from 'stdin' into 's', discard-
                 ing the NEWLINE and terminating 's' with  '\0'.   If  'gets'
                 returns  a line, the function return value is 's'; otherwise
                 it is NULL.

              ...  fffgggeeetttsss --------- gggeeettt aaa ssstttrrriiinnnggg fffrrrooommm aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *fgets (line, size, stream)
                      char *line;
                      int size;
                      FILE *stream;

                 'Fgets' fetches the  next  line  from  'stream'  by  copying
                 characters into 'line' from the stream buffer until 'size'-1
                 characters  have been copied or until it encounters the next
                 NEWLINE character.  The  NEWLINE  character  _i_s  kept.   The
                 function  appends  '\0'  as  the  last  character in 'line'.
                 'Fgets' returns 'line' if  it  obtained  a  line,  and  NULL
                 otherwise.



                                         - 25 -                              




            C User's Guide                                                   


              ...  pppooopppeeennn --------- iiinnniiitttiiiaaattteee aaa """pppiiipppeee""" tttooo///fffrrrooommm aaa ppprrroooccceeessssss

              ...  pppccclllooossseee --------- ccclllooossseee aaa ssstttrrreeeaaammm ooobbbtttaaaiiinnneeeddd fffrrrooommm pppooopppeeennn

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      FILE *popen (command, type)
                      char *command, *type;

                      int pclose (stream)
                      FILE *stream;

                 'Popen'  takes  two string arguments.  The first, 'command',
                 is a command to be executed by  the  Software  Tools  shell.
                 The  second,  'type', is either "r" or "w", to read from the
                 standard output of the command, or to write to the  standard
                 input  of the command, respectively.  The function return is
                 a stream which can be treated like any other object of  type
                 "FILE *".

                 'Popen' will return NULL if 1) another "pipe" is still open,
                 2)  the  'type'  argument is invalid, 3) the shell could not
                 execute the command, or 4) needed temporary files could  not
                 be created.

                 'Pclose'  closes  the  stream  obtained  from  'popen'.   It
                 returns 0 if it could successfully close the "pipe",  other-
                 wise it returns -1.

                 For   programs  that  use  "=lib=/nciolib",  'popen'  _a_l_w_a_y_s
                 returns NULL, and 'pclose' _a_l_w_a_y_s returns -1.

                 See the help on shell(2) in  the  _S_o_f_t_w_a_r_e  _T_o_o_l_s  _S_u_b_s_y_s_t_e_m
                 _R_e_f_e_r_e_n_c_e  _M_a_n_u_a_l  for  some  caveats  when dealing with the
                 shell.

              ...  ppprrriiinnntttfff --------- fffooorrrmmmaaatttttteeeddd ooouuutttpppuuuttt tttooo '''ssstttdddooouuuttt'''

              ...  fffppprrriiinnntttfff --------- fffooorrrmmmaaatttttteeeddd ooouuutttpppuuuttt tttooo aaa ssstttrrreeeaaammm

              ...  sssppprrriiinnntttfff --------- fffooorrrmmmaaatttttteeeddd mmmeeemmmooorrryyy tttooo mmmeeemmmooorrryyy cccooonnnvvveeerrrsssiiiooonnn

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int printf (control [, arg1, arg2, ..., arg10])
                      char *control;
                      _u_n_t_y_p_e_d arg1, arg2, ..., arg10;

                      int fprintf (stream, control [, arg1, arg2, ..., arg10])
                      FILE *stream;
                      char *control;
                      _u_n_t_y_p_e_d arg1, arg2, ..., arg10;

                      int sprintf (string, control [, arg1, arg2, ..., arg10])
                      char *string;
                      char *control;


                                         - 26 -                              




            C User's Guide                                                   


                      _u_n_t_y_p_e_d arg1, arg2, ..., arg10;

                 'Printf' formats its arguments ('arg1', ..., 'arg10') accor-
                 ding to conversion specifications in 'control'  and  outputs
                 the  resulting  character string on 'stdout'.  The arguments
                 may be pointers (i.e., to strings)  or  names  of  variables
                 (e.g.,  ints,  floats, ...).  'Fprintf' does the same thing,
                 but to the named 'stream'.  'Sprintf' places  the  formatted
                 output into 'string'.  These routines take care of accessing
                 the   arguments  according  to  the  specifications  of  the
                 'control' string.   In  the  following  discussion  'printf'
                 should be taken as a generic name for all three functions.

                 The  'control' string contains literal characters, which are
                 copied to the "output" directly, and  up  to  10  conversion
                 specifiers,   each   of  which  must  have  a  corresponding
                 argument.  These routines conform as closely as possible  to
                 the  specifications  given for 'printf' in the UNIX System V
                 User's Manual (Release 1).

                 A conversion specifier may consist of the following:

                      required  %         Begins conversion specification.

                      optional  flag      Modifies the meaning of the conver-
                                          sion specifier.

                      optional  <number>  Minimum field  width.   More  space
                                          will   be   used   if  needed.   If
                                          <number> begins with "0", then  "0"
                                          will  be  used as a padding charac-
                                          ter; otherwise, 'printf'  pads  the
                                          output field with blanks.

                      optional  .         Separates     field    width    and
                                          precision.

                      optional  <number>  Precision:    maximum   number   of
                                          characters  to  print from a string
                                          or maximum number of digits to  the
                                          right  of  the  decimal  point in a
                                          real number.

                      optional  [lh]      Size of  argument  indicator.   'l'
                                          indicates  a  long  integer,  'h' a
                                          short.    The   'h'   modifier   is
                                          recognized,  but  has  no effect on
                                          the conversion.

                      required            Conversion specifier.

                 A field width or precision may be a '*' instead of a decimal
                 integer.  In this case, the next argument  in  the  argument
                 list  will  be  treated as an integer and used for the field
                 width or precision.



                                         - 27 -                              




            C User's Guide                                                   


                 The flag may be one of the following:


                 -         Left justify the conversion within the field.

                 +         The  result  of  a  signed  conversion  is  always
                           signed.   I.e.   a  '+'  will  be prepended if the
                           result is positive.

                 <blank>   If the first character of a signed  conversion  is
                           not  a  minus  sign,  the result will be prepended
                           with a blank.  The '+' flag overrides the  <blank>
                           flag.

                 #         Convert  the  result  to  an alternate form.  This
                           flag has no effect on the ccc, ddd, sss, and  uuu  conver-
                           sion  specifiers.  For ooo conversion, the precision
                           is increased so that the result has a  leading  0.
                           For xxx (XXX) conversion, the result will have a lead-
                           ing  000xxx  (000XXX).  For eee, EEE, fff, ggg, and GGG conversions,
                           the result should always  have  a  decimal  point,
                           even  if there are no digits following the decimal
                           point.

                 The conversion characters and their meanings are:


                      d,o,u,x,X Interpret the  corresponding  argument  as  a
                                decimal,  octal  (no  leading  "0"), unsigned
                                decimal or  hexadecimal  (no  leading  "0x"),
                                integer, respectively.  For xxx conversion, the
                                letters  aaabbbcccdddeeefff are used, while for XXX conver-
                                sion, the letters AAABBBCCCDDDEEEFFF are used.

                      c         Interpret the argument as a character (unpac-
                                ked).

                      s         The argument  is  a  '\0'-terminated  string:
                                output characters until the correct precision
                                has   been   achieved,   or   until  '\0'  is
                                encountered, whichever comes first.

                      e,E       Interpret the  corresponding  argument  as  a
                                _d_o_u_b_l_e_-_p_r_e_c_i_s_i_o_n  floating-point  number  and
                                print it in the form

                                     [-]m{m}.n{n}eee+_xx.

                                EEE format will cause  the  exponent  to  start
                                with EEE instead of eee.








                                         - 28 -                              




            C User's Guide                                                   


                      f         Interpret  the  corresponding  argument  as a
                                _d_o_u_b_l_e_-_p_r_e_c_i_s_i_o_n  floating-point  number  and
                                print it in the form

                                     [-]m{m}.n{n}

                                with  'precision'  digits to the right of the
                                decimal point.   If  'precision'  is  greater
                                than 14, at most 6 significant digits will be
                                printed.

                      g,G       Use  the  shortest  of  %e and %f formats.  GGG
                                format indicates %E instead of %e.

                 If the character "%" follows the initial "%" of the  control
                 specifier,  the  pair  is  taken as a literal character "%".
                 'Printf' returns the number of successfully printed  charac-
                 ters or EOF (-1) if an error occurred.

                 Note  that  the old style (undocumented) capital letter con-
                 version specifiers, which indicated 'long'  arguments  (e.g.
                 %D  for lllooonnnggg iiinnnttt), are not supported.  Use %ld (for example)
                 instead of %D.

              ...  pppuuutttccc --------- pppuuuttt aaa ccchhhaaarrraaacccttteeerrr ooonnn aaa ssstttrrreeeaaammm

              ...  pppuuutttccchhhaaarrr --------- pppuuuttt aaa ccchhhaaarrraaacccttteeerrr ooonnntttooo '''ssstttdddooouuuttt'''

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int putc (ch, stream)
                      char ch;
                      FILE *stream;

                      int putchar (c)
                      char c;

                 'Putc' puts the single character in 'ch' on 'stream'.  If an
                 error occurs, 'putc' returns EOF (-1); otherwise it  returns
                 the character just written.

                 'Putchar'  is a macro; it is defined as 'putc(c, stdout)' in
                 "=incl=/stdio.h".

              ...  fffpppuuutttccc --------- pppuuuttt aaa ccchhhaaarrraaacccttteeerrr ooonnn aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fputc (c, stream)
                      char c;
                      FILE *stream;

                 'Fputc' is another function which does what 'putc' does.  It
                 was initially created to serve as a real function  that  one
                 could  take the address of etc., since under Unix, 'putc' is
                 a macro.  On the prime, both 'putc' and  'fputc'  are  func-


                                         - 29 -                              




            C User's Guide                                                   


                 tions.

              ...  pppuuutttwww --------- pppuuuttt rrraaawww wwwooorrrdddsss ooonnn aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int putw (w, stream)
                      int w;
                      FILE *stream;

                 'Putw'  writes  a  single  16-bit word on 'stream'.  After a
                 successful write 'putw' returns the word written,  while  it
                 returns  EOF  (-1)  if  an  error  occurred.  If 'stream' is
                 attached to "/dev/null", 'putw' always returns EOF.

              ...  pppuuutttsss --------- pppuuuttt aaa ssstttrrriiinnnggg ooonnn '''ssstttdddooouuuttt'''

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int puts (s)
                      char *s;

                 'Puts' appends a NEWLINE to the '\0'-terminated  string  's'
                 and  prints  it  on  standard  output.  If an errors occurs,
                 'puts' returns EOF (-1).

              ...  fffpppuuutttsss --------- pppuuuttt aaa ssstttrrriiinnnggg ooonnn aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int fputs (s, stream)
                      char *s;
                      FILE *stream;

                 'Fputs' puts the '\0'-terminated  string  's'  on  'stream'.
                 Note  that 's' need not contain a NEWLINE character and that
                 'fputs' will nnnooottt supply one.  'Fputs' returns EOF (-1) if an
                 error occurred, zero otherwise.

              ...  ssscccaaannnfff --------- fffooorrrmmmaaatttttteeeddd iiinnnpppuuuttt cccooonnnvvveeerrrsssiiiooonnn fffrrrooommm '''ssstttdddiiinnn'''

              ...  fffssscccaaannnfff --------- fffooorrrmmmaaatttttteeeddd iiinnnpppuuuttt cccooonnnvvveeerrrsssiiiooonnn fffrrrooommm ssstttrrreeeaaammm

              ...  sssssscccaaannnfff --------- fffooorrrmmmaaatttttteeeddd iiinnnpppuuuttt cccooonnnvvveeerrrsssiiiooonnn fffrrrooommm aaa ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int scanf (control [, arg1, arg2, ..., arg10])
                      char *control;
                      char *arg1, *arg2, ..., *arg10;

                      int fscanf (stream, control [, arg1, arg2, ..., arg10])
                      FILE *stream;
                      char *control;
                      char *arg1, *arg2, ..., *arg10;



                                         - 30 -                              




            C User's Guide                                                   


                      int sscanf (string, control [, arg1, arg2, ..., arg10])
                      char *string;
                      char *control;
                      char *arg1, *arg2, ..., *arg10;

                 'Scanf' reads characters from 'stdin', formats them  accord-
                 ing  to conversion specifications in the control string, and
                 stores the results in the variables pointed to by correspon-
                 ding arguments 1-10.  'Fscanf'  reads  its  input  from  the
                 named  'stream'.   'Sscanf'  reads characters from the named
                 'string'.  In the following discussion,  'scanf'  should  be
                 taken as a generic name for all three functions.

                 The  control  string may contain white space, which is skip-
                 ped, literal  characters  (which  mmmuuusssttt  match  corresponding
                 characters  from the input stream) and at most 10 conversion
                 specifiers consisting of the following:

                      required  %         Begins conversion specification.

                      optional  *         Suppresses  assignment   of   input
                                          field (does nnnooottt skip argument).

                      optional  <number>  Numeric field width.

                      optional  l         Read variable as 'long'.

                      optional  h         Read variable as 'short'.

                      required            Conversion specifier:

                      '['[^]<char>[-<char>]{<char>[-<char>]}']'
                                  Input  a string of characters until finding
                                  a character not included in  the  bracketed
                                  set.  E.g., "[a-zA-Z]" stops reading when a
                                  non-alphabetic  character  is  encountered.
                                  If the first character in the set  is  '^',
                                  input  characters  are read until finding a
                                  character included in  the  bracketed  set.
                                  E.g., "[^ ]" reads until a blank is found.

                      d,o,u,x     Input  decimal, octal, unsigned decimal, or
                                  hexadecimal integers.

                         c        Read single character(s) including blanks.

                         s        Input a string delimited by white space, or
                                  until <width> characters  have  been  read.
                                  The  variable  in which the string is to be
                                  stored must be long enough to  contain  the
                                  string followed by a '\0'.







                                         - 31 -                              




            C User's Guide                                                   


                        e,f,g     Read a floating point number of the form

                                              [+_]m{m}.n{n}[EEE[+_]x{x}].

                                  The  value  returned  in  both  cases  is a
                                  fffllloooaaattt.  Use the "l"  option  to  specify  a
                                  dddooouuubbbllleee value.

                 If  the character '%' follows the initial '%' of the control
                 specifier, the pair is taken as a literal character '%'.

                 'Scanf' conversions stop when EOF is seen, when the  control
                 string  is  exhausted,  or when an input character conflicts
                 with the control string.

                 'Scanf' returns the number of  successfully  assigned  input
                 items, or EOF (-1) if none were found.

              ...  ssseeetttbbbuuufff --------- ssseeettt bbbuuuffffffeeerrriiinnnggg ooonnn aaa ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      setbuf (stream, buf)
                      FILE *stream;
                      char *buf;

                 Under  Software  Tools  and  Primos,  'setbuf' is a null (do
                 nothing) function.   Under  Unix,  it  allows  the  user  to
                 associate  a  character  array  as  the  buffer  for a given
                 stream.  'Setbuf' is provided to make  porting  of  programs
                 easier.   It  is  an  actual function, just in case there is
                 code which takes its address, or does something else strange
                 of this nature.

              ...  sssyyysssttteeemmm --------- pppaaassssss aaa cccooommmmmmaaannnddd tttooo ttthhheee SSSoooffftttwwwaaarrreee TTToooooolllsss SSShhheeellllll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int system (cmd)
                      char *cmd;

                 'System' passes a command 'cmd' to the Software Tools  shell
                 to be executed, and returns TRUE if the call was successful.
                 If the call failed, 'system' returns FALSE.  See the help on
                 shell(2)  in  the  _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l
                 for some caveats when dealing with the shell.

                 For  programs  that  use  "=lib=/nciolib",  'system'  _a_l_w_a_y_s
                 returns FALSE.

                 NNNOOOTTTEEE:::  This routine has changed from the previous release of
                 the  C compiler.  Before Version 9 of Software Tools, it was
                 not possible to  call  the  Software  Tools  shell,  so  the
                 'system'  routine called the Primos command interpreter.  If
                 you still need to call Primos, see the help on  sys$$(2)  in
                 the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l.


                                         - 32 -                              




            C User's Guide                                                   


              ...  tttmmmpppfffiiillleee --------- cccrrreeeaaattteee aaa ttteeemmmpppooorrraaarrryyy fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      FILE *tmpfile ()

                 'Tmpfile'  returns a pointer to a temporary file opened with
                 "w+" access.  The name of  the  file  is  inaccessible  from
                 inside  a  program.   The  file  actually  created bears the
                 process unique name "=temp=/tm###" (where  ###  ranges  from
                 1-999)  and  remains  in  the  "=temp="  directory after the
                 creating process terminates.  If no  file  can  be  created,
                 'tmpfile' returns NULL.

              ...  tttmmmpppnnnaaammm --------- rrreeetttuuurrrnnn aaa fffiiillleeennnaaammmeee fffooorrr aaa ttteeemmmpppooorrraaarrryyy fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *tmpnam (s)
                      char *s;

                 'Tmpnam'    returns    a    unique   temporary   file   name
                 "=temp=/ct=pid=###" where ### is  a  process  unique  number
                 0-999  and  =pid=  is  the  current  process  id.  Names are
                 recycled after all 1000 have been used.

              ...  ttteeemmmpppnnnaaammm --------- rrreeetttuuurrrnnn aaa fffiiillleeennnaaammmeee fffooorrr aaa ttteeemmmpppooorrraaarrryyy fffiiillleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *tempnam (dir, pfx)
                      char *dir, *pfx;

                 'Tempnam' is designed to give the user a little more control
                 over the name of his temporary file.  The directory for  the
                 tempfile will be taken from the environment variable TMPDIR,
                 if  it  exists.  Otherwise, if 'dir' is not NULL, 'dir' will
                 be used.  If 'dir' is NULL, the directory will  be  P_tmpdir
                 (defined in "=incl=/stdio.h").

                 If  'pfx' is not NULL, it will be used as the prefix for the
                 file name.  Otherwise, the prefix will be "ct".

                 The full file name will consist of  the  directory  name,  a
                 '/',  then  the  prefix, the process id number, and a number
                 between 0 and 999.  The number changes after  each  call  to
                 'tempnam'.   After  all  1000  have  been used, they will be
                 recycled.

                 'Tempnam' uses 'malloc'  to  create  space  for  the  string
                 containing the file name.  The pointer returned by 'tempnam'
                 can be used later in a call to 'free'.

                 'Tempnam' returns NULL if it could not allocate enough space
                 for the string to hold the generated file name.



                                         - 33 -                              




            C User's Guide                                                   


              ...  uuunnngggeeetttccc --------- pppuuussshhh aaa sssiiinnngggllleee ccchhhaaarrraaacccttteeerrr bbbaaaccckkk ooonnn aaannn iiinnnpppuuuttt ssstttrrreeeaaammm

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int ungetc (ch, stream)
                      char ch;
                      FILE *stream;

                 'Ungetc' places 'ch' in a single-character buffer associated
                 with 'stream'.  The next call to 'getc' or 'fgetc' retrieves
                 'ch'.   Attempting to push more than one character back onto
                 the input stream  or  using  'ungetc'  on  a  closed  stream
                 produces  an  error return of EOF (-1).  Otherwise, 'ungetc'
                 returns 'ch'.

              ...  ffftttrrruuunnnccc --------- tttrrruuunnncccaaattteee aaa ssstttrrreeeaaammm aaattt ttthhheee cccuuurrrrrreeennnttt pppooosssiiitttiiiooonnn

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int ftrunc (stream)
                      FILE *stream;

                 'Ftrunc' flushes all file and 'ungetc' buffers for the  file
                 associated  with  'stream'  and  truncates  the  file at its
                 current position.   The  file  must  be  opened  with  write
                 access.  (If 'fopen' is used to open the file, then the only
                 really  useful  values for 'mode' are "r+" and "a+", because
                 read access  is  usually  necessary  to  position  the  file
                 correctly and because opening the file for write ("w", "w+")
                 access always truncates the file.)  'Ftrunc' returns 0 if it
                 succeeded, -1 otherwise.

                 'Ftrunc' is not part of the Standard I/O Library per se, but
                 is  provided  in order to allow access to this capability of
                 the Primos file system.


            UUUnnniiixxx SSSuuubbbrrrooouuutttiiinnneeesss FFFooorrr CCC PPPrrrooogggrrraaammmsss

                 The following routines are those listed as "3C",  i.e.   the
            routines  which  are  loaded along with every Unix C program, but
            which are not guaranteed to be on other non-Unix systems.

                 The character testing  macros  discussed  below  ('isalnum',
            'isdigit',  etc.)   are valid on integers in the range -1 to 0377
            (EOF to ASCII DEL).  They merely return FALSE  on  characters  in
            the  range  -1  to  '\177'.  The result of these macros on values
            less than -1 or greater than 0377 is _u_n_d_e_f_i_n_e_d.

                 These macros do not necessarily return "true"  values  equal
            to  the  symbolic  constant  TRUE  defined  in  "=incl=/stdio.h".
            Rather, they return logical  true,  i.e.  _n_o_n_-_z_e_r_o,  and  logical
            false, i.e. _z_e_r_o. They should be used as conditions, not compared
            against TRUE and FALSE.  In other words, use:




                                         - 34 -                              




            C User's Guide                                                   


                      if (islower (c)) { /* stuff */ }

            and not

                      if (islower (c) == TRUE) { /* stuff */ }


                 The routines are listed below in roughly alphabetical order.
            However,   logically  associated  routines  (and/or  macros)  are
            grouped together.

              ...  aaa666444lll --------- cccooonnnvvveeerrrttt bbbaaassseee---666444 ssstttrrriiinnnggg tttooo lllooonnnggg iiinnnttteeegggeeerrr

              ...  lll666444aaa --------- cccooonnnvvveeerrrttt lllooonnnggg iiinnnttteeegggeeerrr tttooo bbbaaassseee---666444 ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      long a64l (s)
                      char *s;

                      char *l64a (l)
                      long l;

                 'A64l' takes a '\0'-terminated string containing  a  base-64
                 representation,  and returns the corresponding long.  If the
                 string has more than six characters, only the first six  are
                 used.  'L64a' takes a long integer, and returns a pointer to
                 a string with the corresponding base-64 representation.

                 These routines use the following characters as digits in the
                 base-64  notation.   '.'   for 0, '/' for 1, '0' through '9'
                 for 2-11, 'A' through 'Z' for 12-37, and 'a' through 'z' for
                 38-63.

              ...  aaabbbooorrrttt --------- gggeeennneeerrraaattteee aaa """fffaaauuulllttt"""

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int abort ()

                 Under Unix, 'abort' generates a SSSIIIGGGIIIOOOTTT fault,  which  causes
                 the  program to exit and dump core.  The user may catch this
                 signal.  Under Software Tools or Primos, this routine simply
                 exits.

              ...  aaabbbsss --------- rrreeetttuuurrrnnn iiinnnttteeegggeeerrr aaabbbsssooollluuuttteee vvvaaallluuueee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int abs (x)
                      int x;

                 'Abs' returns the absolute value of  its  integer  argument.
                 This  is  a  fast, assembly language routine, local to the C
                 library.



                                         - 35 -                              




            C User's Guide                                                   


              ...  aaatttooofff --------- cccooonnnvvveeerrrttt ccchhhaaarrraaacccttteeerrr ssstttrrriiinnnggg tttooo dddooouuubbbllleee ppprrreeeccciiisssiiiooonnn rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double atof (str)
                      char *str;

                 Converts a string of characters 'str' to a double  precision
                 real number.  Conversion stops when 'atof' encounters a non-
                 numeric character.

              ...  aaatttoooiii --------- cccooonnnvvveeerrrttt ccchhhaaarrraaacccttteeerrr ssstttrrriiinnnggg tttooo iiinnnttteeegggeeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int atoi (str)
                      char *str;

                 'Atoi'  converts  a  string of characters 'str' to a base-10
                 integer.  Conversion stops when  'atoi'  encounters  a  non-
                 numeric   character.    'Atoi'  uses  'gctoi',  so  it  will
                 recognize the Ratfor "radix notation" (e.g.  8r377).

              ...  aaatttooolll --------- cccooonnnvvveeerrrttt ccchhhaaarrraaacccttteeerrr ssstttrrriiinnnggg tttooo lllooonnnggg iiinnnttteeegggeeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      long atol (str)
                      char *str;

                 'Atol' converts a string of characters 'str'  to  a  base-10
                 long   (32-bit)   integer.   Conversion  stops  when  'atol'
                 encounters a non-numeric character in  'str'.   'Atol'  uses
                 'gctol',  so  it  will recognize the Ratfor "radix notation"
                 (e.g.  8r377).

              ...  ssstttrrrtttooolll --------- cccooonnnvvveeerrrttt ssstttrrriiinnnggg tttooo aaarrrbbbiiitttrrraaarrryyy bbbaaassseee lllooonnnggg iiinnnttteeegggeeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      long strtol (str, ptr, base)
                      char *str;
                      char **ptr;
                      int base;

                 'Strtol'  takes  a  '\0'-terminated  string  in  'str',  and
                 returns  the long integer it represents.  'Base' is the base
                 of the string.  If base is less than zero  or  greater  than
                 36,  'strtol' will return.  If base is zero, it will attempt
                 to determine the base from the string itself.  A leading '0'
                 indicates octal, '0x' or '0X' indicates hexadecimal;  other-
                 wise, the string is assumed to be in decimal.

                 If the value of 'ptr' is not (char **) 0, the address of the
                 character  which  terminated  the  string  will be placed in
                 *ptr.  If no integer can be converted from the string,  *ptr


                                         - 36 -                              




            C User's Guide                                                   


                 is set to 'str', and 0 is returned.

              ...  gggeeetttcccwwwddd --------- gggeeettt pppaaattthhhnnnaaammmeee ooofff cccuuurrrrrreeennnttt wwwooorrrkkkiiinnnggg dddiiirrreeeccctttooorrryyy

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *getcwd (buf, size)
                      char *buf;
                      int size;

                 'Getcwd'  returns  a  pointer to a string containing the SWT
                 path name of the current directory.  If 'buf' is  not  NULL,
                 'getcwd' will use 'buf' a buffer in which to place the name.
                 Otherwise,  it  will  use 'malloc' to dynamically allocate a
                 buffer.  In this case, the  returned  pointer  can  be  used
                 later in a call to 'free'.  'Size' is the size of the buffer
                 to  be  'malloc'ed, so it must include room for the trailing
                 '\0'.

                 'Getcwd' returns NULL if size is less than or equal to 1, if
                 'malloc' could not allocate enough memory, or if one of  the
                 SWT routines 'follow' or 'gcdir$' failed.

              ...  gggeeettteeennnvvv --------- rrreeetttuuurrrnnn vvvaaallluuueee fffooorrr """eeennnvvviiirrrooonnnmmmeeennnttt""" vvvaaarrriiiaaabbbllleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      extern char **environ;

                      char *getenv (var)
                      char *var;

                 'Getenv'  scans  the  environment  list  of _n_a_m_e===_v_a_l_u_e pairs
                 pointed to by the external variable 'environ'.  If 'var'  is
                 found,  'getenv' returns a pointer to its value.  Otherwise,
                 it returns NULL.

                 For programs which use "=lib=/nciolib", 'getenv' will _a_l_w_a_y_s
                 return NULL, and 'environ' is always equal to NULL.

              ...  gggeeetttlllooogggiiinnn --------- gggeeettt ttthhheee lllooogggiiinnn nnnaaammmeee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *getlogin()

                 If the current process  is  a  phantom,  'getlogin'  returns
                 NULL.   Otherwise,  it  returns  the  user's  login name, as
                 obtained from 'cuserid'.









                                         - 37 -                              




            C User's Guide                                                   


              ...  gggeeetttooopppttt --------- gggeeettt oooppptttiiiooonnn llleeetttttteeerrr fffrrrooommm aaarrrggguuummmeeennnttt vvveeeccctttooorrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      extern char *optarg;
                      extern int optind;

                      int getopt (argc, argv, optstring)
                      int argc;
                      char **argv;
                      char *optstring;

                 'Getopt' returns the  next  option  letter  in  'argv'  that
                 matches a letter in 'optstring'.  If a letter in 'optstring'
                 is followed by a colon, then that option is supposed to have
                 an  argument,  that  may  or may not be separated from it by
                 white space.  'Optarg' is set to point to the  beginning  of
                 the argument to the current option when 'getopt' returns.

                 'Getopt'  sets 'optind' to the index of the next argument in
                 'argv' to be processed.  Since 'optind' is external,  it  is
                 initialized to zero.

                 When  all  options have been processed (i.e.  when the first
                 non-option  is  encountered),  'getopt'  returns  EOF.   The
                 special  option  ------  can  be  used to delimit the end of the
                 options.  'Getopt' will return EOF, and will skip the ------.

                 'Getopt' returns a '?'   and  prints  an  error  message  on
                 'stderr' when it finds an option that is not in 'optstring'.

              ...  gggeeetttpppaaassssss --------- rrreeeaaaddd aaa pppaaasssssswwwooorrrddd

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *getpass (prompt)
                      char *prompt;

                 'Getpass' disables echoing, and prints 'prompt' on 'stderr'.
                 It  then reads up to a newline or EOF from the terminal.  It
                 returns a pointer to a '\0'-terminated  string  of  at  most
                 eight  characters.   If  'getpass'  cannot  use the TTY file
                 descriptor, and if it cannot open "/dev/tty", it  will  read
                 from 'stdin'.  'Getpass' turns echoing back on before retur-
                 ning.

              ...  iiisssaaalllnnnuuummm --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaalllppphhhaaannnuuummmeeerrriiiccc

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isalnum (ch)
                      char ch;

                 'Isalnum'  returns  TRUE  if  'ch'  falls  in  the range 'A'
                 through 'Z',  inclusive,  in  the  range  'a'  through  'z',
                 inclusive, or if it lies between '0' and '9', inclusive.  It


                                         - 38 -                              




            C User's Guide                                                   


                 returns  FALSE  otherwise.   To  use  this  macro,  the file
                 "=incl=/ctype.h" must be included first.

              ...  iiisssaaalllppphhhaaa --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaalllppphhhaaabbbeeetttiiiccc

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isalpha (ch)
                      char ch;

                 'Isalpha' returns TRUE if 'ch' lies  between  'A'  and  'Z',
                 inclusive, or if it lies between 'a' and 'z', inclusive.  It
                 returns  FALSE  otherwise.   To  use  this  macro,  the file
                 "=incl=/ctype.h" must be included first.

              ...  iiisssdddiiigggiiittt --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaa dddeeeccciiimmmaaalll dddiiigggiiittt

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isdigit (ch)
                      char ch;

                 'Isdigit' returns TRUE if 'ch' lies  between  '0'  and  '9',
                 inclusive.   It returns FALSE otherwise.  To use this macro,
                 the file "=incl=/ctype.h" must be included first.

              ...  iiisssxxxdddiiigggiiittt --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaa hhheeexxxaaadddeeeccciiimmmaaalll dddiiigggiiittt

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isxdigit (ch)
                      char ch;

                 'Isxdigit' returns TRUE if 'ch' falls between '0'  and  '9',
                 inclusive,  or if it falls between 'A' and 'F' inclusive, or
                 'a' and 'f' inclusive.  It returns FALSE otherwise.  To  use
                 this  macro,  the  file  "=incl=/ctype.h"  must  be included
                 first.

              ...  iiisssuuuppppppeeerrr --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaannn uuuppppppeeerrr cccaaassseee llleeetttttteeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isupper (ch)
                      char ch;

                 'Isupper' returns TRUE if 'ch' lies  between  'A'  and  'Z',
                 inclusive.   It returns FALSE otherwise.  To use this macro,
                 the file "=incl=/ctype.h" must be included first.









                                         - 39 -                              




            C User's Guide                                                   


              ...  iiissslllooowwweeerrr --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaannn lllooowwweeerrr cccaaassseee llleeetttttteeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int islower (ch)
                      char ch;

                 'Islower' returns TRUE if 'ch' lies  between  'a'  and  'z',
                 inclusive.   It returns FALSE otherwise.  To use this macro,
                 the file "=incl=/ctype.h" must be included first.

              ...  iiisssppprrriiinnnttt --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss ppprrriiinnntttaaabbbllleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isprint (ch)
                      char ch;

                 'Isprint' returns TRUE if 'ch'  is  a  printable  character.
                 This  includes  all  punctuation,  letters,  digits, and the
                 space character ' '.  It returns FALSE  otherwise.   To  use
                 this  macro,  the  file  "=incl=/ctype.h"  must  be included
                 first.

              ...  iiisssgggrrraaappphhh --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss ppprrriiinnntttaaabbbllleee aaannnddd vvviiisssiiibbbllleee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isgraph (ch)
                      char ch;

                 'Isgraph' is similar to  'isprint'  above,  except  that  it
                 excludes  the  space character ' '.  It returns TRUE if 'ch'
                 has a graphic representation, FALSE otherwise.  To use  this
                 macro, the file "=incl=/ctype.h" must be included first.

              ...  iiissspppuuunnncccttt --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss pppuuunnnccctttuuuaaatttiiiooonnn

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int ispunct (ch)
                      char ch;

                 'Ispunct'  returns  TRUE  if 'ch' is neither an alphanumeric
                 nor a control  character.   To  use  this  macro,  the  file
                 "=incl=/ctype.h" must be included first.












                                         - 40 -                              




            C User's Guide                                                   


              ...  iiissscccnnntttrrrlll --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss aaa cccooonnntttrrrooolll ccchhhaaarrraaacccttteeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int iscntrl (ch)
                      char ch;

                 'Iscntrl'  returns  TRUE if 'ch' is an ASCII control charac-
                 ter, i.e., if 'ch' falls in  the  range  '\200'  to  '\237',
                 inclusive, or if 'ch' equals '\377' (DEL).  It returns FALSE
                 otherwise.   To  use  this  macro, the file "=incl=/ctype.h"
                 must be included first.

              ...  iiisssaaasssccciiiiii ---------  iiinnndddiiicccaaattteee  iiifff  ccchhhaaarrraaacccttteeerrr  iiisss  wwwiiittthhhiiinnn  ttthhheee  AAASSSCCCIIIIII
                 ccchhhaaarrraaacccttteeerrr ssseeettt

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isascii (ch)
                      char ch;

                 'Isascii'  returns  TRUE if 'ch' lies in the range '\200' to
                 '\377',  inclusive  (Prime's  ASCII   representation).    It
                 returns  FALSE  otherwise.   To  use  this  macro,  the file
                 "=incl=/ctype.h" must be included first.

              ...  iiisssssspppaaaccceee --------- iiinnndddiiicccaaattteee iiifff aaa ccchhhaaarrraaacccttteeerrr iiisss wwwhhhiiittteee ssspppaaaccceee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int isspace (ch)
                      char ch;

                 'Isspace' returns TRUE if 'ch' is a space, a tab, a newline,
                 a carriage return, a  form  feed  or  a  vertical  tab.   It
                 returns  FALSE  otherwise.   To  use  this  macro,  the file
                 "=incl=/ctype.h" must be included first.

              ...  mmmaaalllllloooccc --------- aaallllllooocccaaattteee mmmeeemmmooorrryyy

              ...  aaalllllloooccc --------- aaallllllooocccaaattteee mmmeeemmmooorrryyy (((ooolllddd nnnaaammmeee)))

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *malloc (n)
                      int n;

                      char *alloc (n)
                      int n;

                 'Malloc' allocates 'n' words of memory and returns a pointer
                 to the beginning of the storage block.   If  64K  words  are
                 requested  or  if zero words are requested, 'malloc' returns
                 NULL.

                 'Alloc' is  the  name  of  the  pre-Version 7  UNIX  storage


                                         - 41 -                              




            C User's Guide                                                   


                 allocator.   It performs the same function as 'malloc'.  Its
                 use in new programs is _s_t_r_o_n_g_l_y discouraged.  It is provided
                 to make porting code easier, and because it was in the first
                 release of the C compiler.

              ...  cccaaalllllloooccc --------- aaallllllooocccaaattteee mmmeeemmmooorrryyy fffooorrr aaarrrrrraaayyysss ooorrr ssstttrrruuuccctttuuurrreeesss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *calloc (n, size)
                      int n, size

                 'Calloc' allocates 'n' * 'size' words of memory for  storing
                 'n'  objects  of 'size' words each.  If successful, 'calloc'
                 initializes all words to zero, and returns a pointer to  the
                 first  word  of the storage block.  If 64K or more words are
                 requested or if zero words are requested,  'calloc'  returns
                 NULL.

              ...  rrreeeaaalllllloooccc --------- ccchhhaaannngggeee ttthhheee sssiiizzzeee ooofff ppprrreeevvviiiooouuussslllyyy aaallllllooocccaaattteeeddd mmmeeemmmooorrryyy

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *realloc (ptr, size)
                      char *ptr;
                      int size;

                 'Realloc'  reallocates a block of memory of 'size' words for
                 a storage block previously allocated by 'malloc' or 'calloc'
                 (0 < 'size' < 64K).  The contents of  the  original  storage
                 block are preserved by copying to the newly allocated block.
                 Therefore, the pointer 'ptr' passed as a parameter to 'real-
                 loc'  mmmuuusssttt  point  to  the beginning of a block allocated by
                 'malloc' or 'calloc' in order for the copy to work properly.
                 Any existing pointers to the original data structure must be
                 changed.  (I.e.  the contents of the old memory are  preser-
                 ved, but the same actual block of memory may not be used.)

                 'Realloc'  returns  a  pointer  to the first word of the new
                 storage block or NULL if an error occurred.

              ...  fffrrreeeeee --------- fffrrreeeeee aaallllllooocccaaattteeeddd mmmeeemmmooorrryyy

              ...  cccfffrrreeeeee --------- fffrrreeeeee aaallllllooocccaaattteeeddd mmmeeemmmooorrryyy (((ooolllddd nnnaaammmeee)))

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      free (ptr)
                      char *ptr

                      cfree (ptr)
                      char *ptr;

                 'Free' frees a block of memory previously allocated by 'mal-
                 loc', 'realloc', or 'calloc'.  'Free' will fail miserably if
                 handed an arbitrary pointer; only pointers returned by 'mal-


                                         - 42 -                              




            C User's Guide                                                   


                 loc', 'realloc' or 'calloc' are valid parameters.

                 'Cfree' is  the  name  of  the  pre-Version 7  UNIX  storage
                 releaser.  It performs the same function as 'free'.  Its use
                 in  new programs is _s_t_r_o_n_g_l_y discouraged.  It is provided to
                 make porting code easier, and because it was  in  the  first
                 release of the C compiler.

              ...  mmmeeemmmccccccpppyyy --------- cccooopppyyy ccchhhaaarrraaacccttteeerrrsss uuuppp tttooo aaa ccchhhaaarrraaacccttteeerrr ooorrr sssooommmeee nnnuuummmbbbeeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *memccpy (s1, s2, c, n)
                      char *s1, *s2, c;
                      int n;

                 'Memccpy'  copies  characters (words, on the Prime) from the
                 memory pointed to by 's1' into 's2' until it encounters 'c',
                 or until 'n' characters have  been  copied.   It  returns  a
                 pointer  to the character after the first occurrence of 'c',
                 or NULL if 'c' was not found in the first 'n' characters  of
                 's1'.

              ...  mmmeeemmmccchhhrrr --------- rrreeetttuuurrrnnn aaa pppoooiiinnnttteeerrr tttooo aaa ccchhhaaarrr wwwiiittthhhiiinnn aaa mmmeeemmmooorrryyy aaarrreeeaaa

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *memchr (s, c, n)
                      char *s;
                      int c, n;

                 'Memchr'  returns  a  pointer to the first occurrence of 'c'
                 within the first 'n' characters (words,  on  the  Prime)  of
                 's'.  It returns NULL if 'c' does not occur.

              ...  mmmeeemmmcccmmmppp --------- cccooommmpppaaarrreee aaarrrbbbiiitttrrraaarrryyy aaarrreeeaaasss ooofff mmmeeemmmooorrryyy

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int memcpmp (s1, s2, n)
                      char *s1, *s2;
                      int n;

                 'Memcmp'  looks only at the first 'n' words of its first two
                 arguments.  It returns an integer less than zero,  equal  to
                 zero,   or   greater   than   zero,  according  as  's1'  is
                 lexicographically less than, equal to, or greater than 's2'.











                                         - 43 -                              




            C User's Guide                                                   


              ...  mmmeeemmmcccpppyyy --------- cccooopppyyy aaarrrbbbiiitttrrraaarrryyy aaarrreeeaaasss ooofff mmmeeemmmooorrryyy

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *memcpy (s1, s2, n)
                      char *s1, *s2;
                      int n;

                 'Memcpy' copies  'n'  characters  from  's2'  to  's1'.   It
                 returns 's1'.

              ...  mmmeeemmmssseeettt --------- iiinnniiitttiiiaaallliiizzzeee mmmeeemmmooorrryyy tttooo aaa gggiiivvveeennn vvvaaallluuueee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *memset (s, c, n)
                      char *s;
                      int c, n;

                 'Memset'  sets  the  first  'n' characters (words) of 's' to
                 'c'.  It returns 's'.

              ...  mmmkkkttteeemmmppp --------- mmmaaakkkeee aaa uuunnniiiqqquuueee fffiiillleee nnnaaammmeee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *mktemp (template)
                      char *template;

                 'Mktemp' replaces the contents of the string pointed  to  by
                 'template'  with a unique file name, and returns 'template'.
                 'Template' should look like a file name  with  six  trailing
                 XXXs;  'mktemp'  replaces  the XXXs with a unique letter and the
                 process id.  (This implementation only requires four XXXs; six
                 is recommended for portability to/from Unix systems.)

                 If there are no XXXs in the 'template', 'mktemp' returns NULL.
                 The  "unique"  letter  will  recycled  after  26  calls   to
                 'mktemp'.

                 So  that  this  routine  does  not  conflict  with  the  SWT
                 'mktemp', it is actually a macro, so  "=incl=/stdio.h"  must
                 be included in order to use it.

              ...  rrraaannnddd --------- rrreeetttuuurrrnnn aaa rrraaannndddooommm iiinnnttteeegggeeerrr

              ...  sssrrraaannnddd --------- ssseeeeeeddd ttthhheee rrraaannndddooommm nnnuuummmbbbeeerrr gggeeennneeerrraaatttooorrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int rand()

                      srand (seed)
                      unsigned seed;

                 'Rand'  uses 'rand$m' in the SWT Math Library.  It returns a


                                         - 44 -                              




            C User's Guide                                                   


                 number between 0 and 2^16-1.  'Srand' uses 'seed$m' to  seed
                 the  random  number  generator.   In  keeping  with the Unix
                 semantics, if the user calls 'rand' before calling  'srand',
                 the random number generator will be seeded with 1.

              ...  ssseeetttjjjmmmppp --------- ssseeettt uuuppp fffooorrr nnnooonnn---lllooocccaaalll gggoootttooo

              ...  lllooonnngggjjjmmmppp --------- pppeeerrrfffooorrrmmm aaa nnnooonnn---lllooocccaaalll gggoootttooo

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      #include <setjmp.h>

                      int setjmp (env)
                      jmp_buf env;

                      longjmp (env, status)
                      jmp_buf env;
                      int status;

                 'Setjmp'  saves  the  current stack frame in 'env' for later
                 use.  On every call, 'setjmp' returns  0.   'Longjmp'  takes
                 'status'  and  performs a non-local "goto" to an environment
                 ('env') saved by a previous call to 'setjmp'.  The result of
                 that operation allows execution to continue as  if  'setjmp'
                 had  returned  'status'  rather  than  0  at  the  point  of
                 invocation.  Use of these  routines  _r_e_q_u_i_r_e_s  inclusion  of
                 "<setjmp.h>"  before  either  of the routines is called.  In
                 particular  "<setjmp.h>"  does  a  tttyyypppeeedddeeefff   on   the   type
                 'jmp_buf',  and  contains a macro definition which is needed
                 for 'setjmp' to return properly.

              ...  sssllleeeeeeppp --------- sssllleeeeeeppp fffooorrr ttthhheee gggiiivvveeennn nnnuuummmbbbeeerrr ooofff ssseeecccooonnndddsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int sleep (amount)
                      unsigned amount;

                 'Sleep' will sleep for  'amount'  seconds.   'Sleep'  simply
                 calls the Primos 'sleep$' routine.  It returns no value.

              ...  ssstttrrrcccaaattt --------- cccooonnncccaaattteeennnaaattteee tttwwwooo ssstttrrriiinnngggsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strcat (t, s)
                      char *t, *s;

                 'Strcat'  concatenates string 's' to string 't', terminating
                 't' with '\0'.  The target string 't' is assumed to be large
                 enough to accommodate all of the characters copied from 's'.
                 'Strcat' returns a pointer to 't', or NULL if either 's'  or
                 't' is NULL.




                                         - 45 -                              




            C User's Guide                                                   


              ...  ssstttrrrnnncccaaattt --------- cccooonnncccaaattteeennnaaattteee sssuuubbbssstttrrriiinnnggg tttooo ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strncat (t, s, n)
                      char *t, *s;
                      int n;

                 Concatenates  at most 'n' characters of string 's' to string
                 't'.  If 's' contains fewer than 'n' characters,  then  only
                 "strlen  (s)"  characters  will  be  copied.   In  any case,
                 'strncat' terminates 't' with '\0' and returns a pointer  to
                 't'.

              ...  ssstttrrrcccmmmppp --------- cccooommmpppaaarrreee ssstttrrriiinnngggsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      strcmp (s1, s2)
                      char *s1, *s2;

                 'Strcmp'  compares  strings  's1'  and 's2' and returns 0 if
                 they are equal or if s1 = NULL and s2 = NULL.  If *s1 >  *s2
                 or  if  s2  =  NULL,  'strcmp'  returns a positive value; it
                 returns a negative value if *s1 < *s2 or if s1 = NULL.

              ...  ssstttrrrnnncccmmmppp --------- cccooommmpppaaarrreee sssuuubbbssstttrrriiinnngggsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int strncmp (s1, s2, n)
                      char *s1, *s2;
                      int n;

                 'Strncmp' compares at most 'n' characters of 's1' and  's2'.
                 It  returns  0  if  equal  or  if s1 = NULL and s2 = NULL; a
                 positive value if *s1 > *s2 or if s2 = NULL; or  a  negative
                 value if *s1 < *s2 or if s1 = NULL.

              ...  ssstttrrrcccpppyyy --------- cccooopppyyy ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strcpy (t, s)
                      char *t, *s;

                 Copy string 's' to string 't'.  'Strcpy' assumes that 't' is
                 large enough to receive all characters contained in 's'.  If
                 't' is NULL 'strcpy' returns NULL; if 's' is NULL and 't' is
                 non-NULL, 't' is set to the empty string ("").








                                         - 46 -                              




            C User's Guide                                                   


              ...  ssstttrrrnnncccpppyyy --------- cccooopppyyy sssuuubbbssstttrrriiinnnggg tttooo ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strncpy (s1, s2, n)
                      char *s1, *s2;
                      int n;

                 'Strncpy'  copies at most 'n' characters from string 's2' to
                 string 's1'.  If 's2' contains  more  than  'n'  characters,
                 then  's1'  will  not  be '\0'-terminated.  If 's2' contains
                 fewer than 'n' characters (including a terminal '\0'),  then
                 's1' is '\0'-padded until it contains 'n' characters.

              ...  ssstttrrrllleeennn --------- rrreeetttuuurrrnnn llleeennngggttthhh ooofff ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int strlen (s)
                      char *s;

                 'Strlen'  returns  the  length of a string 's' _e_x_c_l_u_d_i_n_g the
                 terminating '\0' character.

              ...  ssstttrrrccchhhrrr --------- fffiiinnnddd ccchhhaaarrraaacccttteeerrr iiinnn ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strchr (s, c)
                      char *s, c;

                 Returns pointer to first  occurrence  of  character  'c'  in
                 string 's'; if 'c' is not found 'strchr' returns NULL.

              ...  ssstttrrrrrrccchhhrrr --------- fffiiinnnddd ccchhhaaarrraaacccttteeerrr iiinnn ssstttrrriiinnnggg (((lllaaasssttt oooccccccuuurrrrrreeennnccceee ooofff)))

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strrchr (s, c)
                      char *s, c;

                 'Strrchr'  returns  a  pointer to the last occurrence of the
                 character 'c' in the string 's'.  If 'c' does not  occur  in
                 's',  NULL  is  returned.   ('Strrchr'  also  works if 'c' =
                 '\0'.)

              ...  ssstttrrrpppbbbrrrkkk --------- fffiiinnnddd ooonnneee ooofff aaa ccclllaaassssss ooofff ccchhhaaarrraaacccttteeerrrsss iiinnn aaa ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strpbrk (s1, s2)
                      char *s1, *s2;

                 Returns a pointer to the first character  in  's1'  matching
                 any  character  in  string  's2', or NULL if no character in
                 's2' is in 's1'.  Both 's1' and 's2' must be non-NULL.


                                         - 47 -                              




            C User's Guide                                                   


              ...  ssstttrrrssspppnnn --------- fffiiinnnddd qqquuuaaallliiifffiiieeeddd sssuuubbbssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int strspn (s1, s2)
                      char *s1, *s2;

                 'Strspn' returns the length of the initial substring of 's1'
                 that is made entirely of characters from  's2'.   If  either
                 's1' = NULL or 's2' = NULL, 'strspn' returns 0.

              ...  ssstttrrrcccssspppnnn --------- fffiiinnnddd qqquuuaaallliiifffiiieeeddd sssuuubbbssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int strcspn (s1, s2)
                      char *s1, *s2;

                 'Strcspn'  returns  the  length  of the initial substring of
                 's1' not having any characters contained in 's2'.

              ...  ssstttrrrtttoookkk --------- fffiiinnnddd tttoookkkeeennnsss iiinnn aaa ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *strtok (s1, s2)
                      char *s1, *s2;

                 'Strtok' returns a pointer to the start  of  each  token  in
                 's1'.   Tokens  are defined as contiguous strings of charac-
                 ters delimited by separators.  'Strtok' skips over any lead-
                 ing separators.  'S2' contains 1 or more  characters  to  be
                 considered  as  token  separators.   When  'strtok'  finds a
                 token, it replaces the terminating delimiter with '\0'.   If
                 it  can't  find  a token with the current set of delimiters,
                 'strtok' returns NULL; however, if  's1'  has  already  been
                 successfully  searched  for a token, the terminating '\0' in
                 's1' is considered a valid delimiter.  Thus, the final token
                 in 's1' can be retrieved without any special finagling  (the
                 '\0'  of  's2'  is never considered a valid separator during
                 the scan of 's1' for delimiters).

                 On the first call to 'strtok', 's1' should point to a  valid
                 string,  while  on  subsequent  calls 's1' should be NULL so
                 that the entire string is scanned.  The characters  in  's2'
                 may change from call to call searching the same 's1'.

              ...  iiinnndddeeexxx --------- fffiiinnnddd ccchhhaaarrraaacccttteeerrr iiinnn ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *index (s, c)
                      char *s, c;

                 Same  as  'strchr'.   This  is  the  V7  (and Berkeley) UNIX
                 routine; the name was changed with UNIX System III.


                                         - 48 -                              




            C User's Guide                                                   


              ...  rrriiinnndddeeexxx --------- fffiiinnnddd ttthhheee lllaaasssttt oooccccccuuurrrrrreeennnccceee ooofff ccchhhaaarrraaacccttteeerrr iiinnn ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *rindex (s, c)
                      char *s, c;

                 Same as 'strrchr'.  This  is  the  V7  (and  Berkeley)  UNIX
                 routine; the name was changed with UNIX System III.

              ...  tttoooaaasssccciiiiii --------- cccooonnnvvveeerrrttt aaa ccchhhaaarrr///iiinnnttt tttooo aaa vvvaaallliiiddd AAASSSCCCIIIIII vvvaaallluuueee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char toascii (ch)
                      char ch;

                 'Toascii'  returns its argument converted into a valid ASCII
                 value.  When unpacking packed character  strings,  'toascii'
                 can  be used to obtain the high character after shifting the
                 packed word right by 8 bits.  The low character can be  got-
                 ten  by passing the whole integer to 'toascii'.  To use this
                 macro, the file "=incl=/ctype.h" must be included first.

              ...  tttooouuuppppppeeerrr --------- cccooonnnvvveeerrrttt lllooowwweeerrr cccaaassseee ccchhhaaarrraaacccttteeerrr tttooo uuuppppppeeerrr cccaaassseee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char toupper (ch)
                      char ch;

                 If 'ch' is  a  lower  case  letter,  'toupper'  returns  the
                 corresponding  upper case letter.  Otherwise it returns 'ch'
                 unchanged.  This  is  actually  a  fast,  assembly  language
                 routine, declared in "=incl=/ctype.h".

              ...  tttooolllooowwweeerrr --------- cccooonnnvvveeerrrttt uuuppppppeeerrr cccaaassseee ccchhhaaarrraaacccttteeerrr tttooo lllooowwweeerrr cccaaassseee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char tolower (ch)
                      char ch;

                 If  'ch'  is  an  upper  case  letter, 'tolower' returns the
                 corresponding lower case letter.  Otherwise it returns  'ch'
                 unchanged.   This  is  actually  a  fast,  assembly language
                 routine, declared in "=incl=/ctype.h".











                                         - 49 -                              




            C User's Guide                                                   


              ...  ___tttooouuuppppppeeerrr --------- bbbllliiinnndddlllyyy cccooonnnvvveeerrrttt aaa ccchhhaaarrraaacccttteeerrr tttooo uuuppppppeeerrr cccaaassseee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char _toupper (ch)
                      char ch;

                 '_toupper' returns 'ch' converted to upper  case.   It  does
                 nnnooottt  check  that its argument is indeed a lower case letter.
                 This function performs the Unix Version 7  'toupper',  which
                 was  changed to '_toupper' in Unix System III to accommodate
                 those who may still want it.  To use this  macro,  the  file
                 "=incl=/ctype.h" must be included first.

              ...  ___tttooolllooowwweeerrr --------- bbbllliiinnndddlllyyy cccooonnnvvveeerrrttt aaa ccchhhaaarrraaacccttteeerrr tttooo lllooowwweeerrr cccaaassseee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char _tolower (ch)
                      char ch;

                 '_tolower'  returns  'ch'  converted to lower case.  It does
                 nnnooottt check that its argument is indeed an upper case  letter.
                 This  function  performs the Unix Version 7 'tolower', which
                 was changed to '_tolower' in Unix System III to  accommodate
                 those  who  may  still want it.  To use this macro, the file
                 "=incl=/ctype.h" must be included first.

              ...  ttttttyyynnnaaammmeee --------- rrreeetttuuurrrnnn ttthhheee nnnaaammmeee ooofff ttthhheee ttteeerrrmmmiiinnnaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *ttyname (fd)
                      int fd;

                 'Ttyname' takes an integer file descriptor as  an  argument.
                 If  the device which is attached to the file descriptor is a
                 terminal, it returns the  string  "/dev/tty",  otherwise  it
                 returns  NULL.   (Under  Unix,  it  would  return the actual
                 device name.)

                 The associated 'isatty' function already exists in SWT.   It
                 may used as is.


            TTThhheee CCC MMMaaattthhh LLLiiibbbrrraaarrryyy

                 The following routines are those listed as "3M", i.e.  the C
            Math  Library.  These routines all take arguments of type dddooouuubbbllleee,
            and return type dddooouuubbbllleee.

                 You should include the file "=incl=/math.h"  which  declares
            these  routines,  before  using  them.  This can be done with the
            line:




                                         - 50 -                              




            C User's Guide                                                   


                         #include <math.h>


                 Most of these routines simply call the corresponding routine
            in the SWT math library, "vswtmath".  See the  _S_W_T  _M_a_t_h  _L_i_b_r_a_r_y
            _U_s_e_r_'_s  _G_u_i_d_e  for  details on how these routines work, and under
            what condition(s) they will raise an error condition.


              ...  aaacccooosss --------- tttaaakkkeee aaarrrccc cccooosssiiinnneee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double acos (x)
                      double x;

                 This routine returns the value obtained from 'dacs$m' in SWT
                 math library.

              ...  aaasssiiinnn --------- tttaaakkkeee aaarrrccc sssiiinnneee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double asin (x)
                      double x;

                 This routine returns the value obtained from 'dasn$m' in SWT
                 math library.

              ...  aaatttaaannn --------- tttaaakkkeee aaarrrccc tttaaannngggeeennnttt ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double atan (x)
                      double x;

                 This routine returns the value obtained from 'datn$m' in SWT
                 math library.

              ...  aaatttaaannn222 --------- tttaaakkkeee aaarrrccc tttaaannngggeeennnttt ooofff xxx///yyy

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double atan2 (x, y)
                      double x, y;

                 This routine first divides x by y.  It passes the result  of
                 the  division  to  the  SWT  math  library routine 'datn$m',
                 returning its result.

              ...  ccceeeiiilll --------- rrreeetttuuurrrnnn sssmmmaaalllllleeesssttt iiinnnttteeegggeeerrr nnnooottt llleeessssss ttthhhaaannn xxx

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double ceil (x)
                      double x;


                                         - 51 -                              




            C User's Guide                                                   


                 This routine uses the  'dint$m'  routine  in  the  SWT  Math
                 Library  to remove the fractional part, and then adds 1.0 if
                 its argument was positive.

              ...  cccooosss --------- tttaaakkkeee cccooosssiiinnneee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double cos (x)
                      double x;

                 This routine returns the value obtained  from  the  'dcos$m'
                 routine in the SWT math library.

              ...  cccooossshhh --------- tttaaakkkeee hhhyyypppeeerrrbbbooollliiiccc cccooosssiiinnneee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double cosh (x)
                      double x;

                 This  routine  returns  the value obtained from the 'dcsh$m'
                 routine in the SWT math library.

              ...  eeexxxppp --------- cccooommmpppuuuttteee eeexxxpppooonnneeennntttiiiaaalll (((bbbaaassseee eee))) ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double exp (x)
                      double x;

                 This routine returns the value obtained  from  the  'dexp$m'
                 routine in the SWT math library (Raise _e to 'x' power).

              ...  fffaaabbbsss --------- cccooommmpppuuuttteee ttthhheee aaabbbsssooollluuuttteee vvvaaallluuueee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double fabs (x)
                      double x;

                 This  routine  returns  the  absolute  value  of  its double
                 precision  argument.   It  is  a  fast,  assembly   language
                 routine, local to the C library.

              ...  fffmmmoooddd --------- dddooo fffllloooaaatttiiinnnggg pppoooiiinnnttt mmmoooddduuullluuusss ooopppeeerrraaatttiiiooonnn

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double fmod (x, y)
                      double x, y;

                 'Fmod'  returns 'x' if 'y' is zero.  Otherwise, it returns a
                 number _f, of the same sign as _x, such that _x = _i_y  _+  _f  for
                 some integer _i, and |_f| < |_y|.



                                         - 52 -                              




            C User's Guide                                                   


              ...  hhhyyypppooottt --------- rrreeetttuuurrrnnn EEEuuucccllliiidddeeeaaannn dddiiissstttaaannnccceee fffuuunnnccctttiiiooonnn

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double hypot (x, y)
                      double x, y;

                 'Hypot' returns

                              sqrt (x * x + y * y)

                 It  does  not  check  for overflow of the multiplication and
                 addition operations (although it should).

              ...  fffllloooooorrr --------- rrreeetttuuurrrnnn lllaaarrrgggeeesssttt iiinnnttteeegggeeerrr nnnooottt gggrrreeeaaattteeerrr ttthhhaaannn xxx

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double floor (x)
                      double x;

                 This routine uses the  'dint$m'  routine  in  the  SWT  Math
                 Library  to  remove  the fractional part, and then subtracts
                 1.0 if its argument was negative.

              ...  llloooggg --------- tttaaakkkeee ttthhheee nnnaaatttuuurrraaalll llloooggg (((bbbaaassseee eee))) ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double log (x)
                      double x;

                 This routine returns the value  obtained  from  the  'dln$m'
                 routine in the SWT math library.

              ...  llloooggg111000 --------- tttaaakkkeee ttthhheee llloooggg bbbaaassseee 111000 ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double log10 (x)
                      double x;

                 This  routine  returns  the value obtained from the 'dlog$m'
                 routine in the SWT math library.

              ...  pppooowww --------- ppprrrooovvviiidddeee eeexxxpppooonnneeennntttiiiaaatttiiiooonnn fffooorrr CCC ppprrrooogggrrraaammmsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double pow (a, b)
                      double a, b;

                 'Pow' computes 'a' to the 'b'.  'Pow' calls 'powr$m' in  the
                 SWT  math  library.   It  may raise 'SWT_MATH_ERROR$' if the
                 first argument is negative, or  if  the  first  argument  is
                 zero,  and  the  second  is negative or zero.  The exception


                                         - 53 -                              




            C User's Guide                                                   


                 will also be raised if the results of the calculation  would
                 cause an overflow.

              ...  sssiiinnn --------- tttaaakkkeee sssiiinnneee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double sin (x)
                      double x;

                 This  routine  returns  the value obtained from the 'dsin$m'
                 routine in the SWT math library.

              ...  sssiiinnnhhh --------- tttaaakkkeee hhhyyypppeeerrrbbbooollliiiccc sssiiinnneee ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double sinh (x)
                      double x;

                 This routine returns the value obtained  from  the  'dsnh$m'
                 routine in the SWT math library.

              ...  sssqqqrrrttt --------- tttaaakkkeee sssqqquuuaaarrreee rrroooooottt ooofff aaa pppooosssiiitttiiivvveee rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double sqrt (x)
                      double x;

                 This  routine  returns  the value obtained from the 'dsqt$m'
                 routine in the SWT math library.

              ...  tttaaannn --------- tttaaakkkeee tttaaannngggeeennnttt ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double tan (x)
                      double x;

                 This routine returns the value obtained  from  the  'dtan$m'
                 routine in the SWT math library.

              ...  tttaaannnhhh --------- tttaaakkkeee hhhyyypppeeerrrbbbooollliiiccc tttaaannngggeeennnttt ooofff aaa rrreeeaaalll

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      double tanh (x)
                      double x;

                 This  routine  returns  the value obtained from the 'dtnh$m'
                 routine in the SWT math library.






                                         - 54 -                              




            C User's Guide                                                   


            UUUnnniiixxx SSSpppeeeccciiiaaalll LLLiiibbbrrraaarrryyy RRRooouuutttiiinnneeesss

                 The following routines are those listed as "3X",  i.e.   the
            routines which require special libraries and/or include files.

              ...  aaasssssseeerrrttt --------- pppuuuttt aaasssssseeerrrtttiiiooonnnsss iiinnntttooo CCC ppprrrooogggrrraaammmsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      #include <assert.h>

                      assert (expression)
                      int expression;

                 The  'assert'  function  is actually a macro which tests the
                 boolean expression.  If the expression  is  FALSE,  'assert'
                 prints  a message to 'stderr', and exits.  The error message
                 will contain the file name and line number of  the  'assert'
                 statement.  The 'assert' macro is written in such a way that
                 it  can  be  used  as a regular statement in a C program; it
                 will not mess up iiifff-eeelllssseee nesting, for instance.

                 Defining NDEBUG before including "<assert.h>" or on the 'cc'
                 (or 'ccl' or 'ucc') command line will turn 'assert'  into  a
                 null (empty) macro.

              ...  lllooogggnnnaaammmeee --------- rrreeetttuuurrrnnn lllooogggiiinnn nnnaaammmeee ooofff uuussseeerrr

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *logname()

                 'Logname'  returns  a  pointer  to  a  string containing the
                 user's login name.   If  the  LOGNAME  environment  variable
                 exists, 'logname' returns its value.  Otherwise, if the tem-
                 plate  =user=  has  a  value,  that  value  is returned.  If
                 neither of those work,  'logname'  returns  NULL.   Both  of
                 these methods are subject to counterfieting.

              ...  vvvaaarrraaarrrgggsss  --------- pppooorrrtttaaabbblllyyy wwwrrriiittteee fffuuunnnccctttiiiooonnnsss wwwiiittthhh aaa vvvaaarrriiiaaabbbllleee nnnuuummmbbbeeerrr
                 ooofff aaarrrggguuummmeeennntttsss

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      #include <varargs.h>

                      _f_u_n_c_t_i_o_n (va_alist)
                      va_dcl
                      va_list _p_v_a_r;
                      va_start (_p_v_a_r);
                      f = va_arg (_p_v_a_r, _t_y_p_e);
                      va_end (_p_v_a_r);

                 The file "=incl=/varargs.h" contains a set of  macros  which
                 allow you to write functions which will have a variable num-
                 ber of arguments in a portable (if slightly opaque) fashion.


                                         - 55 -                              




            C User's Guide                                                   


                      va_alist       is  used  in  place of the argument list
                                     inside the  parentheses  of  a  function
                                     header,  to  declare a vvvaaariable aaargument
                                     llliiisssttt.

                      va_dcl         declares  the  "type"  of  the  variable
                                     argument  list.   Note  that there is _n_o
                                     semicolon after the "va_dcl".

                      va_list        is a "type" for declaring  the  variable
                                     _p_v_a_r.   _P_v_a_r is a variable which will be
                                     used to step through the argument  list.
                                     One such variable must be declared.

                      va_start (_p_v_a_r) initializes  _p_v_a_r  to  the beginning of
                                     the argument list.

                      va_arg (_p_v_a_r, _t_y_p_e) returns the next  argument  in  the
                                     list  pointed  to by _p_v_a_r.  It will be a
                                     value  of  type  _t_y_p_e.    Variables   of
                                     different  types may be mixed, but it is
                                     up to the called  routine  to  determine
                                     their  types,  since this cannot be done
                                     at compile time.

                      va_end (_p_v_a_r)  is used to finish up.

                 The list can be traversed multiple times, as  long  as  each
                 traversal starts with a 'va_start' and ends with 'va_end'.

                 While  'varargs'  originated  at Bell Labs, and is available
                 with System V, it is not documented there.  Instead, its use
                 was popularized with the Berkeley versions of Unix (which do
                 document it).  In any case, you should be able  to  use  the
                 'varargs'  macros  to  portably write functions which take a
                 variable number of arguments (like 'printf' does).

                 The current implementation of 'varargs' allows a maximum  of
                 ten arguments in the 'va_alist'.


            OOOttthhheeerrr RRRooouuutttiiinnneeesss NNNooottt FFFrrrooommm UUUnnniiixxx

                 The  following  routines are not routines found on Unix, but
            are supplied in "ciolib", since they are generally useful.













                                         - 56 -                              




            C User's Guide                                                   


              ...  bbbaaassseeennnaaammmeee --------- rrreeetttuuurrrnnn ttthhheee fffiiillleee nnnaaammmeee pppaaarrrttt ooofff aaa pppaaattthhh nnnaaammmeee

              ...  dddiiirrrnnnaaammmeee --------- rrreeetttuuurrrnnn aaallllll bbbuuuttt ttthhheee lllaaasssttt pppaaarrrttt ooofff aaa pppaaattthhh nnnaaammmeee

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      char *basename (str)
                      char *str;

                      char *dirname (str)
                      char *str;

                 'Basename' returns a pointer to the last  part  of  the  SWT
                 path  name  contained  in 'str'.  If there are no slashes in
                 'str', it returns 'str', otherwise it returns a  pointer  to
                 somewhere in the middle of 'str'.

                 'Dirname' returns a pointer to the directory part of the SWT
                 path  name  contained  in  'str'.   It  copies  'str' into a
                 private buffer (of length MAXPATH), and  then  replaces  the
                 final  slash  with  a  '\0'.   If  there  are no slashes, it
                 changes no characters in  the  buffer.   In  all  cases,  it
                 returns the address of the buffer; the original 'str' is not
                 modified.

                 The following example should clariy what these routines do:

                           basename ("path/file");   returns   "file"
                           dirname ("path/file");    returns   "path"


              ...  ccc$$$ccctttooovvv --------- cccooonnnvvveeerrrttt CCC ssstttrrriiinnnggg tttooo PPPLLL///III ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int c$ctov (dest, src)
                      int *dest;
                      char *src;

                 Converts  the  C string in 'src' to a PL/I varying string in
                 'dest'.  (A PL/I string is an array of integers.  The  first
                 element  contains  the  number  of characters in the string.
                 The rest of the array contains the characters, packed two to
                 a word.)  Conversion terminates when a '\0'  is  encountered
                 in  'src'.   The function return is the number of characters
                 converted to 'var'.  Like other C string routines, no bounds
                 checking is performed (see ctov(2)  in  the  _S_o_f_t_w_a_r_e  _T_o_o_l_s
                 _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l, though).

                 NNNOOOTTTEEE:::   This  routine  has  been  changed  from the previous
                 release of the C compiler.







                                         - 57 -                              




            C User's Guide                                                   


              ...  ccc$$$vvvtttoooccc --------- cccooonnnvvveeerrrttt PPPLLL///III ssstttrrriiinnnggg tttooo CCC ssstttrrriiinnnggg

                 _C_a_l_l_i_n_g _I_n_f_o_r_m_a_t_i_o_n:

                      int c$vtoc (dest, src)
                      char *dest;
                      int *src;

                 Converts a PL/I varying string 'src' to a C  string  'dest'.
                 The function returns the number of characters copied into to
                 'str'.   Again,  no  bounds checking is done (see vtoc(2) in
                 the _S_o_f_t_w_a_r_e _T_o_o_l_s _S_u_b_s_y_s_t_e_m _R_e_f_e_r_e_n_c_e _M_a_n_u_a_l).

                 NNNOOOTTTEEE:::  This routine  has  been  changed  from  the  previous
                 release of the C compiler.











































                                         - 58 -                              




            C User's Guide                                                   


                                       ___CCC___ooo___nnn___vvv___eee___rrr___sss___iii___ooo___nnn




                 The  Georgia  Tech C compiler is based on the specifications
            contained in _T_h_e _C _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e by Kernighan and Ritchie.
            However the C compiler environment is not totally compatible with
            the Unix C implementation.   Simulation  of  a  Unix  environment
            under  Primos  can be done only with an unreasonable loss of per-
            formance.  Therefore, Unix C programs require some conversion  to
            execute  on Prime systems.  (Programs that depend intimately upon
            the Unix process mechanism or the Unix  file  system  layout  are
            more  difficult  to  convert.  Likewise, programs that make heavy
            use of Unix inter-process 'signal' interfaces will  be  difficult
            to convert.)



                                    CCC PPPrrrooogggrrraaammm CCChhheeeccckkkeeerrr


                 There  exist the beginnings of a "C Program Checker" to flag
            possibly dangerous C program constructs when it encounters  them;
            e.g.   type mismatches.  The "C Program Checker" can be called by
            using the "-y" option with 'cc', 'ccl', or 'ucc'.   It  currently
            reports  on  mismatched  formal/actual parameters and misdeclared
            function return values.



                             IIInnncccooommmpppaaatttaaabbbiiillliiitttiiieeesss WWWiiittthhh PPPDDDPPP---111111 CCC


                 The C compiler is compatible with PDP-11 C  where  possible.
            The  following list enumerates those features of the Georgia Tech
            C compiler which are not compatible with PDP-11 C.


            IIInnncccllluuudddeee SSStttaaattteeemmmeeennntttsss

                 The compiler will complain about semicolons appearing at the
            end of include statements.

                 Note that the Georgia Tech C compiler automatically includes
            the standard definitions in "=cdefs=" so that the  typical  Unix-
            style "#include <stdio.h>" is optional.  The compiler will search
            for  an include file starting with the the current working direc-
            tory, through the  directories  listed  with  the  "-I"  compiler
            option  in  the  order listed, and ending with the system include
            directory "=incl=".  Use of  angle  brackets  (e.g.,  <filename>)
            rather  than  double  quotes  (e.g.,  "filename")  in the include
            statement directs the compiler to skip the search of the  current
            working directory.




                                         - 59 -                              




            C User's Guide                                                   


            PPPoooiiinnnttteeerrrsss

                 It  is  currently not possible to make pointers and iiinnnttts the
            same length.  Pointers are 32 bits, iiinnnttts are 16 bits.   The  com-
            piler  tries  to  warn  of  pointer truncation, but cannot always
            detect it.

                 If NULL pointers are to be passed as arguments, they must be
            of type pointer (e.g.  you cannot pass 0 or 0L as a NULL pointer.
            Use  the   symbolic   constant   NULL   which   is   defined   in
            "=incl=/stdio.h" to be "(char*) 0").

                 Pointers  to  dynamically linked objects cannot be compared.
            Pointers to dynamically linked objects (currently only  functions
            are dynamically linked) are actually faulting pointers to charac-
            ter  strings.  At run time, these pointers are filled in with the
            correct linkage address (the links are "snapped") the first  time
            the  pointer  is  referenced  indirectly.   The  C  compiler must
            generate a constant pointer to each external  object  in  each  C
            object  file.   If  relocatable files are linked together, during
            execution it is possible to  have  one  file's  constant  pointer
            snapped, and the other's untouched.  The object code generated by
            the compiler to compare these pointers does not reference through
            the  pointers; it merely treats them as 32-bit integers.  Because
            of this, comparisons of pointers to  dynamically  linked  objects
            may give inconsistent results.  A significant performance penalty
            would  be  required  to  guarantee  consistent  results in such a
            limited case.


            PPPrrrooogggrrraaammm aaannnddd DDDaaatttaaa OOObbbjjjeeecccttt SSSiiizzzeee RRReeessstttrrriiiccctttiiiooonnnsss

                 No source file may require more than 65536 words  of  static
            data.   The static data for each C source file is compiled into a
            single linkage frame, and the linkage frame size  restriction  is
            imposed by the system architecture.

                 If  you  do require very large data objects, you may be able
            to get around this restriction with some work.  You must  declare
            the  data object as an eeexxxttteeerrrnnn and write a Fortran subroutine that
            declares the data object name  as  a  common  block.   Then  when
            accessing  the  contents  of  this  large  block you must somehow
            insure that an object nnneeevvveeerrr crosses a segment boundary (start  it
            at  the  beginning of the next segment just as Fortran does).  If
            you attempt to address an object (such as a dddooouuubbbllleee) across a seg-
            ment boundary, part of your reference simply wrap around  to  the
            beginning of the segment you are trying to reference beyond.

                 No  source  file  may  require  more  than  65536  words  of
            procedure text.  The compiler generates  all  procedures  in  the
            same PMA (Prime Macro Assembler) module.  Currently PMA restricts
            the module size to 65536 words.

                 No  function may generate more than 65536 words of internal-
            format PMA (currently around 16K statements).  This  is  a  code-
            generator  workspace  restriction.   It has only been encountered


                                         - 60 -                              




            C User's Guide                                                   


            with output from  YACC  --  functions  this  huge  are  just  not
            normally  found  around  PDP-11s.   (YACC  is  an  LALR(1) parser
            generator.  Its reads a BNF grammar, and produces  a  C  function
            which  will  parse  the  grammar.  This generated output has many
            large tables.)


            FFFuuunnnccctttiiiooonnnsss

                 In C, all arguments are passed by value.  In Georgia Tech C,
            as long as arguments match in  type  they  are,  in  all  outward
            appearances,   also  passed  by  value.   However,  the  internal
            mechanism for parameter passing is different from Unix C and will
            give different side effects if arguments do not match in type and
            in number.

                 The Prime architecture maintains a stack for local variables
            and  provides  a  64V  mode  procedure  call  argument   transfer
            primitive  for  passing  pointers,  but not data values.  We have
            used this mechanism to take advantage of its  speed.   Therefore,
            pointers  are passed by value, just as in Unix C, but data values
            are not passed by value; a pointer to the data  value  is  passed
            into  the  stack frame of the called procedure; the data value is
            then  copied  into  the  local  stack  frame  by  the   procedure
            initialization code.  This scheme is transparent as long as there
            are  no  type  mismatches.  For this reason, an attempt to cast a
            pointer argument to a non-pointer type will fail.

                 A variable number of arguments can be used, but not  in  the
            same  manner  as  in  Unix.   The  strategy is to declare as many
            arguments as you will ever need (make them pointers so  that  the
            compiler  does  not  try to copy them).  You will actually ignore
            all but the first of these names in  the  function.   This  trick
            forces  the  compiler  to leave enough room for your arguments in
            the procedure's local stack frame.  When the function is  called,
            you  will  find  the first argument pointer at the address of the
            first argument, the second argument pointer at the address of the
            first argument plus 3, the third at  the  address  of  the  first
            argument plus 6, etc.  Note that because of software conventions,
            i.e.,  the  procedure  initialization  code,  functions  that are
            declared with zero arguments must be  called  with  exactly  zero
            arguments;  and  functions  that  are  declared  with one or more
            arguments must _n_o_t be called with zero arguments.

                 Programs that depend on the order  of  parameter  evaluation
            will fail.

                 You  cannot  call  a function with single precision floating
            point arguments nor can you ever expect a function  to  return  a
            single precision floating point argument.  Remember, C turns them
            into double precision.

                 If a structure is to be a return value, the compiler adds on
            an additional first argument through which it passes a pointer to
            a  temporary  area in the calling procedure for the return value.
            Needless  to  say,  type  or  length   mismatches   could   cause


                                         - 61 -                              




            C User's Guide                                                   


            significant nastiness.

                 The  side  effects  of type mismatches are quite predictable
            and can be useful for calling non-C procedures.  For example,  if
            you  pass  a  non-pointer argument to a pointer argument, it will
            behave exactly as if a pointer had been  passed  (i.e.   possibly
            allowing  the  supposed "value" argument to be modified).  If you
            pass a pointer argument to a simple variable argument it  behaves
            just like you passed the value of the argument instead.

                 Be  wary  of  non-C  routines  which  modify their arguments
            (particularly Subsystem routines like  'ctoi');  if  you  pass  a
            constant,  the  "constant" might end up with a different value in
            it than it had before the routine was called!


            AAArrrrrraaayyysss

                 Although it is possible to index outside  of  array  bounds,
            doing  so  is  very dangerous.  In 64V mode, indexed instructions
            are  much  faster  than  32-bit   pointer   arithmetic.    As   a
            consequence,  the  compiler generates 16-bit indexed instructions
            wherever possible.  The only  side  effect  of  this  performance
            improvement is that indexing outside the bounds of arrays may not
            give the expected results.


            IIIdddeeennntttiiifffiiieeerrrsss --------- NNNaaammmiiinnnggg RRReeessstttrrriiiccctttiiiooonnnsss

                 Because  the C compiler originally generated symbolic assem-
            bly language which was then processed by  PMA,  the  Prime  Macro
            Assembler, variable and function names had to follow PMA's naming
            conventions  which  require  that  names begin with an alphabetic
            character.  To achieve the necessary compatibility, variable  and
            function  names  beginning  with  an underscore are prefixed with
            "z$".  Even though 'vcg' now generates object code directly, this
            naming restriction is still in effect.

                 Field names within ssstttrrruuucccttts must be unique since the  C  com-
            piler  does not maintain a separate symbol table for each ssstttrrruuucccttt.
            This behavior is in accordance with K&R and the V7  Unix  C  com-
            piler.   (Berkeley  Unix,  System  III,  and  System  V, all keep
            separate symbol tables for each structure.)


            CCChhhaaarrraaacccttteeerrr RRReeeppprrreeessseeennntttaaatttiiiooonnn aaannnddd CCCooonnnvvveeerrrsssiiiooonnn

                 Character values run from 128-255, not 0-127.

                 Characters are not sign extended when promoted to integers.


            NNNuuummmeeerrriiicccaaalll

                 Programs that use data of type dddooouuubbbllleee may lose precision  in
            trade for increased magnitude.


                                         - 62 -                              




            C User's Guide                                                   


                 See  the  _S_W_T  _M_a_t_h _L_i_b_r_a_r_y _U_s_e_r_'_s _G_u_i_d_e for more details on
            Prime's floating point hardware and software.


            LLLiiibbbrrraaarrryyy IIInnncccooommmpppaaatttiiibbbiiillliiitttiiieeesss

                 The Unix  call  'fork'  cannot  be  efficiently  implemented
            because  of  operating  system restrictions, and is therefore not
            available with Georgia Tech C.

                 'Read' and 'write' calls that do not use 'sizeof' to compute
            the buffer length will probably have to be changed.

                 Programs that open other users' terminals can  not  be  sup-
            ported.


            UUUnnniiixxx FFFiiillleee SSSyyysssttteeemmm IIInnncccooommmpppaaatttiiibbbiiillliiitttiiieeesss

                 Programs that depend intimately on the Unix directory struc-
            ture  ('..',  directory  layout,  links)  will not be easily con-
            verted.

                 Programs that depend on the order and behavior of Unix  file
            descriptors will not be easily converted.

                 You  cannot  depend  on  file descriptors 0, 1, and 2 always
            being connected to standard input, standard output, and  standard
            error  respectively.   Instead, use the macros STDIN, STDOUT, and
            STDERR  (defined  in  "=incl=/swt.h",  which   is   automatically
            included by "=cdefs=").


            TTTaaabbbsss

                 Tabs  are  not  supported  in exactly the same manner on the
            Prime as in Unix.  C programs which produce tabs in their  output
            should  be  run  piping  their  output into the Subsystem program
            'detab' ('detab +8' is recommended).


            SSStttaaatttiiiccc IIInnniiitttiiiaaallliiizzzeeerrrsss

                 Initializers for  static  data  objects  which  involve  the
            "address-of"  operator  may  only  consist of "&objectreference".
            For example, while the statement "static char *x = &A"  is  okay,
            the  statement  "static  char *x = &A+1" cannot be handled by the
            Georgia  Tech  C  compiler.   The  restriction  arises  from  the
            inability  of  PMA/SEG  to handle address expressions of external
            symbols when forming 32-bit pointers.


            RRReeegggiiisssttteeerrrsss

                 In 64V mode, the Prime is essentially a  single  accumulator
            machine.   Thus,  while  the  compiler  recognizes  the  rrreeegggiiisssttteeerrr


                                         - 63 -                              




            C User's Guide                                                   


            keyword, there is no effect on the size or speed of the generated
            code.


            TTThhheee TTTyyypppeee vvvoooiiiddd

                 Berkeley and System III Unix introduced the  new  type  vvvoooiiiddd
            into  the C language.  A vvvoooiiiddd function is one which is guaranteed
            not to return a value (i.e.  a true procedure).   Only  functions
            may  be declared to be of type vvvoooiiiddd, although you may also cast a
            function call to vvvoooiiiddd.  Georgia Tech C does not directly  support
            vvvoooiiiddd, but you may get around it with the simple statement:

                      #define void int

            which  should  allow  you to port practically any code which uses
            vvvoooiiiddd.  Admittedly, this defeats some of the  type  checking  that
            the  new  type  provides,  but  it  will  allow you to port code,
            without having to modify it.







































                                         - 64 -                              




            C User's Guide                                                   


                                          ___BBB___uuu___ggg___sss




                                       KKKnnnooowwwnnn BBBuuugggsss


                 The following is a list of known problems with  the  C  com-
            piler, as well as important enhancements that need to be made.

             1.  In  certain  instances,  the  compiler's  attempt at parsing
                 error correction fails to accept an input token.   This  can
                 result  in  an  infinite loop in the parser as it encounters
                 and reports the same error repeatedly.  A  good  example  is
                 placing  an  extra  semicolon  after  the right brace of the
                 statement in an iiifff, before the corresponding eeelllssseee.  The com-
                 piler will halt after reaching a limit of 50 such messages.
                 
             2.  Bit  fields  must   be   initialized   by   execution   time
                 assignments;  compile  time  initialization  does  not  work
                 correctly.
                 
             3.  If "f" and "g" are type float, then "f*=g" is  performed  in
                 single  precision,  whereas  "f=f*g"  is performed in double
                 precision.  We have not made  a  detailed  analysis  of  the
                 ramifications  of  this situation; it may be that no loss of
                 precision can  be  detected.   Regardless,  because  of  the
                 structure  of  the code generator, it will be very difficult
                 to alter this situation.
                 
             4.  The preprocessor does not support the "#if" construct.
                 
             5.  The parameter-checking option ("-y") does not check calls to
                 the C library.
                 
             6.  A duplicate cccaaassseee in a ssswwwiiitttccchhh is not detected  by  the  first
                 pass  of  the  compiler.   It  will  cause an error (with no
                 information regarding the location of the  error!)   message
                 to  be  reported  by  'vcg'.   In  some  cases,  no error is
                 reported, but 'vcg' generates unreasonable code.
                 
             7.  There are several problems involving duplicated declarations
                 for an external/global  identifier  (e.g.   "extern  a;  int
                 a;").  Most reasonable redeclarations are handled correctly,
                 but  some of the more obscure cases are probably not handled
                 the way the Unix compilers handle them.  In general, correct
                 handling of these odd cases is not described  explicitly--to
                 find  out  how  they  "should" be handled, you have to ask a
                 Unix compiler (and they often give different answers).
                 
             8.  The sequence of declarations "extern  int  a[];  int  a[5];"
                 generates  a  warning  message  that "a" is being redeclared
                 improperly.  This is caused by the  differing  array  bounds
                 confusing   the  compiler  into  thinking  that  the  second
                 declaration is unreasonable.  This is  a  definite  bug  (as


                                         - 65 -                              




            C User's Guide                                                   


                 opposed to a question of interpretation).
                 
             9.  The  constant  -2^-31  (smallest  32-bit negative number) is
                 mishandled in all bases ('gctoi' goofs on it).  For the time
                 being, instead  of  using  "0x80000000",  use  "(1<<31)"  or
                 "(~0x7FFFFFFF)".   These will give identical results because
                 the constant folder gives correct results.
                 
             10. The construct "p++->x" confuses the compiler and  causes  it
                 to complain about missing parentheses.  This is because "->"
                 is  of  higher  precedence  than  "++" and thus confuses the
                 recursive-descent parser.  You should write  the  expression
                 as "(p++)->x".
                 
             11. The new version of the code generator still has some bugs in
                 it.   If  it  produces  an object file which causes an error
                 from the loader, you may wish to compile  the  program  with
                 the  "-s"  option, to generate PMA in a ".s" file.  Then use
                 'pmac' to assemble it, and load the new binary.   This  will
                 usually work; it will simply take longer to compile.






































                                         - 66 -                              




            C User's Guide                                                   


                                  ___TTT___eee___ccc___hhh___nnn___iii___ccc___aaa___lll___ ___III___nnn___fff___ooo___rrr___mmm___aaa___ttt___iii___ooo___nnn




                                     IIImmmpppllleeemmmeeennntttaaatttiiiooonnn


                 The  C  compiler  accepts  C source code as input and in two
            "passes" produces 64V-mode relocatable  object  code  as  output.
            The  first  compilation  pass  is implemented by a Ratfor program
            known as the "front end," and the second pass by a Ratfor program
            known as the "back end."  The front end is the Subsystem  program
            'c1' and the back end is 'vcg'.

            
            
                     ________    _________    ___________
                     |      |    |       |    |         |
                     |      |    |       |    |         |--->- Entry Points
               C --->-|  LA  |--->-|  CMP  |--->-|  PARSE  |--->- Static Data
            Program  |      |    |       |    |         |--->- Function Bodies
                     |______|    |_______|    |_________|
                                                   A|
                                                   |
                                                   V|
                                               Mode Table
                                              Symbol Table
                                            Expression Table


                 TTThhheee  """FFFrrrooonnnttt  EEEnnnddd...""" LA is the lexical analyzer, or scan-
                 ner.  CMP is the C macro preprocessor.   PARSE  is  the
                 parser and intermediate code generator.


                 The  front  end  is  a classical recursive-descent compiler,
            employing a lexical  analyzer  (to  break  the  stream  of  input
            characters   into   tokens),  a  preprocessor  (to  handle  macro
            definitions and source file inclusion), and a parser (to  analyze
            the  program, diagnose syntactic and semantic errors, and produce
            an "intermediate form" output stream).
















                                         - 67 -                              




            C User's Guide                                                   


            
            
                              ______                             _______
                              |    |---------------------------->-|     |
               Entry Points ->-|    |                             |     |
                Static Data ->-| IN |   __________   __________   | OUT |->- PMA
            Function Bodies ->-|    |-->-|        |-->-|        |-->-|     |
                              |____|   |  CODE  |   |  OPT   ||_____|
                                       | tree->- |   |        |
                                       |  mach. |   | (mach. |
                                       |  inst. |   | inst.) |
                                       |________|   |________|


                 TTThhheee """BBBaaaccckkk EEEnnnddd...""" IN reads the intermediate code produced
                 by the front end.   CODE  attempts  to  "intelligently"
                 generate  machine instructions.  OPT performs some sim-
                 ple peephole optimizations to  remove  redundant  loads
                 and stores.  OUT converts the internal instruction form
                 to 64V-mode object code, or, optionally, to Prime Macro
                 Assembly Language.


                 The  back  end is a reusable general-purpose code generator.
            It accepts the linearized intermediate form tree produced by  the
            front  end,  rebuilds the tree internally, converts the tree to a
            linked list  of  machine  instruction  representations,  performs
            peephole  optimizations  on that list, and then produces 64V-mode
            object code, ready for link  editing  and  subsequent  execution.
            'Vcg'  has  an  option  for  producing symbolic assembly language
            instead  of  object  code.   The  assembly  language  that  'vcg'
            produces is suitable for processing by the Prime Macro Assembler,
            PMA.

                 For  those  of  you wishing to supply your own front-ends to
            the code generator, there is a _V_-_m_o_d_e _C_o_d_e _G_e_n_e_r_a_t_o_r _U_s_e_r_'_s _G_u_i_d_e
            (use the Subsystem command 'guide') and a Reference Manual  entry
            for 'vcg'.



                                       PPPeeerrrfffooorrrmmmaaannnccceee


                 The  C  compiler  requires  parts of 5 segments to run.  The
            previous version of the C compiler, which used to call  PMA,  ran
            almost  twice  as fast as Prime's Fortran 77 and Pascal compilers
            (700 lines per minute vs 400 lines/minute on a PRIME 550  running
            under  Primos  18.1).   Hand  inspection  and informal benchmarks
            indicate that the code produced is superior to that  produced  by
            Pascal,  PL/1  and Fortran 77; in particular, fewer base register
            loads are generated, and operations on packed data structures are
            performed without resorting to the  field  manipulation  instruc-
            tions.




                                         - 68 -                              




            C User's Guide                                                   


                 The   compile   time   requirements   for  each  phase  were
            approximately as follows:  'c1':  23%, 'vcg':  27%, 'pma':   50%.
            Roughly  half  of  'vcg's time was spent in the assembly-language
            output routines.

                 For the second release, 'vcg' has been  changed  to  produce
            64V-mode  object  modules  directly.   This substantially reduces
            compile time.  We have not measured the new version of  the  com-
            piler, but the compile time requirements for each phase are about
            equal.   The total compile time is now approximately half of what
            it was, since PMA is not involved in the process.















































                                         - 69 -                              




            C User's Guide                                                   


                               ___SSS___uuu___bbb___sss___yyy___sss___ttt___eee___mmm___ ___MMM___aaa___nnn___aaa___ggg___eee___rrr___sss___ ___SSS___eee___ccc___ttt___iii___ooo___nnn




                 The machine-readable  text  of  the  _U_s_e_r_'_s  _G_u_i_d_e  _f_o_r  _t_h_e
            _G_e_o_r_g_i_a _T_e_c_h _C _C_o_m_p_i_l_e_r is in the file "=doc=/fguide/cc" (already
            formatted)  and  in  the directory "=doc=/guide/cc" (unformatted)
            (assuming that you have already installed the C compiler  accord-
            ing to the directions below).



                                 IIInnnssstttaaallllllaaatttiiiooonnn PPPrrroooccceeeddduuurrreee


                 The  C  compiler and its support programs are intended to be
            part of the Subsystem.  Source, documentation and executable ver-
            sions "drop in" to appropriate Subsystem directories so that they
            are accessible as standard Subsystem tools.  This section  covers
            the procedures necessary for installation of the C compiler.



                           GGGeeeooorrrgggiiiaaa TTTeeeccchhh CCC IIInnnssstttaaallllllaaatttiiiooonnn PPPaaaccckkkaaagggeee


                 The  C  Installation  Package  as  sent  from  Georgia  Tech
            contains the following items:

                      1 Release Tape
                      1 Copy of the C User's Guide




                                  RRReeellleeeaaassseee TTTaaapppeee CCCooonnnttteeennntttsss


                 The C Release Tape contains all files and directories neces-
            sary for proper operation of the C compiler  under  the  Software
            Tools  Subsystem.   It  is  in  standard MAGSAV/MAGRST format and
            contains 5 "logical tapes."  Each logical tape contains a  number
            of files that "drop in" to Subsystem directories.


            LLLooogggiiicccaaalll TTTaaapppeee 111

                 The first logical tape contains executable files that are to
            be placed in "=bin=",

                      cc   ccl   compile   ucc   vcg   vcgdump

            'Cc' is the Subsystem C compiler, 'ccl' is a shell file that com-
            piles  and  loads  a C program, 'ucc' is a 'Unix-like' C compiler
            and 'vcg' is the V-mode code generator.  'Vcg' is used by  the  C


                                         - 70 -                              




            C User's Guide                                                   


            compiler  but can also be used separately by those users who have
            their own "front ends."  'Vcgdump' reads the  intermediate  files
            produced  by  'c1',  and  prints  a human-readable version of the
            intermediate form tree.  'Compile' is a general purpose  compiler
            interlude.


            LLLooogggiiicccaaalll TTTaaapppeee 222

                 The second logical tape contains libraries for "=lib=",

                      ciolib   c$main   nciolib   vcglib   vcg_main


                 "Ciolib"  contains  the executable version of the C run time
            library; "c$main" is a small startup program that must be  loaded
            with every C main program.  "Nciolib" is the version of the C run
            time library for programs which are to run under bare Primos.

                 'Vcglib'  is a library of regular and shortcall routines for
            range testing and other purposes.  'Vcg' generates calls to these
            routines  for  their  operations,  instead  of  generating  code.
            'Vcg_main'  is  a small general purpose start off routine.  These
            are not used by C programs, but are  necessary  if  you  wish  to
            provide your own "front end" for 'vcg'.


            LLLooogggiiicccaaalll TTTaaapppeee 333

                 The third logical tape contains files for "=extra=",

                      bin/(c1   cc   cck1   cck2   compile   ucc)
                      
                      incl/(swt_def.c.i    ascii.h    assert.h    ctype.h
                            debug.h        lib_def.h  keys.h      math.h
                            memory.h       setjmp.h   stdio.h     swt.h
                            swt_com.h      varargs.h)
                      
                      incl/(vcg_defs.h   vcg_defs.p.i   vcg_defs.r.i)

            'C1' is the "front end" for the C compiler and is called by 'cc',
            'ccl', and 'ucc'.  'Compile' is a general purpose compiler inter-
            lude.   'Ucc' calls it.  'Cck1' and 'cck2' are the "trouble spot-
            ters" for C  programs.   They  will  flag  potentially  dangerous
            constructs  in a C program and are invoked by compiling a program
            with "ucc -y".  Subsystem definitions  for  the  C  compiler  are
            contained  in  "swt_def.c.i".   The  ?*.h  files are other header
            files, discussed  above  in  the  chapter  on  the  compile  time
            environment.

                 The  vcg_defs.?*  files contain constant definitions for use
            in writing "front ends" for 'vcg'.






                                         - 71 -                              




            C User's Guide                                                   


            LLLooogggiiicccaaalll TTTaaapppeee 444

                 The fourth logical tape contains documentation for "=doc=",

                      man/s1/(cc.d    ccl.d       ucc.d
                              vcg.d   vcgdump.d   compile.d)
                      
                      man/s5/(c1.d   cck1.d   cck2.d)
                      
                      fman/s1/(cc.d    ccl.d       ucc.d
                               vcg.d   vcgdump.d   compile.d)
                      
                      fman/s5/(c1.d   cck1.d   cck2.d)
                      
                      guide/(cc vcg)
                      
                      fguide/(cc vcg)



            LLLooogggiiicccaaalll TTTaaapppeee 555

                 The fifth logical tape contains source files for "=src=",

                      std.sh/(cc.sh   ccl.sh   ucc.sh   compile.sh)
                      
                      ext.c   # new directory with source files for C interludes
                      
                      ext.r/(cck1.r   cck2.r   cck2_com.r.i   cck2_def.r.i)
                      
                      lib/(cio   c$main    nc$main   vcg    vcg_main)
                      
                      spc/(c1.u   vcg.u)
                      
                      std.r/(vcgdump.r   vcgdump_com.r.i)

            If you do not have a source license then you will not recieve any
            of the source files.  In fact, the "src" directory will not be on
            the tape.



                                    LLLoooaaadddiiinnnggg ttthhheee TTTaaapppeee


                 To load the release tape, follow the instructions below:

            1.   Assign a tape drive:

                      AAASSSSSSIIIGGGNNN MMMTTT000

            2.   Mount the release tape on the assigned drive.

            3.   Attach to directory "=bin=":

                      AAATTTTTTAAACCCHHH BBBIIINNN <<<ooowwwnnneeerrr---pppaaasssssswwwooorrrddd>>>


                                         - 72 -                              




            C User's Guide                                                   


                 or if the tape is being restored to an ACL or  priority  ACL
                 protected partition, type

                      AAATTTTTTAAACCCHHH BBBIIINNN

            4.   Load the contents of the first logical tape with MAGRST:

                      MMMAAAGGGRRRSSSTTT
                      Tape Unit (9 Trk): 000
                      Enter logical tape number: 111
                      <tape label information>
                      Ready to Restore: yyyeeesss

                 (This  loads the files "cc", "ccl", "ucc", "compile", "vcg",
                 and "vcgdump".)

            5.   Attach to directory "=lib=":

            6.   Load the contents of the next logical tape (i.e., reply  "0"
                 to  the  "Enter  logical tape number:"  prompt) with MAGRST.
                 (This loads the library files for 'cc' and 'vcg'.)

            7.   Attach to directory "=extra=":

            8.   Load the contents of the  next  logical  tape  with  MAGRST.
                 (This  loads  the  support  programs for the compiler inter-
                 faces.)

            9.   Attach to directory "=doc=":

            10.  Load the contents of the  next  logical  tape  with  MAGRST.
                 (This  loads  the formatted and unformatted 'vcg' and C com-
                 piler guides, and the formatted  and  unformatted  Reference
                 Manual (help) entries.)

            11.  Attach to directory "=src=":

            12.  Load  the  contents  of  the  next logical tape with MAGRST.
                 (This loads the source code for the C compiler, the run_time
                 library, the compiler interfaces, the V-mode code generator,
                 and the vcg support routines.)  If you do not have a  source
                 license, and/or you have received a demonstration tape, this
                 logical tape will not be present.

                 This completes the loading of the C compiler from tape.



                                      IIInnnssstttaaallllllaaatttiiiooonnn


                 Once  you  have  loaded the tape, the C compiler is ready to
            use.  However, for the C  compiler  programs  to  appear  in  the
            "help"  index,  you  must  rebuild it by executing 'man_index' in
            "=doc=/build".



                                         - 73 -                              




            C User's Guide                                                   


                 Finally, for the 'locate'  and  'source'  commands  to  work
            correctly,  you  have  to rebuild the =srcloc= file.  To do this,
            'cd' to "=src=/misc", and execute the file  "make_srcloc".   This
            completes  the integration of the C compiler with the rest of the
            Subsystem.





















































                                         - 74 -                              




            


                                    ___TTT___AAA___BBB___LLL___EEE___ ___OOO___FFF___ ___CCC___OOO___NNN___TTT___EEE___NNN___TTT___SSS




                                     ___GGG___eee___ttt___ttt___iii___nnn___ggg___ ___SSS___ttt___aaa___rrr___ttt___eee___ddd



            PPPrrreeerrreeeqqquuuiiisssiiittteeesss ............................................   1

            CCCaaalllllliiinnnggg ttthhheee CCC CCCooommmpppiiillleeerrr ...................................   1
               Cc --- compile a C program ............................   1
               Ccl --- compile and load a C program ..................   2
               Ucc --- compile and load a C program ..................   2
               Compile --- general purpose compile and load ..........   2

            CCC PPPrrrooogggrrraaammm DDDeeevvveeelllooopppmmmeeennnttt --------- AAAnnn EEExxxaaammmpppllleee .....................   2




                               ___FFF___eee___aaa___ttt___uuu___rrr___eee___sss___ ___ooo___fff___ ___GGG___eee___ooo___rrr___ggg___iii___aaa___ ___TTT___eee___ccc___hhh___ ___CCC



            SSStttaaannndddaaarrrddd IIImmmpppllleeemmmeeennnttteeeddd .....................................   4

            AAAddddddiiitttiiiooonnnaaalll FFFeeeaaatttuuurrreeesss ......................................   4




                                 ___CCC___ooo___mmm___ppp___iii___lll___eee___ ___TTT___iii___mmm___eee___ ___FFF___aaa___ccc___iii___lll___iii___ttt___iii___eee___sss



            IIInnncccllluuudddeee FFFiiillleee OOOrrrgggaaannniiizzzaaatttiiiooonnn ................................   6
               =incl=/swt_def.c.i ....................................   6
               =incl=/stdio.h ........................................   7
               =incl=/ctype.h ........................................   8
               =incl=/swt.h ..........................................   8
               =incl=/ascii.h ........................................   9
               =incl=/assert.h .......................................   9
               =incl=/debug.h ........................................   9
               =incl=/keys.h .........................................  10
               =incl=/lib_def.h ......................................  10
               =incl=/math.h .........................................  10
               =incl=/memory.h .......................................  10
               =incl=/setjmp.h .......................................  10
               =incl=/swt_com.h ......................................  10
               =incl=/varargs.h ......................................  11






                                         - iii -                             




            


            LLLoooaaadddiiinnnggg CCC PPPrrrooogggrrraaammmsss FFFooorrr BBBaaarrreee PPPrrriiimmmooosss .......................  11




                                  ___RRR___uuu___nnn___ ___TTT___iii___mmm___eee___ ___EEE___nnn___vvv___iii___rrr___ooo___nnn___mmm___eee___nnn___ttt



            CCCaaalllllliiinnnggg PPPrrriiimmmooosss aaannnddd SSSuuubbbsssyyysssttteeemmm RRRooouuutttiiinnneeesss ....................  13

            TTThhheee MMMaaaiiinnn PPPrrrooogggrrraaammm .........................................  13

            CCC RRRuuunnn TTTiiimmmeee LLLiiibbbrrraaarrryyy .......................................  14
               UNIX System Calls .....................................  15
               The C Standard I/O Library ............................  18
               Unix Subroutines For C Programs .......................  34
               The C Math Library ....................................  50
               Unix Special Library Routines .........................  55
               Other Routines Not From Unix ..........................  56




                                       ___CCC___ooo___nnn___vvv___eee___rrr___sss___iii___ooo___nnn



            CCC PPPrrrooogggrrraaammm CCChhheeeccckkkeeerrr ........................................  59

            IIInnncccooommmpppaaatttaaabbbiiillliiitttiiieeesss WWWiiittthhh PPPDDDPPP---111111 CCC ..........................  59
               Include Statements ....................................  59
               Pointers ..............................................  60
               Program and Data Object Size Restrictions .............  60
               Functions .............................................  61
               Arrays ................................................  62
               Identifiers --- Naming Restrictions ...................  62
               Character Representation and Conversion ...............  62
               Numerical .............................................  62
               Library Incompatibilities .............................  63
               Unix File System Incompatibilities ....................  63
               Tabs ..................................................  63
               Static Initializers ...................................  63
               Registers .............................................  63
               The Type void .........................................  64













                                         - iv -                              




            


                                          ___BBB___uuu___ggg___sss



            KKKnnnooowwwnnn BBBuuugggsss ...............................................  65




                                  ___TTT___eee___ccc___hhh___nnn___iii___ccc___aaa___lll___ ___III___nnn___fff___ooo___rrr___mmm___aaa___ttt___iii___ooo___nnn



            IIImmmpppllleeemmmeeennntttaaatttiiiooonnn ...........................................  67

            PPPeeerrrfffooorrrmmmaaannnccceee ..............................................  68




                               ___SSS___uuu___bbb___sss___yyy___sss___ttt___eee___mmm___ ___MMM___aaa___nnn___aaa___ggg___eee___rrr___sss___ ___SSS___eee___ccc___ttt___iii___ooo___nnn



            IIInnnssstttaaallllllaaatttiiiooonnn PPPrrroooccceeeddduuurrreee ...................................  70

            GGGeeeooorrrgggiiiaaa TTTeeeccchhh CCC IIInnnssstttaaallllllaaatttiiiooonnn PPPaaaccckkkaaagggeee ......................  70

            RRReeellleeeaaassseee TTTaaapppeee CCCooonnnttteeennntttsss ....................................  70
               Logical Tape 1 ........................................  70
               Logical Tape 2 ........................................  71
               Logical Tape 3 ........................................  71
               Logical Tape 4 ........................................  72
               Logical Tape 5 ........................................  72

            LLLoooaaadddiiinnnggg ttthhheee TTTaaapppeee .........................................  72

            IIInnnssstttaaallllllaaatttiiiooonnn .............................................  73




















                                          - v -                              




            




























































            


