Waterloo C Compiler and Library on MUSIC/SP

   This document is (c) Copyright by Dave Edwards, 2005

Table of Contents

 
1. Overview
2. Conditions of Use
3. Usage and control statements; compiler options
4. Waterloo C library functions and #include header files (CHELP)
5. A small sample program: $wcc:watc.test
6. Execution using a load module (/inc xmwatc)
7. Library functions specific to the MUSIC/SP operating system
8. Run-time stack size
9. Features not supported under MUSIC/SP; compatibility issues
10. MUSIC/SP file access using fopen()
11. Command-line arguments
12. Calling assembler or Fortran routines from WatC
13. Calling WatC functions from assembler or Fortran
14. WatC function linkage conventions
15. Waterloo C sockets for TCP/IP
 
     This file last updated Nov 22, 2005


WatC: Overview

 
MUSIC/SP supports the Waterloo C compiler and library,
version 3.2 for MVS, provided by the University of Waterloo.
 
Waterloo C is (c) Copyright 1989 by the University of Waterloo.
 
Please see the Conditions of Use (section 2 in "help watc" or
help topic CONDITIONS).
 
Waterloo C conforms, as far as practical in the MVS environment,
to the ANSI C standard of December 1988.  It translates C language
programs into IBM System/370 object or assembler files, which can
then be linked with the Waterloo C library functions and executed.
Not all features and functions of the full Waterloo C product are
supported on MUSIC/SP, but all of the language and many of the basic
run-time library functions (including printf(), fopen(), etc.) work
as documented.  For a useful summary of the ANSI C extensions to
the original (Kernighan and Ritchie) C language, see:
ansi_c_summry.htm on the Sim390 web page.
 
Reference manuals, published by WATCOM Products Inc., 415 Phillip
Street, Waterloo, Ontario, Canada N2L 3X2 :
 
   "Waterloo C Development System Version 3.2 for OS, MVS and MVS/XA,
   User's Guide" by M.J.Carmody et al. Feb 1, 1989.
 
   "Waterloo C Development System Version 3.2 for OS, MVS and MVS/XA,
   Run-time Library Reference" by M.J.Carmody, D.W.Mulholland.
   Feb 1, 1989.


WatC: Conditions of Use

 
This software, including the Sim390 mainframe emulator, the MUSIC/SP
Demo system, and third-party software provided with the MUSIC/SP
Demo system, is provided on an "as-is" basis, and is intended only
for demonstration and evaluation purposes. Use it at your own risk.
The author is not responsible for any damages or losses that may
occur from your use of this software, and no support or warranty is
provided. This software must not be used, sold, or distributed for
profit, without the written permission of the author. It is
provided only for personal use by individuals. Use in a production
or commercial or institutional environment is prohibited.
 
Sim390 is (c) Copyright by Dave Edwards, 2001-2005.
 
The MUSIC/SP operating system is (c) Copyright by McGill University,
1989-2000.
 
The Waterloo C compiler and library is (c) Copyright by the
University of Waterloo, 1989. The Waterloo C compiler and library
distributed with the MUSIC/SP Demo system is provided without
support, warranty, or source code. It is to be run only on the
MUSIC/SP Demo system running under Sim390, Hercules, or a similar
mainframe emulator. It must not be repackaged or redistributed for
use under any other system.


