


			    C Compiler for PWS

			     21	October	1987

			     Angelika Hierath

				 BCD R&D

			     Hewlett Packard


       Following is the	description of the first  version  of  a  C
       compiler	 for the PWS 3.2 (Pascal Workstation). This version
       is running right	now under HP-UX, either	on S200/300 or S500
       and  on PWS 3.2.	 The compiler produces assembly	code, which
       the workstation assembler is able to process.

       There are also some other facilities necessary  to  run	the
       final  code  of	a C program on PWS. One	is a Pascal program
       that calls  the	C  main	 routine  and  imports	all  needed
       modules.	  We have implemented a	subset of the HP-UX Runtime
       Support System as libraries.  A detailed	description of	the
       available  libraries and	system calls and how to	use them is
       given in	section	3.

       This document is	not intended to	be  a  C  reference  or	 to
       explain	any  of	 the  Pascal  workstation  features.  It is
       assumed that the	user of	this C compiler	is C  knowledgeable
       and familiar with how to	use the	PWS compiler, assembler	and
       librarian and how to run	a program on PWS.

       This compiler is	derived	from the portable C compiler on	the
       HP-UX 9000 S300.

       NOTICE: Therefore a HP-UX license is rrrreeeeqqqquuuuiiiirrrreeeedddd  to  run  code
       output from this	compiler.






























				  - 2 -



       1.  HHHHoooowwww ttttoooo rrrruuuunnnn aaaa	CCCC pppprrrrooooggggrrrraaaammmm oooonnnn PPPPWWWWSSSS

       There are two systems on	which you can develop a	C  program.
       The  first  one	is any HP-UX (s200/300 or s500 with version
       5.0) system.  In	this case  the	C  program  is	edited	and
       compiled	on HP-UX.  Then	it is brought onto PWS via lifcp or
       something else and assembled.  All  steps  necessary  to	 do
       this  are  explained  in	 the first section of this chapter.
       How the user can	develop	a  C  program  totally	on  PWS	 is
       described  in the second	section.  How to finally run such a
       program is discussed in the third section.


       1.1  DDDDeeeevvvveeeellllooooppppmmmmeeeennnntttt	uuuunnnnddddeeeerrrr HHHHPPPPUUUUXXXX

       It is possible to develop and compile a C program  on  HP-UX
       for  the	later use on PWS.  To do so the	modified C compiler
       has to be used.	It is called ccom and is available for both
       HP9000 s200/300 and s500	running	HP-UX.	The steps necessary
       to get an assembly file which then can be brought  onto	PWS
       are the following:

       $ /lib/cpp tstfile.c tstfile

       $ ccom -P tstfile tstfile.s

       $ expand	tstfile.s >TSTFILE

       $ lifcp TSTFILE /dev/rfd:

       The expand is necessary,	because	the tabs  in  the  assembly
       code  are  not accepted by the workstation assembler. The -P
       flag is optional, it  specifies	whether	 the  Pascal  entry
       point  and  the	import	information  for a module should be
       created.	This is	covered	in a later section.

       The lifcp  step	can  be	 supplanted  with  appropriate	SRM
       commands	to transfer the	file.


       1.2  DDDDeeeevvvveeeellllooooppppmmmmeeeennnntttt	uuuunnnnddddeeeerrrr PPPPWWWWSSSS

       The program which allows	the user to do this is	called	cc,
       like  on	 HP-UX.	 This program calls the	preprocessor (CPP),
       and the compiler	(CCOM).	 The final output of  this  program
       is  an assembly file, readable by the ASSEMBLER.	 The format
       of the input file has to	be C style.  This  means  that	the
       source  files must be translated	(with the FILER's translate
       command)	into type .UX files.  It is recommended	that, after
       the  translate  is done,	the file name is changed so that it
       has a ".c" suffix.











				  - 3 -



       If you run CC you have to be aware of the following:

	  - The	user should work on a SRM (or HFS) file	system.

	  - The	include	files have to be on a  SRM  (or	 HFS)  file
	    system.

	  - The	programs CPP, and CCOM have to be in proper places.
	    This is your system	default	or *.

	  - CLIBRARY.CODE has to be p-loaded.

	  - The	input file has to be in	C (.UX)	style format.

	  - If the program is stoped by	the user there may be  some
	    temporary files .  The user	has to manually	remove such
	    files.


       1.2.1  CCCCCCCC

       To compile a  C	program	 on  PWS  execute  cc.	 After	the
       invocation the following	display	appears:

       C Compiler      [ 01/14/86]
       What source file	?

       The user	input to this is the name of a C file.	As you will
       see  later  on,	the  name  of  the generated module will be
       whatever	you type in as source file name.  If  the  name	 of
       the  source  file is for	example	#3:TSTP.C this will be kept
       by the preprocessor and the name	of the module will then	 be
       #3:TSTP.	  Therefore  if	 you don't like	module name of this
       kind you	have to	copy your source file  onto the	SRM  system
       too.

       Then you	are asked for the name	of  an	output	file.	The
       default	value  is derived from the name	of the source file.
       If there	is a '.C' or  a	 '.c'  at  the	end  this  will	 be
       stripped	off.  A	'.S' or	'.s' is	then appended to this name.
       This name is also taken as  first  part	for  two  temporary
       files.	They  get  '.T1'  and '.T2' as suffix.	Now you	are
       asked for the CPP options.  The	options	 are  described	 in
       section	1.2.2.	 Unless	 you  don't  press 'CR'	you will be
       asked for up to 30 CPP options.	At the	end  the  user	can
       input up	to 5 CCOM options, see 1.2.3.
















				  - 4 -



       1.2.2  CCCCPPPPPPPP

       This program was	directly taken from HP-UX, with	no changes.
       The following options are available:

       - DDDDname

       - DDDDname=def

       - IIIIdir

       - UUUUname

       The meaning of this options is the same as  in  HP-UX.	For
       details refer to	the "HP-UX Reference Manual Section 1, cpp"

       As mentioned previously the include files have to be  on	 an
       SRM  or	HFS  system.  This is because of how the pathes	for
       them are	generated.  An example for the -I option looks like
       -I#5:/USERS.


       1.2.3  CCCCCCCCOOOOMMMM

       This program is the C compiler, compare with ccom on  HP-UX.
       Because	this  program  needs several temporary files, which
       can extend their	size during execution, it is  necessary	 to
       run  it	on an SRM or HFS system.  The name of the temporary
       files are of the	form 'pcXXXXXXXX' and 'dnXXXXXXXX'.

       The available options here are:

       - PPPP Generate the	Pascal entry point for a routine.

       - CCCC This	option causes a	special	import text for	 a  routine
	parameter  of type character. Instead of 'charvar: ANYPTR',
	'var charvar: char' is generated.

       - IIII This	option supresses the module initialization code	and
	the copy of inittialized global	variables and strings.

       - YYYYEEEE This option	causes source code lines to be	printed	 on
	the  assembly  file  as	assembly comments, thus	showing	the
	correspondence between C source	and the	resulting  assembly
	code.

       - wwww Suppress warning messages.















				  - 5 -



       1.3  RRRRuuuunnnnnnnniiiinnnngggg tttthhhheeee	pppprrrrooooggggrrrraaaammmm

       For the further steps you have to have a	special	version	 of
       the following:

	  - CLIBRARY, C	support	library	( minimum required part	 of
	    this library is CLIB).

	 A.  The first step  is	 to  assemble  the  output  of	the
	     compiler on the workstation.

	 B.  The next step is to create	a Pascal main program. This
	     program  calls  the  C  main  routine  and	imports	the
	     CLIBRARY  stuff  and  the	C  module,  which  is  very
	     important.	This program looks always like this :

		 $SEARCH 'CLIBRARY'$
		 PROGRAM TST(INPUT,OUTPUT);

		 IMPORT	TSTFILE,CLIB;

		 VAR X : INTEGER;
		 BEGIN
			 X := MAIN;
		 END.

	     After you have created this program compile it.  There
	     should  be	 no  error messages at this point. If there
	     are some, there possibly may be several things  wrong.
	     Either  CLIBRARY.CODE  or	TSTFILE.CODE are not at	the
	     proper place, or the export text of TSTFILE  does	not
	     match the declaration in the Pascal main program. This
	     is	when you  have	declared  main	not  to	 return	 an
	     integer  value,  or  when	main has some arguments. If
	     this is the  case,	 you  have  to	update	the  Pascal
	     program accordingly.

	     If	your C program consists	of several files, which	are
	     considered	at this	point the same way assembly modules
	     are, you have to import every  module.  Otherwise	the
	     program may (or may not) run properly.

	 C.  The last step  is	to  link  all  these  =.CODE  files
	     together  with  the librarian.  You may only link some
	     modules together, while the others	are P-loaded.  This
	     step  varies,  depending  on  how	the system is to be
	     used.

       At this point you should	be able	to  run	 your  program	the
       same way	you run	a Pascal program.












				  - 6 -



       2.  CCCC ccccoooommmmppppiiiilllleeeerrrr iiiinnnntttteeeerrrrnnnnaaaallllssss

       This section describes how the C	compiler  works	 and  which
       differences  exist between the HP-UX and	the PWS	version. It
       also outlines which parts of the	C code had to  be  changed.
       There  is  a  description  of how to call a C routine from a
       Pascal routine and vice versa. The last one is used when	the
       Pascal main program calls the C main routine.

       Before starting with the	description of the internals it	 is
       necessary  to sum up the	differences between C and Pascal in
       general.	The main difference is how parameters are passed to
       routines	and how	the value of a function	is returned.


       2.1  CCCC cccchhhhaaaarrrraaaacccctttteeeerrrriiiissssttttiiiiccccssss

       In C parameters are passed from right to	the left via stack,
       the  last  parameter  is	 pushed	 first,	the first is pushed
       last. All parameters are	passed by value. If the	user  wants
       to  pass	 something by reference	they have to pass a pointer
       and has to declare it in	the called subroutine  accordingly.
       The  stack  space  used	to  pass parameters is freed by	the
       calling routine.	 The return value  of  a  routine  is  done
       through the registers d0	and d1,	depending on the type.

       Floats in C are only 4 Bytes long, but they  are	 passed	 as
       doubles	(8  Bytes).  This translation is automatically made
       by the compiler.	Variables  of  type  character	are  passed
       using 4 Bytes.

       In  C  it  is  possible	to  declare  local  variables	and
       parameters  to  be stored in registers (register	variables).
       Therefore the compiler generates	 code,	to  save  registers
       used  in	 this  routine	on  the	 stack.	This is	done at	the
       beginning of each routine. Before returning from	 a  routine
       those  are  restored.  This  mechanism is very advantageous,
       because only those registers are	saved that are really  used
       in a subroutine.

       You can have different kinds of global variables, explicitly
       initialized  and	not explicitly initialized. Non	initialized
       globals are however automatically initialized with zeroes.


       2.2  PPPPaaaassssccccaaaallll cccchhhhaaaarrrraaaacccctttteeeerrrriiiissssttttiiiiccccssss

       In Pascal parameters are	passed from the	left to	the  right.
       The  first  parameter  is  pushed  first	and so forth. There
       exists a	call by	value and an explicit  call  by	 reference.
       The  stack  space  used	to  pass parameters is freed by	the











				  - 7 -



       called routine, before returning	 to  the  calling  routine.
       The  return  value  of  a  function is pushed onto the stack
       beneath the parameters.

       Parameters of type real	are  always  passed  by	 reference.
       Therefore, if a real is passed, the called routine must copy
       the value of the	real. Characters are passed using 2 Bytes.

       There are no register  variables	 available  in	Pascal	and
       there  is  no  way  to know which registers are used.  After
       each Pascal program statement all registers are	reevaluated
       as needed.

       Register	a5 is used to  reference  global  variables.   This
       register	should never been used in a user program.  It never
       changes its value.


       2.3  EEEEnnnnttttrrrryyyy ppppooooiiiinnnnttttssss,,,, iiiimmmmppppoooorrrrtttt tttteeeexxxxtttt aaaannnndddd ----PPPP ooooppppttttiiiioooonnnn

       Given  the  previous  stated  differences  the  C   compiler
       generates  different  code,  depending  on  whether a Pascal
       routine is called from a	C routine or whether a C routine is
       called  from  a Pascal routine.	There are no changes in	the
       case where another C routine is called from C.

       The compiler generates two entry	points	for  each  routine,
       and  an import text section for each module.  Each C program
       file comprises one module, but may contain several routines.
       The  name  of the resulting module is the filename. The name
       of the C	entry point for	a routine is '_routine'.  The  name
       of  the	Pascal	entry  point  is 'modulename_routine'. Both
       names follow the	conventions used  so  far.  Additionally  a
       module initialization routine is	generated, the name of this
       is 'modulename_modulename'.

       The  Pascal  entry  point  and  the  import  text  are  only
       generated  when	'ccom  -P'  is called.	If the user wants a
       routine to be callable only from	C, he must  not	 call  ccom
       with  the  '-P'	option.	 This option is	always applied to a
       whole module.  It is not	possible  to  generate	the  Pascal
       entry  for  one routine in a file and not to generate it	for
       another one in the same file. To	do this, you must split	the
       routines	into different files.

       It is clear that	you have to generate the Pascal	entry point
       at least	for the	routine	'main'.	Otherwise you can't call it
       from your Pascal	main program.

       The import text contains	an entry for each global C variable
       and global available C routine. They look like











				  - 8 -



	       src function func( x1:type; x2:type;...):type;
       for C routines and
	       src var modulename_varname['_varname']:type;
       for global variables.

       In C there is only a call by value.  Call  by  reference	 is
       done  using  pointers.	In  order to ease the user's job of
       interfacing, I have tried to mix	the two	strategies.   If  a
       parameter  is  a	 pointer the compiler checks for uncomposed
       (simple)	data types.  If	a parameter is one of those (short,
       integer,	 float,	 double), the import text does not generate
       ANYPTR as the type of the variable. Instead
	       ... var varname:type ...
       is generated.  This can also be done for	parameters of  type
       character if the	-C option is used with ccom.

       You cannot call	C  routines  with  a  '_'  or  '@'  at	the
       beginning  of  the  routine name	from Pascal. This is due to
       the Pascal compiler.  It	cannot process the resulting import
       text.   Therefore,  it  is  unwise  to generate Pascal entry
       points for routines with	such names.


       2.3.1  IIIImmmmpppplllleeeemmmmeeeennnnttttaaaattttiiiioooonnnn

       To implement this the routines in file code.c were  changed.
       Most  of	the modifications occurred in the "bfcode" routine.
       This routine is responsible to output a	def  statement	for
       the  routine  name.  It	also  computes	the  offset for	the
       parameters.  A new routine called genpentry has been  added.
       This  routine  generates	the Pascal entry point depending on
       pascalflag, it is called	from bfcode.  The  import  text	 is
       mainly  generated by the	routines genpentry and defnam (both
       in code.c).


       2.4  MMMMoooodddduuuulllleeee iiiinnnniiiittttiiiiaaaalllliiiizzzzaaaattttiiiioooonnnn

       For  each  module  a  module   initialization   routine	 is
       generated.  As a	result of this mechanism it is not possible
       to give a routine the same name as the file's name. But this
       is not possible on PWS anyway.

       The purpose of  this  routine  is  to  initialize  C  global
       variables.   If	you do an import from a	Pascal main program
       this routine is called  first,  before  executing  any  real
       code.	This   routine	is  called  once  for  each  import
       statement.

       The first version of the	C compiler forced the user to  call
       or  import  this	 routine.   You	may or may not need to call











				  - 9 -



       this routine depending on the following:	If  you	 only  care
       about initialization of C globals during	load time, you need
       not call	the routine, but you may.  If you run your  program
       without	reloading  it  the  C  globals	may not	contain	the
       initialized value. They will contain the	last value from	the
       previous	 run.	If  you	are concerned about such situations
       you  should   call   the	  initialization   routine.    This
       distinction was made because of the C standard.

       If routines from	CLIBRARY are called CLIB has to	be imported
       right now.  This	requirement may	be changed at a	later date.


       2.5  HHHHoooowwww	ttttoooo ccccaaaallllllll	PPPPaaaassssccccaaaallll rrrroooouuuuttttiiiinnnneeeessss	ffffrrrroooommmm CCCC

       To call a Pascal	routine	from C you must	declare	the routine
       as  type	Pascal,	just as	you do with external routines.	The
       syntax of  the  routine	name  is  'modulename_routinename',
       which  is the full specification	of the Pascal routine name.
       The declaration of a Pascal routine looks like:

	       pascal <type> <modulename_routinename>();

       To call a Pascal	routine	 from  C  there	 are  a	 number	 of
       actions	 to   be   performed.	 All   these   actions	are
       automatically performed if the routine is declared to  be  a
       Pascal routine.

	  - save all registers on the stack

	  - reserve space on the stack	for  the  return  value	 if
	    needed

	  - pass parameters in reversed	order, and convert them	 if
	    necessary

	  - use	the given name to indicate the entry point  to	the
	    Pascal routine

	  - store the return value in register d0-d1,  and  convert
	    it to the appropriate type

	  - restore all	registers from the stack

       If the user wants to call a Pascal procedure  they  can	use
       the '(void)' instruction	(e.g (void) pascal_proc(..., ...)).
       In this special case there is no	stack space reserved for  a
       return  value,  so  be careful not to call a Pascal function
       with this construction. Even if you  don't  care	 about	the
       return  value.	Utilizing  this	"feature" can cause erratic
       program behavior.











				  - 10 -



       2.5.1  PPPPoooossssssssiiiibbbblllleeee ttttyyyyppppeeeessss ooooffff	ppppaaaarrrraaaammmmeeeetttteeeerrrrssss

       Variables of the	following C type can be	passed to a  Pascal
       routine.

	  - character and unsigned character

	  - short and unsigned short, they are passed as integers

	  - integer, unsigned, long and	unsigned long

	  - double

	  - pointer (ANYPTR)

       You can not at this time	pass variables of type float.	You
       also   should   not   pass   a	character   directly   like
       pasc_proc(...,'a',...). In this case the	compiler  generates
       a  4  byte  value, because it cannot be distinguished from a
       direct passing of an integer value.


       2.5.2  PPPPoooossssssssiiiibbbblllleeee ttttyyyyppppeeeessss ooooffff	rrrreeeettttuuuurrrrnnnn vvvvaaaalllluuuueeeessss

       The Pascal return types can be translated to the	following C
       types:

	  - character

	  - short, in this case	a Pascal integer is converted to  a
	    short

	  - integer and	long

	  - float, the Pascal real is converted	 to  a	float  with
	    ftod

	  - double

	  - pointer


       2.5.3  IIIImmmmpppplllleeeemmmmeeeennnnttttaaaattttiiiioooonnnn

       It was necessary	to define a new	 cookie	 value,	 "FORARGP".
       This  new  cookie  indicates  that  the	arguments are to be
       passed to a Pascal routine  rather  than	 to  a	C  routine.
       Together	with this, additional templates	(table.c) have been
       created for the new cookie.













				  - 11 -



       The routine gencall (local2.c) required also  many  changes.
       It  handles the return value of the Pascal routine. It saves
       and restores the	registers, reserves  stack  space  for	the
       return  value and stores	it into	d0-d1 and it is	responsible
       for passing the parameters in the correct order.

       Another change had to be	 done  in  p2tree  (trees.c).  This
       routine	checks	whether	 a routine or global variable is of
       type pascal. If this is the case	the declared name is  taken
       directly	without	any changes to it.


       2.6  HHHHoooowwww	ttttoooo ccccaaaallllllll	CCCC rrrroooouuuuttttiiiinnnneeeessss ffffrrrroooommmm	PPPPaaaassssccccaaaallll

       To call a C routine from	Pascal the user	has to compile	the
       corresponding  C	 file  with  the  '-P'	option.	 The Pascal
       module or program has to	import it.  This  is  done  exactly
       like it would be	a Pascal module.

       The Pascal module calls the Pascal entry	point in this case.
       The actions performed by	this routine are:

	  - push the parameter onto the	stack in reverse order

	  - call the C entry point (C routine)

	  -  push  the	result	from  d0-d1  onto  the	stack,	 do
	    transformations if necessary

	  - free up the	space used by the parameters

	  - return to the calling routine

       If a user wants a C routine to be treated like  a  procedure
       in  Pascal  they	 can  use  the	'void'	type (e.g. void	int
       croutine(...) ).	In this	case the import	text  contains	the
       information that	a procedure xyz	is defined in this module.


       2.6.1  PPPPoooossssssssiiiibbbblllleeee ttttyyyyppppeeeessss ooooffff	ppppaaaarrrraaaammmmeeeetttteeeerrrrssss

       The types of the	passed variables  can  only  be	 predefined
       Pascal  types.	These  are  characters,	integers, reals	and
       ANYPTR.


















				  - 12 -



       2.6.2  PPPPoooossssssssiiiibbbblllleeee ttttyyyyppppeeeessss ooooffff	rrrreeeettttuuuurrrrnnnn vvvvaaaalllluuuueeeessss

       The values returned from	a C routine can	be any valid C type
       values. They are	transformed automatically into Pascal types
       where necessary.


       2.6.3  IIIImmmmpppplllleeeemmmmeeeennnnttttaaaattttiiiioooonnnn

       The calling of C	routines from Pascal is	handled	 by  a	new
       routine called 'genpentry' (code.c).


       2.7  HHHHoooowwww	ttttoooo aaaacccccccceeeessssssss CCCC gggglllloooobbbbaaaallllssss ffffrrrroooommmm PPPPaaaassssccccaaaallll

       It is possible to access	a C global from	Pascal by using	the
       name "modulename_varname". The import text must be generated
       with the	-P option, to allow this access.


       2.8  HHHHoooowwww	ttttoooo aaaacccccccceeeessssssss PPPPaaaassssccccaaaallll gggglllloooobbbbaaaallllssss ffffrrrroooommmm CCCC

       To call a Pascal	global variable	the same directive  can	 be
       used as for calling Pascal routines.

	       pascal <type> <modulename>;

       This definition indicates to the	compiler, that you want	 to
       access  a pascal	module.	 The address of	a Pascal global	has
       to be computed within the C routine.  Following is a general
       description of how this must be done:

       Declarations:
	       pascal  <modulename>;
	       extern pgbase;

	       <type> *<variablename>;

       Computation of the address:
	       <variablename>=(<type>*)(pgbase-<offset>+(<type>)(&<modulename>);

       Using the variable's value:
	       ... = (<type>) *	(<variablename>);

       The variable 'pgbase' is	a global C variable.   It  contains
       the  contents  of register a5.  This variable is	defined	and
       initialized in module CLIB.   Therefore	you  must  run	the
       module  initialization routine CLIB to access Pascal globals
       within a	C routine.  This access	 method	 is  shown  in	the
       example in the last section.












				  - 13 -



       2.9  SSSSttttddddiiiinnnn,,,, ssssttttddddoooouuuutttt,,,, ssssttttddddeeeerrrrrrrr

       The compiler generates code which automatically opens stdin,
       stdout  and  stderr for the routine main.  This is only done
       when you	have invoked  ccom  with  -P.	In  this  case	the
       standard	files are set up in a way similar to HP-UX.  At	the
       moment the user must do an import of CLIBRARY if	he wants to
       do any I/O, see chapter 1.

       The C routine main  has	another	 special  meaning  in  this
       context.	 If the	Pascal entry point is generated	for routine
       main it is assumed that the Pascal main program serves  only
       to  call	 a  C  program.	  Therefore  this entry	point looks
       different from other  Pascal  entry  points.   First  stdin,
       stdout  and stderr are set up properly.	Then the parameters
       are pushed on the stack in reversed order  and  the  C  main
       routine	is  called.   After the	return from main this entry
       point automatically calls exit.	Exit calls the C fclose	for
       all  files  with	 outstanding  I/O and exits from the user's
       program at this point.  Therefore you cannot  call  main	 in
       the  midst  of  a  Pascal  program,  because  of	the special
       meaning of the C	main routine.

       This was	done because in	C there	are buffered files  and	 it
       seemed  not wise	to let the user	be able	to toggle between C
       and Pascal I/O operation.  If the user really  wants  to	 do
       this, stdin, stdout and stderr must be opened explicitly	and
       the name	main cannot be used for	the C main routine.

       If there	is no C	main routine, the file pointers	0, 1, 2	and
       stdin, stdout and stderr	are not	available.  The	user has to
       open them explicitly.  This can be done	by  calling  the  C
       open routine for	'#1:' with read	or write mode.	This has to
       be done in the correct order, otherwise	the  standard  file
       pointers	 are  not related to the standard file descriptors.
       Therefore first open '#1:' with read mode, then	twice  with
       write mode.


       2.10  KKKKnnnnoooowwwwnnnn PPPPrrrroooobbbblllleeeemmmmssss

       Due to a	PWS ASSEMBLER bug it is	not  possible  to  use	the
       constant	 "#-2147483648"	 (-2**31). In this case	you have to
       edit the	 compiler  output  and	replace	 it  with  the	hex
       equivalent  ($80000000).	  A fix	to this	may be investigated
       in the future.

       There is	no distinction between lower case  and	upper  case
       symbol  names.	This  is  true	for  both routine names	and
       variable	names.












				  - 14 -



       It is not possible to give a routine the	same  name  as	the
       file's name.

       The user	has to be careful about	the declaration	of the same
       C  global  in different modules,	even when they look exactly
       the same.  On HP-UX the loader can  solve  such	situations,
       this  is	 not  possible	on  PWS.  This is because the PWS C
       compiler	generates initialization code  for  the	 global	 in
       both modules.  If you try to link such modules together with
       the PWS librarian, it asks you whether you really want to do
       this.   You  should answer with NO, and solve the problem in
       your C code.  Otherwise you might get problems.

       Variables  and  parameters  of  type  unsigned  integer	 or
       unsigned	 long  might  cause  some  problems  when used by a
       Pascal program.	The C compiler generates type  integer	for
       those  variables	 in  the export	text.  If the user wants to
       use these types they should turn	 range	check  off  in	the
       corresponding Pascal program.











































				  - 15 -



       3.  DDDDeeeessssccccrrrriiiippppttttiiiioooonnnn ooooffff CCCCLLLLIIIIBBBBRRRRAAAARRRRYYYY,,,, tttthhhheeee	CCCC ssssuuuuppppppppoooorrrrtttt lllliiiibbbbrrrraaaarrrryyyy

       This library consists of	two parts, CLIB, and CSYS.  CSYS is
       composed	 of  four  parts,  linked together: LIBCRT, LIBSYS,
       LIBGEN, and LIBSTDIO.  These correspond	to  the	 C  runtime
       support	on  HP-UX.   The user using CLIBRARY however cannot
       see the different parts.


       3.1  CCCCLLLLIIIIBBBB

       It is very important this module	be imported in every Pascal
       program	calling	 a C routine.  This module calls the module
       initialization  part  of	 all  of  the  C  support   modules
       contained in CLIBRARY.


       3.2  LLLLIIIIBBBBCCCCRRRRTTTT

       This library consists of	the low	level  routines,  that	are
       used  to	 do  arithmetic,  handle  floating  point  numbers,
       convert doubles to floats, etc.	To build up this library we
       took  the  assembly  routines  from the HP-UX 9000 S300 with
       some changes.


       3.3  LLLLIIIIBBBBSSSSYYYYSSSS

       This library implements some of the system  calls  available
       on HP-UX. These system calls are	implemented in assembly	and
       they themselves call  the  lower	 level	routines  from	the
       Pascal  Workstation,  for  example  fhpopen, freadbytes etc.
       There are some differences between these	calls and the HP-UX
       C requirements.

       The routines implemented	so far are :

	  - open
	    There are several open flags possible. To open the file
	    for	read you have to call open with	'0', to	write to it
	    use	'1', read and write permission is  flag	 '2'.  This
	    call  is  also  used  to  create  a	 file, compare with
	    O_CREAT on HP-UX.

	    A file opened with the C open call is always opened	 as
	    'file of char'.

	    This routine also sets a flag  that	 indicates  whether
	    the	 opened	 file  is  a  terminal device.	So far only
	    volumes '#1:' and '#2:' are	recognized  as	interactive
	    or terminal	devices.











				  - 16 -



	    With this call it is also possible to open volumes	for
	    direct volume read and write.

	  - creat
	    no changes,	except that the	mode is	ignored	right now.

	  - creat_text
	    Creates a file and opens it	as text.

	  - close
	    no changes

	  - read
	    The	read works similar to the read	on  HP-UX.  If	you
	    want  to  read  from stdin,	you can	use file pointer 0.
	    This is automatically opened for reading if	the  Pascal
	    main  program  calls  the  C main routine, see previous
	    section.

	    If a  read	request	 to  stdin  is	done,  each  CR	 is
	    translated	into a LF by default.  A read from stdin is
	    done byte by byte and stops	if there is a CR or Ctrl^D.
	    However  EOF  is  only  set	if the Ctrl^D was the first
	    character of a keyboard input.

	    If a read request to a file	is done,  the  PWS  routine
	    fsreadbytes	 is  called.   To  the	user  there  is	 no
	    difference to a read request on HP-UX.

	  - write
	    This routine works according to read.  File	 pointer  1
	    and	2 can be used to write to stdout and stderr. If	you
	    write to  a	 terminal  or  to  a  printer  LF  (\n)	 is
	    translated into CR LF.

	    If a write request to a file is done, the  PWS  routine
	    fswritebytes  is  called.	To  the	 user  there  is no
	    difference to a write request on HP-UX.

	  - lseek
	    no changes.

	  - exit,_exit
	    This routine does a	close of  all  stream  files  where
	    there   is	an  outstanding	 I/O  and  exits.  This	 is
	    necessary because otherwise	the last output	 to  stdout
	    or other stream files can be lost.

	  - isatty
	    This routine is also part of this library because it is
	    related  to	 the others in here. A call to it returns 1











				  - 17 -



	    if the given  file	descriptor  is	associated  with  a
	    terminal, 0	otherwise.

	  - gotoxy
	    Same as in PaWS.

	  - time
	    Returns seconds since 1 Jan	1970 GMT.

	  - sbrk
	    Allocated memory cannot be returned.

	  - unlink
	    unlink  can	 only  delete  files  which   are   closed.
	    Therefore the user has to close a file before unlinking
	    it.

	  - access
	    If the file	given exists, this routine return always 0,
	    otherwise -1.

	  - getpid
	    This routine returns  a  fixed  value  in  the  current
	    version.


       3.4  LLLLIIIIBBBBGGGGEEEENNNN

       The C source from HP-UX was compiled  utilizing	the  PWS  C
       compiler.   There  were	no  changes  done on the original C
       version.

       The available routines are: _ctype, mktemp, strcat,  strchr,
       strrchr,	 strcpy, strncpy, strlen, strncat, strcmp, strncmp,
       strpbrk,	 strspn,  strcspn,  strtok,  strtol,  atof,   atoi,
       strtod,	ecvt, fcvt, malloc, free, realloc, memccpy, memchr,
       memcpy,	memset,	 memcmp,  assert,  calloc,  cfree,  perror,
       mult32,	cvt,  gcvt,  a64l,  l64a, abs, ltol3, l3tol, qsort,
       drand48,	 erand48,  jrand48,  lcong48,	lrand48,   mrand48,
       nrand48,	 seed48,  srand48,  srand,  rand, bsearch, hsearch,
       hcreate,	hdestroy, lsearch, lfind.


       3.5  LLLLIIIIBBBBSSSSTTTTDDDDIIIIOOOO

       The C source from HP-UX was compiled  utilizing	the  PWS  C
       compiler.   There  were	no  changes  done on the original C
       version.

       Available routines are :	clearerr, ctermid,  fdopen,  fgetc,
       fgets,  filbuf,	findiop,  flsbuf,  fopen,  fclose,  fflush,











				  - 18 -



       freopen,	fputc, fputs, fread, fseek,  ftell,  fwrite,  gets,
       getw,  puts,  putw, rewind, printf, fprintf, sprintf, scanf,
       fscanf, sscanf, setbuf, setvbuf,	 tmpfile,  tmpnam,  ungetc,
       vfprintf,  vprintf, vsprintf, tolower, toupper, swab, ctime,
       localtime, gmtime, asctime, ct_numb, tzset, tfind,  tsearch,
       tdelete,	twalk.
























































				  - 19 -



       4.  FFFFiiiilllleeee	ppppooooiiiinnnntttteeeerrrr	ttttaaaabbbblllleeee aaaannnndddd ccccoooonnnnnnnneeeeccccttttiiiioooonnnn ttttoooo	FFFFIIIIBBBB....

       This section is a description for those who  are	 interested
       in  how the file	pointers from C	are translated into FIBs on
       PWS.

       In module PAWSCSYS a file descriptor table for 64 entries is
       initialized.   This  allows  64	simultaneously	open files.
       Each entry consists of a	number,	which  indicates  the  file
       descriptor,  an	in_use	byte  that  indicates  whether this
       information block is already in use, a pointer to a FIB	and
       a pointer to a window.

       The fildes_table	has the	type :

       type
	       fildes =	0..63;

	       fildesentry = packed record
		       fd      : file_pointer;
		       in_use  : boolean;
		       is_unit1: boolean;
		       is_unit2: boolean;
		       is_unit6: boolean;
		       use4, use5, use6, use7: boolean;
		       f_ptr   : fibp;
		       fwindow : windowp;
		       end;
       end;

       The field 'fd' of this structure	contains the number of	the
       corresponding file descriptor.

       The  second  byte  (offset  1)  of  this	 structure  has	 an
       important  function.   Each bit has a special meaning. Bit 0
       indicates whether this file_table block is already  used	 by
       another file pointer.  Bits 1, 2, and 3 indicate	whether	the
       related files are '#1:',	'#2:' or  '#6:'.   These  bits	are
       cleared during initialization.

       If the user calls open, the routine searches for	 the  first
       available  fildes_table entry.  If there	is an entry left, a
       FIB gets	initialized and	 assigned  to  the  'f_ptr'  field.
       After  a	successful open	of the file the	in_use bits are	set
       accordingly.

       Close calls the PWS fclose with the proper FIB,	and  clears
       the in_use byte.

       When a read or write request is	made,  the  proper  FIB	 is
       utilized	 to  call  the corresponding Pascal routine.  Lseek











				  - 20 -



       utilizes	the FIB	and resets  file  positions  based  on	the
       request,	no I/O is done.




























































				  - 21 -



       5.  EEEExxxxaaaammmmpppplllleeee

       The following is	an example of a	C main routine called by  a
       Pascal  main  program.	The C routine itself calls a Pascal
       function	(pascal_sum).  Within the C routine the	address	 of
       a Pascal	global is computed, and	the value of this global is
       used.  The Pascal main program writes the  value	 of  two  C
       globals	to  the	console.  The example also shows how to	use
       CLIBRARY.

       Pascal main program:

	       $SYSPROG$
	       $SEARCH 'TSTFILE','CLIBRARY'$
	       PROGRAM TST(INPUT,OUTPUT);
	       IMPORT TSTFILE,CLIB;
	       VAR
		       X : INTEGER;
		       Y : INTEGER;
		       Z : INTEGER;
	       BEGIN
		       {write C	globals}
		       WRITELN(TSTFILE_I,TSTFILE_J);
		       X := 5;
		       Y := 6;
		       Z := 10;
		       {call C main routine}
		       MAIN(Y,Z);
	       END.

       The C main routine:

	       pascal pascal_sum();
	       pascal TST;
	       extern pgbase;
	       int i = 1;
	       int j = 2;
	       int *TST_X;
	       void main(a, b)
	       {
	       int s;
		       /* create pointer to X in Pascal	global space */
		       TST_X = (int *)(pgbase -	4 + (int)(&TST));
		       /* call pascal function */
		       s = pascal_sum(a, b, i, j, (int)*(TST_X));
		       printf( "sum : %d0,s);
	       }















				  - 22 -



       Pascal module:

	       MODULE PASCAL;

	       EXPORT
		       FUNCTION	SUM(A,B,C,D,E :	INTEGER) : INTEGER;

	       IMPLEMENT
		       FUNCTION	SUM(A,B,C,D,E :	INTEGER) : INTEGER;
			       BEGIN SUM := A+B+C+D+E END;
	       END.


       Compiler	listing	of Pascal program:

       Pascal [Rev 3.1M	 7/18/85] EXMAIN.TEXT

	    1:D	       0 $SYSPROG$
	    2:D	       0 $SEARCH 'TSTFILE','TSTCC:CLIBRARY'$
	    3:S
	    4:D	       0 PROGRAM TST(INPUT,OUTPUT);
	    5:S
	    6:D	       1 IMPORT	TSTFILE,CLIB;
	    7:S
	    8:D	       1 VAR
	    9:D	   -4  1	X : INTEGER;
	   10:D	   -8  1	Y : INTEGER;
	   11:D	  -12  1	Z : INTEGER;
	   12:S
	   13:C	       1 BEGIN
	   14:C	       1	WRITELN(TSTFILE_I,TSTFILE_J);
	   15:C	       1	X := 5;
	   16:C	       1	Y := 6;
	   17:C	       1	Z := 10;
	   18:C	       1	MAIN(Y,Z);
	   19:C	       1 END.

       No errors. No warnings.
		      ***** Nonstandard	language features enabled *****


       The output of the example program:

		 1	    2
       sum : 24





















				 CONTENTS


       1.  How to run a	C program on PWS.......................	  2

	   1.1	 Development under HPUX........................	  2

	   1.2	 Development under PWS.........................	  2
		 1.2.1	CC.....................................	  3
		 1.2.2	CPP....................................	  4
		 1.2.3	CCOM...................................	  4

	   1.3	 Running the program...........................	  5

       2.  C compiler internals................................	  6

	   2.1	 C characteristics.............................	  6

	   2.2	 Pascal	characteristics........................	  6

	   2.3	 Entry points, import text and -P option.......	  7
		 2.3.1	Implementation.........................	  8

	   2.4	 Module	initialization.........................	  8

	   2.5	 How to	call Pascal routines from C............	  9
		 2.5.1	Possible types of parameters...........	 10
		 2.5.2	Possible types of return values........	 10
		 2.5.3	Implementation.........................	 10

	   2.6	 How to	call C routines	from Pascal............	 11
		 2.6.1	Possible types of parameters...........	 11
		 2.6.2	Possible types of return values........	 12
		 2.6.3	Implementation.........................	 12

	   2.7	 How to	access C globals from Pascal...........	 12

	   2.8	 How to	access Pascal globals from C...........	 12

	   2.9	 Stdin,	stdout,	stderr.........................	 13

	   2.10	 Known Problems................................	 13

       3.  Description of CLIBRARY, the	C support library......	 15

	   3.1	 CLIB..........................................	 15

	   3.2	 LIBCRT........................................	 15

	   3.3	 LIBSYS........................................	 15




				  - i -











	   3.4	 LIBGEN........................................	 17

	   3.5	 LIBSTDIO......................................	 17

       4.  File	pointer	table and connection to	FIB............	 19

       5.  Example.............................................	 21















































				  - ii -