WatC: Usage and Control Statements, Compiler Options

 
The Waterloo C compiler is invoked by the /inc watc control
statement, which may be preceded by /FILE statements (ddname
definitions for the COMP compile step and the GO execution step),
and may be followed by /JOB statements (MUSIC/SP, MVS simulation,
and Loader options), /OPT statements (compiler options), and the
C source to be compiled.  The compiler reads the C source from
ddname SYSIN and writes object files to ddname OBJ1.  Errors and other
messages are written to ddname STDOUT (also to ddname SYSLIST).
Header (#include) files are read from the MUSIC/SP PDS defined by
ddname SYSLIB, which by default is /FILE SYSLIB PDS($WCC:CLIB.*.H,*.H).
The input stream (SYSIN) can also contain object files, which are
copied to ddname OBJ1 and loaded for execution along with the
compiler object output.  Predefined ddnames for the GO step are
STDIN, STDOUT, STDERR.
 
In order to better synchronize source line numbers in error messages
with the actual source file, you can point to a source file xxx by
using the /include xxx control statement.  A /OPT or /JOB or
/DATA record signals end-of-file to the compiler, which ends one
compile and starts another (if more source follows); however /DATA
indicates end of all source and the start of SYSIN data records for
the GO (execution) step.  An object record also signals end-of-file
to the compiler.
 
If the compiler option ASM or ASMSRC is used, assembler output is
written to ddname ASM1.  If the compiler option PPC is used, C
preprocessor output is written to ddname SYSPRINT.
 
If the NOGO option is not used on /JOB, the MUSIC/SP Loader is
invoked after the compiles, to load the object files into memory,
include required modules from the run-time library, and finally
begin execution in MVS simulation mode.  The MAP option on /JOB can
be used to display a memory map of modules (CSECTs) and entry points.
As for other MUSIC/SP processors such as /LOAD ASM, various tracing
and debugging options (SVCTRACE, IOTRACE, CDUMP) can be used on /JOB.
Case (upper/lower) is not significant on /JOB and /OPT.
 
Example 1:
 
This example shows compile, load, and execution of a small C source:
 
    /inc watc
    #include <stdio.h>
    static void mysub(void);   /* prototype for a local function */
    int main(void)
    {
    printf("main starting\n");
    mysub();
    printf("main ending\n");
    return 0;
    }
    static void mysub(void)
    {
    printf("Now in mysub\n");
    }
 
Example 2:
 
This example shows compile of two source files, without execution.
The object files are written to a new file myprog.obj.
If the /OPT statement between the 2 source files is omitted, then
only one compilation occurs; otherwise the compiler is invoked twice.
 
    /file obj1 n(myprog.obj) new(repl) space(100)
    /inc watc
    /job nogo
    /inc myprog.c
    /opt
    /inc mysubs.c
 
  File myprog.c :
 
    #include <stdio.h>
    void mysub(void);   /* prototype for an external function */
    int main(void)
    {
    printf("main starting\n");
    mysub();
    printf("main ending\n");
    return 0;
    }
 
  File mysubs.c :
 
    #include <stdio.h>
    void mysub(void)
    {
    printf("Now in mysub\n");
    }
 
  The program can be executed by:
 
    /inc watc
    /inc myprog.obj
 
Compiler Options
 
Compiler options are specified on the /OPT statement, separated
from each other by 1 or more blanks.  Case is not significant.
More than 1 /OPT can be used if all the options do not fit on one;
options on multiple /OPT's are cumulative.  In most cases, no
compiler options are needed.  Commonly used options are ASMSRC,
PPC, STACKCHK.
 
ALIGN          Enables address alignment of integer and float type
               values.  For example, short int values are aligned
               on a halfword (2-byte) boundary; int and float are
               aligned on a fullword (4-byte) boundary; double values
               are aligned on a doubleword (8-byte) boundary.
               If ALIGN is not used, only function parameters are
               aligned.
 
ASCIIOUT       Converts all string and character constants to
               equivalent ASCII values in generated code.
 
ASM            Writes assembler code to ddname ASM1.
 
ASMSRC         Same as ASM, except the C source line numbers appear
               as comments in the assembler output.
 
COL n          Input from the source file (SYSIN) and from #include
               files that are delimited by double quote ("), are
               processed starting in the specified column number n
               of each line.  Columns 1 thru n-1 are ignored.
               See also TRUNC.
 
CSECT name     Sets the name of the Control Section (CSECT) in the
               object output to @name.
 
NOTEXT         Supresses the generation of object output.
 
NOZERO         Suppresses the initialization of otherwise
               unititialized static variables to zero values.
 
OPT
NOOPT          NOOPT suppressed compiler code optimization.
               The default is OPT.
 
OS             Generates code which uses an OS (MVS) style register
               linkage convention with a reserved run-time stack
               pointer register.  (The default linkage convention
               is C-style linkage, which uses nonstandard registers.)
 
OSENTRY        Generates code which uses an OS (MVS) style register
               linkage convention with no run-time stack.
 
OSFUNC         Generates code which uses an OS (MVS) style register
               linkage convention where a special call is generated
               during the function prologue to obtain a stack pointer.
 
PPC            Writes preprocessor output (without compiling it)
               to ddname SYSPRINT.
 
PRM id token   Simulates the addition of the C preprocessor
               directive at the top of the source file:
 
                    #define id token
 
               Both the id and token must be specified.  To define
               more than one identifier, use the option once for each.
               Example:  /opt prm ABC 12 prm DEF 34
               NOTE: The /OPT statement is converted to upper case
               before processing, therefore identifiers defined this
               way should be upper case and not contain lower-case
               characters in their token values (this is a MUSIC/SP
               restriction).
 
STACKCHK       Generates code which checks for run-time stack overflow
               at the start of each function.
 
TRUNC n        Characters after the specified column number n, in
               the source file (SYSIN) and #include files delimited
               by double quote ("), are ignored.  This is useful
               for skipping sequence number fields. See also COL.
 
WNG
NOWNG          Controls output of warning messages. There are two
               classes of warning messages: conditional and
               unconditional.  WNG causes both type to be put out.
               NOWNG suppresses both types.  If neither option is
               used, conditional warnings are suppressed and
               unconditional warnings are put out.


WatC: Library Functions and Header Files

 
For information about the Waterloo C library functions and #include
header files, type the command CHELP on a MUSIC/SP system.


WatC: A Small Sample Program

 
File $wcc:watc.test contains a simple test program which displays
a 1-line message:
 
/com ** Waterloo C simple test program.  26mar2005.
/com ** This test prog uses the new setup: invoked by /INC WATC,
/com ** with user Load Library.  WatC version 3.2.
/inc watc
#include <stdio.h>
int main(void)
{
printf("Hello from Waterloo C!\n");
return 0;
}


WatC: Execution Using a Load Module

 
A Waterloo C program can be executed as a load module, which
gives considerably faster start-up, since the run-time library
functions are pre-linked into the load module and therefore the
subroutine library does not need to be searched.
 
The load module is executed using /inc xmwatc instead of the
normal /load xmon control statement.
 
 
Instructions:
 
  - Compile the C source modules, producing object files.
    Use /JOB NOGO and a /FILE statement for ddname OBJ1, specifying
    the file to which the object file is to be written.
    A single source file may be used, or multiple separate source
    files, depending on the design of the program.
 
  - Include the object files in a Linkage Editor (/LOAD LKED) job,
    which creates the load module file.  Use the normal Linkage
    Editor control statements, except add the MODE=OS option
    on the /JOB statement, and supply the following /FILE statement
    before /LOAD LKED:
 
      /file sublibos pds(*cw,*mus,*os)
 
  - Execute the resulting load module using a file as follows:
 
      /sys region=nnnn
      /inc xmwatc
      myprog n(myprog.lmod) lcparm
 
    where nnnn is the job region (memory) size in Kbytes, myprog is
    the name of the load module member, and myprog.lmod is the
    name of the load module file.  The LCPARM option causes the
    original-case parameter string to be used (i.e. not converted
    to upper case).  Other options, such as tracing and debug options,
    can also be used, as for /LOAD XMON.
 
Example:
 
  This example uses 2 source files.
 
  Source file 1:
 
    /file obj1 n(testprog.obj) new(repl)
    /inc watc
    /job nogo
    #include <stdio.h>
    void myfunc1(int value);   /* prototype for external function */
    static void myfunc2(void);  /* prototype for local function */
    int main(void)
    {
    printf("Starting main\n");
    myfunc1(100);
    myfunc2();
    printf("Ending main\n");
    return 0;
    }
    static void myfunc2(void)
    {
    printf("Now in myfunc2\n");
    }
 
  Source file 2:
 
    /file obj1 n(testfunc1.obj) new(repl)
    /inc watc
    /job nogo
    #include <stdio.h>
    void myfunc1(int value)
    {
    printf("Now in myfunc1, value = %d\n",value);
    }
 
  Execute each of the above source files.
 
  Next, run the following Linkage Editor job to create the load module:
 
    /file lmod n(testprog.lmod) new(repl) space(100) lr(128) recfm(f)
    /file sublibos pds(*cw,*mus,*os)
    /load lked
    /job map,nogo,print,stats,mode=os,name=testprog
    /inc testprog.obj
    /inc testfunc1.obj
 
  The executor file to run the program is as follows:
 
    /inc xmwatc
    testprog n(testprog.lmod) lcparm


WatC: Library Functions Specific to MUSIC/SP

 
The following WatC run-time library functions are specific to
the MUSIC/SP operating system. They are not part of the standard
Waterloo C.
 
  mufilinf  Gets info about a MUSIC/SP file
  mufilnew  Creates a new MUSIC/SP file
 
The following #include header files are specific to MUSIC/SP:
 
  HMUSRTNS  <musrtns.h>
 
Character set translation functions: musa2e and muse2a have
the same calling sequence as WatC library functions atoe and etoa,
respectively, but they use slightly different Ascii - EBCDIC
translation tables. The tables used are 1-to-1 among all 256
possible character codes, and therfore each call can be undone
by the opposite function.  The prototypes for musa2e and muse2a
are in header files <musrtns.h> and <socket.h>.
 
See also the TCP/IP socket functions described in file
$tcp:sockets.doc .


WatC: Run-time Stack Size

 
The size of the Waterloo C run-time stack is 10K bytes by default.
All auto variables, parameters and the register save areas for a C
program are allocated from this stack (memory area).  A C program
can determine how much unused stack space is available by calling
the stakleft library function.  Type chelp stakleft for a
description.
 
By default, there is no checking at run time for overflowing the
stack.  Symptoms of stack overflow include program abort due to an
addressing or protection Program Interrupt, incorrect results, and
erratic or unpredictable program behaviour.  The compiler option
STACKCHK (requested by the /opt stackchk control statement) can
be used to cause stack overflow checking code to be generated at
the start of each function.  This may slightly reduce program speed.
 
Depending on your program, you may need to define a larger stack.
There are two ways to do this:
 
(1) Change the initialized value of external variable _staksize
    as shown in this example:
 
    /inc watc
    #include <stdio.h>
    #include <stdlib.h>   /* for stakleft() */
    const int _staksize=60*1024;  /* set stack size to 60K bytes */
    int main(void)
    {
    printf("Hello from WatC\n");
    printf("WatC stack size left = %u\n",stakleft());
    return 0;
    }
 
or
 
(2) Include the object file $wcc:watc.stak.50k.obj in your
    program.  This sets the stack size to 50K bytes.  Example:
 
    /inc watc
    #include <stdio.h>
    #include <stdlib.h>   /* for stakleft() */
    int main(void)
    {
    printf("Hello from WatC\n");
    printf("WatC stack size left = %u\n",stakleft());
    return 0;
    }
    /inc $wcc:watc.stak.50k.obj


WatC: Features Not Supported Under MUSIC/SP

 
Waterloo C features which are NOT supported under MUSIC/SP, or
which do not work correctly, or which may cause compatibility
problems, are listed below.  This is not a complete list, since
not all features have been tested yet.
 
If you have an addition to this list, please post a message to
the Yahoo discussion group H390-Music (free to join):
 
        http://groups.yahoo.com/group/H390-music
 
 
Features NOT supported:
 
- The Waterloo C Debugger (full-screen source-level debugger).
  The debug and tracing facilities of MUSIC/SP can be used instead.
 
- 3270 full-screen Panel Library (for the MVS/TSO environment).
  MUSIC/SP's Panel Facility can be used instead; MUSIC/SP Panel
  routines must be called indirectly via the fvscalli() library
  function.
 
- Waterloo C run-time library functions resident in the Link Pack
  Area (LPA).  If you need faster program start-up, use a load
  module, with /inc xmwatc.
 
- Waterloo C development tools: GREP, DIFF, TXTREF.
  Various MUSIC/SP commands and utilities (COMPARE, FINDTEXT)
  can be used instead.
 
- The CW, LINK, and CALL commands (MVS/TSO environment) are not
  available.  Instead, MUSIC/SP jobs (files) containing the
  equivalent control statements for compiling, linking, and
  executing a WatC program, should be used.  Refer to the
  appropriate sections in this help text.
 
- MVS PDS (Partitioned Data Set) support:
    - The syntax pdsdatasetname(membername), where the 1- to 8-char
      member name is specified in parentheses after the data set name,
      is partially supported in the fopen() library function, but
      not in the remove() and rename() functions.  MUSIC/SP does not
      have true PDS data sets; each member is a separate Save Library
      file in MUSIC/SP.  fopen() maps the xxx(yyy) syntax into a
      file name as follows:  If xxx contains the placeholder "__"
      (2 consecutive underscores), the placeholder is replaced by the
      member name. Otherwise xxx(yyy) maps to file name xxx.yyy.
      Examples:  MYPDS1.__.S(MYMEMB)  maps to  MYPDS1.MYMEMB.S
                 MYPDS2(MYMEMB)  maps to  MYPDS2.MYMEMB
    - PDS directory scanning, via functions opendir, closedir,
      readdir, and rewinddir, is not supported.
    - A "MUSIC/SP PDS" cannot be accessed via a /FILE statement,
      i.e. like /FILE ddname PDS(*.S), at run-time using fopen().
 
- #include preprocessor directives are handled slightly differently
  from other C compilers:
  #include <xxx.h> refers to member xxx in the MUSIC/SP PDS
  defined as ddname SYSLIB, and normally reads file $wcc:clib.xxx.h.
  #include "xxx.yyy" refers to member xxx in the MUSIC/SP PDS
  defined as ddname yyy.  For the common case where yyy is H, the
  file WATC contains the statement /FILE H PDS(*.H,$WCC:CLIB.*.H) DEF
  and therefore the file xxx.H is read from the user's library.
  In both cases, the member name xxx should not exceed 8 characters;
  if it does, only the first 8 characters are used.
 
- rewind() and fseek() do not work.  Instead of rewind, close the
  file then re-open it.  frseek(), frtell(), fgetpos(), fsetpos(),
  ftell(), rtell(), lseek(), rseek(), tell() have not been tested.
 
- fopen() update options "r+" and "w+" do not work, since they
  internally use fseek() or rewind().  For more details on MUSIC/SP's
  support of fopen() and file input/output, see the section on it
  in this help text.
 
- fstat() and stat() do not return complete info about the file.
  Structure members st_recfm and st_lrecl are set to 0.
  st_dsname is set to the ddname.  You can use mufilinf() to get
  accurate info about a MUSIC/SP file.
  Functions lrecl() and recfm() have not been tested.
 
- Environment variable support: getenv() always returns NULL.
  putenv() and setenv() always return -1 (error).
 
- clear() (clear the 3270 screen) does not work.  Instead, the
  special MUSIC/SP print control character x'70' can be used, as in:
      unsigned char clearch=0x70;
      printf("%c\n",clearch);
 
- system() does not work.  Instead, the MUSIC/SP routine NXTCMD
  can be called (indirectly via the fvscalli() library function).
 
- The time() function gives curent system local time, not GMT time.
  localtime() and gmtime() give the same result i.e. local time.
  This is because MUSIC/SP sets the System/390 machine TOD Clock
  to local time, not to GMT time as in a real MVS system, and the
  Time Zone Offset (CVTTZ) in the MUSIC/SP CVT (Communications
  Vector Table) is 0.
 
- Signal-processing functions, including signal(), ssignal(), kill(),
  alarm() etc., have not been tested and probably are not fully
  functional.
 
- longjmp() and setjmp() functions have not been tested.
 
- Dynamic memory allocation above the 16 megabyte line and 31-bit
  addressing are not supported. See functions setalloc(), setamode().
 
- In WatC, type char is unsigned by default.  This is different
  from some other C compilers (such as Microsoft Visual C++ 6.0 and
  Borland Turbo C 2.0).  To avoid portability issues, it is best
  to always specify unsigned char or signed char.
  In WatC, int, long int and pointers are 32 bits.
  short int is 16 bits. float is 32 bits (single-precision
  floating point). double is 64 bits (double-precision floating
  point).
 
- In MUSIC/SP, as in a real MVS system, external names in object
  modules are limited to 8 characters in length.  For this reason,
  WatC external names (global variables and non-local function names)
  are truncated to length 8 and are converted to upper case, and the
  resulting names must be unique.  Also, underscores ("_") in the C
  names are changed to $ in the object module.  For example,
  external name my_function becomes MY$FUNCT.  It is recommended
  that functions local to a C source file be declared as "static",
  so that their names do not appear in the object module.
  Choose external names that are unique after truncation to 8
  characters and conversion to upper case.
 
- There is a bug in the compiler that can occur when automatic
  (i.e. non-static) variables, especially arrays, are initialized
  in the declaration statement in a function.  The bug results in
  the wrong values being used for some constants.  To avoid this
  bug, you should declare such variables as static.  If initialization
  is needed at each function call, use execution-time statements to
  set the variables.  Example:
 
     Instead of:   char abc[5]={0,1,2,3,4};
     Use:          static char abc[5]={0,1,2,3,4);


WatC: MUSIC/SP File Access Using fopen()

 
In WatC, a file name string for the fopen() library function has
the following syntax:
 
        "ddname ( options"
 
    or  "dsname(member) ( options"
 
    or  "dsname ( options"
 
ddname is a 1- to 8-character DD name (defined on a /FILE statement).
member is a 1- to 8-character PDS (Partitioned Data Set) member name.
dsname is 1 1- to 44-character MUSIC/SP Save Library file name.
options are option specifications, separated from each other by blanks.
The opening ( and the options can be omitted.  Case (upper/lower) is
not significant in the file name string.
 
Once the file is successfully opened by fopen(), you can read or
write it by using library functions such as getc() and putc().
When you are finished, close it by calling fclose().
 
WatC first tries to match the name with a defined ddname.  If that
fails, it tries to use the name as a MUSIC/SP file name, via an
MVS Dynamic Allocation request (SVC 99).  The attempt to match with a
ddname can be suppressed by enclosing the dsname in single quotes (').
When single quotes are used with a member, include (member) within
the single quotes: for example 'mypds(member1)', not 'mypds'(member).
 
For an output file (fopen() with 2nd argument containing "w" or "a"),
SVC 99 tries to create a new file if the file does not already exist.
When creating a new file, SVC 99 Open uses record format FC, logical
record length 80, space 200K, secondary space allocation 300%.
If these attributes are not satisfactory, you should call library
function mufilnew() to create the new file before calling fopen().
 
When a member name is specified, the xxx(yyy) specification is
mapped by SVC 99 to a MUSIC/SP file name, which is then used as the
file for the member.  If xxx contains the placeholder "__" (2
consecutive underscores), the placeholder is replaced by the member
name.  Otherwise the file name used is xxx.yyy .
Examples:   mypds1.__.s(mymem)   maps to   mypds1.mymem.s
            mypds2(mymem)        maps to   mypds2.mymem
 
The options can be used to specify the input/output processing
parameters that WatC will use when reading or writing the file.
These options override the attributes of the MUSIC/SP file itself,
or the attributes specified on the /FILE statement (for a ddname).
However, the attributes of the actual file are not affected,
except in the case of a new file being created.  Options such as
RECFM and LRECL may need to be specified in the file name string, in
some cases, to cause WatC to use different i/o processing than would
otherwise be indicated by the attributes of the file itself.
Possible options are:
 
RECFM x      The MVS record format to be used.  x can be a
             combination of the following letters:
               F   Fixed-length logical records.
               V   Variable-length logical records.
               B   Blocked records. (This does not apply to MUSIC/SP,
                     since sequential i/o done by MUSIC/SP's MVS
                     simulation is normally unblocked.)
               M   Indicates presence of machine-type printer
                     control characters at the beginning of each
                     logical record.
               A   Indicates presence of ANSI-type printer
                     control characters at the beginning of each
                     logical record.
 
LRECL n      The MVS logical record length, or maximum record length
             in the case of variable-length records.  The length n
             does not include the RDW (Record Descriptor Word) bytes
             that are used for a variable-length record.
 
BLKSIZE n    The MVS block size.  This is normally ignored, since
             MUSIC/SP i/o in MVS simulation is normally unblocked.
 
BIN          The file is processed in binary mode.  This is the same
             as using character "b" in the 2nd argument of fopen().
             In binary mode, the newline character '\n' has no
             special significance during input/output.
 
TEXT         The file is processed in text mode.  The newline
             character '\n' signifies end of a logical record.
             When files are read in text mode, WatC supplies a
             newline character at the end of each record.
 
Examples:
 
    (1)   fopen("my.data.file","r");
 
    (2)   fopen("$000:dir1\\my.output.file ( recfm v lrecl 200","w");
 
             Note the use of double backslash (\\) to represent a
             single backslash in the file name.  This is required
             by the syntax rules of C strings.  The actual string
             in the object file only contains 1 backslash.
 
    (3)   /file outfile n(my.output) new(repl) space(500)
          ...
          fopen("outfile","wb");
 
    (4)   fopen("'notddn' ( recfm f","r");


WatC: Command-line Arguments

 
Support for command-line arguments, i.e. the parameter field of
the command that runs the WatC program, or of the /PARM control
statement, is as follows.
 
The parameter field is parsed (in various ways according to the
setting of the _parms global variable) and the resulting array
of strings is passed to the main() function as its arguments.
The global constant _parms has a default value of EXTEND_NOPARENS
which treats the parameter field as a sequence of words separated
by 1 or more blanks.  If _parms=C_STRINGS is used, a word in the
parameter field can contain blanks if the word is enclosed in
double quotes ("..."), in which case the double quotes are removed;
for C_STRINGS, backslash (\) is processed as an escape character,
as in C character constants; \\ gives \; \" gives ".
 
The first word (index [0] in the array of strings passed to
main()), which is the program name on some other systems, is
always a null string, and there is an extra null string as a
final word at the end of the array.
 
Example program:
 
      /parm testarg1 "test arg\\2" test\\arg\"3
      /inc watc
      #include <stdio.h>
      #include <setup.h>   /* defines the values for _parms */
      const int _parms=C_STRINGS;  /* default is EXTEND_NOPARENS */
      int main(int numarg, char *cmdarg[])
      {
      int i;
      printf("numarg=%d\n",numarg);
      for(i=0;i<=numarg;i++)
        { printf("arg%d=|%s|\n",i,cmdarg[i]);
        }
      return 0;
      }
 
   The output is:
 
      numarg=4
      arg0=||
      arg1=|testarg1|
      arg2=|test arg\2|
      arg3=|test\arg"3|
      arg4=||
 
   If the initialization line for _parms is omitted, or is changed to
   EXTEND_NOPARENS, the output is:
 
      numarg=5
      arg0=||
      arg1=|testarg1|
      arg2=|"test|
      arg3=|arg\\2"|
      arg4=|test\\arg\"3|
      arg5=||


WatC: Calling Assembler or Fortran Routines from WatC

 
It is possible to call an assembler or VS Fortran subroutine from a
WatC program, but it must be called indirectly via the fvscalli
library function (for a Fortran routine that returns an integer
value or no value), or the fvscallr function (for a Fortran
routine that returns a double floating-point value), or the oscall
function (for an assembler routine that uses the standard MVS
linkage conventions).  The indirect call is necessary because C
and MVS use different linkage conventions.
 
In the case of a VS Fortran routine which may require VS Fortran
run-time services (such as i/o or error handling), fvsinit must
be called once, before any fvscalli or fvscallr calls, to establish
the VS Fortran run-time environment.  fvsinit calls VSCOM# + 64.  If
fvsinit is called, the statement /FILE FT06F001 PRT must be used in
the job.
 
Refer to the descriptions of the library functions fvscalli, fvscallr,
fvsinit, and oscall.  Use the command: CHELP functionname
 
Example program:
 
This example shows calling the MUSIC/SP library routines TSUSER,
JD, and NXTCMD from a WatC program.  All of these routines are
actually assembler and do not use VS Fortran services, therefore
fvsinit does not need to be called.
 
/inc watc

#include <stdio.h>
#include <stdlib.h>   /* for fvscalli(), fvscallr(), fvsinit() */
#include <string.h>

void TSUSER(void); /* Fortran routine to be called.
               TSUSER does not actually return a value; when we
               call fvscalli(), we ignore the return value.
               TSUSER is actually assembler, and does not use any
               VS Fortran services, therefore fvsinit() is not
               needed. */
void JD(void); /* Fortran routine, returns Julian Date (a number of
               days) for the date (year,month,day).
               E.g. JD(2005,8,12) is 2453595.
               JD is actually assembler, and does not use any
               VS Fortran services, therefore fvsinit() is not
               needed. */
void NXTCMD(void); /* NXTCMD assembler routine is used to execute a
               MUSIC/SP command as a new task (multi-session).
               It does not need fvsinit(). */
       /* Note: The Fortran routines are declared void here, to
          avoid a compiler warning message for mismatched arg 1
          in calls to fvscalli. */

int main(void)
{
int n,year,mon,day,n1,n2;
unsigned char userid[17],cmd[100];

/* fvsinit(); */  /* Initialize the VS Fortran execution environment.
             It is required only if the Fortran routines being
             called do Fortran i/o, error handling, etc.
             If it is called, /FILE FT06F001 PRT must be provided. */

n1=1;  /* TSUSER(1,n2) sets n2 to the termtype (0=batch, 6=3270,
          etc.) */
fvscalli(TSUSER,2,&n1,&n2);
printf("From TSUSER: termtype=%d\n",n2);

n1=4;  /* TSUSER(4,n2) sets n2 to the TCB number. */
fvscalli(TSUSER,2,&n1,&n2);
printf("From TSUSER: TCBnum=%d\n",n2);

n1=8;  /* TSUSER(8,id) sets id to the userid (16 chars, blank
          padded, no null terminator). */
fvscalli(TSUSER,2,&n1,userid);  /* Note that we use userid (not
          &userid), since userid is already an address. */
userid[16]=0;  /* add the null terminator, to make a C string */
printf("From TSUSER: userid=|%s|\n",userid);

year=2005; mon=8; day=12;  /* JD(year,mon,day) returns Julian date */
               /* E.g. JD(2005,8,12) is 2453595 */
n=fvscalli(JD,3,&year,&mon,&day);
printf("JD(%d,%d,%d) is %d\n",year,mon,day,n);

strcpy(cmd,"SYSDATE");  /* MUSIC/SP command to be executed via
                           multi-session (i.e. a child task).
     Note: NXTCMD does not require cmd to have a null terminator. */
n1=strlen(cmd);  /* length of the command */
n2=128+32+64;  /* Flags: 128 = multi-session
                          32 = delete child task at child end of job
                          64 = parent task must wait for child to end
               */
printf("Calling multi-session NXTCMD, cmd=%s\n",cmd);
fvscalli(NXTCMD,3,cmd,&n1,&n2);  /* CALL NXTCMD(cmd,n1,n2) */
printf("Returned from NXTCMD\n");

return 0;
}
 
The output from the above program is similar to:
 
From TSUSER: termtype=6
From TSUSER: TCBnum=9
From TSUSER: userid=|$000000         |
JD(2005,8,12) is 2453595
Calling multi-session NXTCMD, cmd=SYSDATE
  THU OCT 06, 2005     2005/279     21:41:23.86   TIME ZONE: -0400 (EDT)
  MUSIC IPL'd at  9:55 yesterday  ( 5 Oct 2005)
  Nucleus level: ESA-FBA 03JAN04
  MUSIC level:  Version 6   Release  1   Service  0   0
  CPU ID: D1000001 5D710000
Info as from /VER command:
  This system is MUSIC/SP Version 6 Release 1 (MUSIC/ESA)
  Distribution: Demo A
  MUSIC/ESA running under Sim390 emulator on Windows
Returned from NXTCMD


WatC: Calling WatC Functions from Assembler or Fortran

 
A C function can be called from an assembler or VS Fortran program,
but the C run-time environment must first be initialized (by
calling CINIT), and an interface routine must be used, because
of the different linkage conventions used by WatC.  Interface
routine CCALL is used to call a C function that does not return
a value. ICFUNC is used to call a C Function that returns an
integer value. DCFUNC is used to call a C function that returns
REAL*8 value.  These interface routines pass the address of the
VS Fortran argument list to the C function.  The routine CEXIT
should be called when you are done calling C functions, to release
any resources obtained by the C environment; this call to CEXIT is
optional; you can omit it if it seems to cause problems such as a
Program Interrupt; see the note below.
 
CINIT and CEXIT are called without any arguments.  CINIT returns an
integer value, which indicates an error if it is nonzero.
 
CCALL, ICFUNC, and DCFUNC are called with the name of the C function
as the first argument, and with the arguments (0 or more) to be passed
to the C function as the remaining arguments.  The C function name
(which is the C name truncated to 8 characters, converted to upper
case, and _ changed to $) should be declared as EXTERNAL in the
Fortran program, by the Fortran statement:  EXTERNAL name
In order to follow VS Fortran Version 1 name length rules, the name
should not exceed 6 characters; in assembler and VS Fortran Version 2,
the name can be up to 8 characters.
 
The interface routine calls your C function with a single argument
of type void **arglist i.e. an array of pointers, which are the
addresses in the Fortran argument list for the call to the interface
routine.  arglist[0] is the address of your C function (you do not
use this value).  arglist[1] is the addr of the first arg for your
C function.  arglist[2] is the addr of the 2nd arg (if any), etc.
Your C function must obtain the actual arguments from that array of
pointers.  In the case of ICFUNC, your C function returns an integer
value.  In the case of DCFUNC, your C function returns a double
value.
 
NOTE: When mixing MUSIC/SP (Fortran) and WatC library routines,
      name conflicts can occur.  A conflict is a routine name that
      occurs in more than one subroutine library, for example in
      both the WatC (*CW) and MUSIC/SP (*MUS) libraries.
      Known conflicts are the CLOSE and WRITE names, which occur
      in WatC and in MUSIC/SP's TCP/IP socket library routines
      ($tcp:sockets.obj, CSECT name TCPIUCV).  CLOSE is called by
      CEXIT.  If CEXIT calls the wrong copy of CLOSE, a Program
      Interrupt (PI) occurs and the job aborts.  For this reason,
      you should define the WatC library (*CW) ahead of *MUS in
      the /FILE SUBLIB statement.  See the example below.
      If your Fortran program needs to use the socket routines of
      MUSIC/SP, you would have to reverse the order (define *MUS
      ahead of *CW) and omit the call to CEXIT; but problems
      could still occur.  Be careful.  Check the loader map by
      using /JOB MAP.  There is no problem if you use only the WatC
      socket routines in file $tcp:watc.sockets.obj, which you
      add to your program via a /include statement.
 
Example:
 
In this example, a Fortran program calls C functions add2(), getmax(),
and dprod().  add2 takes 3 integer*4 args, sets the 3rd arg to the
sum of the first 2, and does not return a value.  getmax takes 2
integer*4 args and returns their maximum.  dprod takes 2 real*8 args
and returns their product.
 
Here is the Fortran program:
 
/file sublib pds(*cw,*mus,*os)
/file stdout prt
/file stderr prt
/load vsfort
      EXTERNAL ADD2,GETMAX,DPROD
      INTEGER ICFUNC,CINIT
      REAL*8 DCFUNC,D1
      IF(CINIT().NE.0) THEN
         WRITE(6,*) '** ERROR: UNABLE TO INITIALIZE C'
         STOP 1
      ENDIF
      CALL CCALL(ADD2,3,5,N1)
      WRITE(6,*) 'N1 from ADD2 is ',N1
      N1=ICFUNC(GETMAX,30,20)
      WRITE(6,*) 'N1 from GETMAX is ',N1
      D1=DCFUNC(DPROD,1.5D0,2.5D0)
      WRITE(6,*) 'D1 from DPROD is ',D1
      CALL CEXIT
      WRITE(6,*) 'Fortran program ending'
      STOP
      END
/inc calltest.obj   - object file for the c functions, created below
 
Here is the job to compile the C functions:
 
/file obj1 n(calltest.obj) new(repl)
/inc watc
/job nogo
void add2(int **arglist)
{
*(arglist[3]) = *(arglist[1]) + *(arglist[2]);
}
int getmax(int **arglist)
{
int arg1,arg2;
arg1=*(arglist[1]);
arg2=*(arglist[2]);
if(arg1>=arg2) return arg1;
          else return arg2;
}
double dprod(void **arglist)
{
double arg1,arg2;
arg1=*((double*)(arglist[1]));
arg2=*((double*)(arglist[2]));
return arg1*arg2;
}
 
Here is the output of the Fortran program:
 
N1 from ADD2 is           8
N1 from GETMAX is          30
D1 from DPROD is   3.75000000000000000
Fortran program ending


WatC: Function Linkage Conventions

 
By default, Waterloo C generated code uses a nonstandard linkage
convention for calling functions.  It is referred to as the
"C linkage" convention, to distinguish it from the "standard"
linkage convention used by most MUSIC/SP and MVS routines such as
those written in VS Fortran, assembler, Cobol, and other languages.
 
C linkage is different in the machine registers it uses, and
because it uses a memory stack rather than program-allocated
areas such as the 18-word save area used by standard linkage.
The two standards are not compatible.  If a WatC program calls
a VS Fortran routine directly, for example, a Program Interrupt
(PI) usually occurs and the program aborts.
 
Register usage for the C linkage convention:
 
R10 (ZP)   Address of the WatC global area.  The called routine
           must not change this register (or, if it changes it
           temporarily, it must restore it before returning).
 
R11 (LN)   Address of the entry point of the called routine.
           The called routine can use it as a base register for
           its code (provided it does not call any C functions).
           If the called routine's return value is an integer
           or a pointer (address), it is placed in R11 on return;
           otherwise R11 does not have to be restored on return
           to the calling routine.  If the return value is not an
           integer or pointer (e.g. it is a double floating-point
           or a structure), it is stored on the stack, at the
           address that was in R12 on entry, overlaying the
           arguments.
 
R12 (SP)   The stack pointer.  The arguments passed to the
           called routine are at this address.  The called routine
           is assumed to know the type and number of arguments
           passed to it.  Memory in the stack AFTER the arguments
           can be used as a work area by the called routine.
           This register can be used as a base for the routine's
           data areas.  Before returning, the routine must restore
           this register to its original value.
 
R13 (RA)   The return address to the calling routine.  This register
           must be restored before returning.
 
R14 thru R9  These registers are not input to the called routine.
           They must be restored before returning.
 
FPR0 thru FPR6  These 4 floating-point registers must be restored
           before returning, if the called routine (or any routine
           it calls) changes them.
 
Example called routine in assembler:
 
The following assembler routine CTEST is coded using C linkage
and can be called directly from a WatC program.  It returns an
integer value which is the sum of its 2 integer arguments.
The equivalent function in C is:
 
         int ctest(int arg1, int arg2)
         {
         return arg1+arg2;
         }
 
This example CTEST routine sets up a work area (as a DSECT) and
a standard save area, which would be used if CTEST needed to
call other standard-linkage routines.  CTEST is re-entrant (does
not modify itself during execution) and the assembler option RENT
(/OPT RENT) can be used when assembling it.
 
/file syspunch n(ctest.obj) new(repl)
/load asm
/job nogo
/opt deck,rent
CTEST    CSECT
         REGS
* DSECT FOR WORK AREA ALLOCATED ON THE C RUN-TIME STACK.
* R12 (FROM THE CALLER) IS THE ADDRESS OF THIS AREA.
STKWORK  DSECT
ARG1     DS    F                  ARGUMENT 1
ARG2     DS    F                  ARGUMENT 2
SAVREGS  DS    15F                CALLER'S REGS R12 THRU R10
SVAREA   DS    18F                SAVE AREA PASSED TO CALLED ROUTINES
*... OTHER WORK AREAS WOULD BE DEFINED HERE
WORKEND  EQU   *                  END OF THE WORK AREA
         SPACE 2
CTEST    CSECT
* ENTRY POINT:
         USING *,R11              BASE REGISTER FOR CODE
         USING STKWORK,R12        BASE REGISTER FOR WORK AREA
         STM   R12,R10,SAVREGS    SAVE CALLER'S REGS
         LA    R13,SVAREA         STANDARD SAVE AREA FOR ROUTINES
*                                 WE CALL
         L     R3,ARG1            DO THE WORK: ARG1+ARG2
         A     R3,ARG2
*... ANY OTHER WORK WOULD BE DONE HERE.
* RETURN LINKAGE: AT THIS POINT, R3 CONTAINS THE RETURN VALUE
RETURN   LR    R11,R3             PUT RETURN VALUE INTO R11
         LM    R12,R10,SAVREGS    RESTORE CALLER'S REGS EXCEPT R11
         BR    R13                RETURN TO CALLER
         END
 
The following WatC program shows calling CTEST:
 
/inc watc
#include <stdio.h>
int ctest(int arg1, int arg2);   /* function prototype */
int main(void)
{
int res;
printf("main starting\n");
res=ctest(20,30);
printf("res from ctest is %d\n",res);
return 0;
}
/inc ctest.obj
 
The output is:
 
main starting
res from ctest is 50


Waterloo C Sockets for TCP/IP

 
Using various library functions, most of which are in the object
file $tcp:watc.sockets.obj, it is possible to program TCP/IP
socket applications in Waterloo C under MUSIC/SP.  This is a
MUSIC/SP addition to the standard Waterloo C.  The WatC socket
functions use an interface that is very close to the more-or-less
standardized one used by Unix, VM, and Windows (WinSock) sockets.
 
For details, please refer to the section on Waterloo C in the
documentation file $tcp:sockets.doc .
 
There is a sample program in file $wcc:watc.sock.sample .
 
The header file for WatC socket functions is <socket.h>, which is
in file $wcc:clib.socket.h .  The #include statement for <socket.h>
should precede other #include statements for library header files.

 
-----
Converted Tue Nov 22, 2005 10:15:12 by help2html from Help file $HLP:@GO.WATC