297 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			Groff
		
	
	
	
	
	
.\" $Header$
 | 
						|
.TH LIBPC 7ACK
 | 
						|
.ad
 | 
						|
.SH NAME
 | 
						|
libpc \- library of external routines for Pascal programs
 | 
						|
.SH SYNOPSIS
 | 
						|
.ta 11n
 | 
						|
const	bufsize = ?;
 | 
						|
.br
 | 
						|
type	br1 =  1..bufsize;
 | 
						|
.br
 | 
						|
	br2 =  0..bufsize;
 | 
						|
.br
 | 
						|
	br3 = -1..bufsize;
 | 
						|
.br
 | 
						|
	ok = -1..0;
 | 
						|
.br
 | 
						|
	buf = packed array[br1] of char;
 | 
						|
.br
 | 
						|
	alfa = packed array[1..8] of char;
 | 
						|
.br
 | 
						|
	string = ^packed array[1..?] of char;
 | 
						|
.br
 | 
						|
	filetype = file of ?;
 | 
						|
.br
 | 
						|
	long = ?;
 | 
						|
 | 
						|
{all routines must be declared extern}
 | 
						|
 | 
						|
function	argc:integer;
 | 
						|
.br
 | 
						|
function	argv(i:integer):string;
 | 
						|
.br
 | 
						|
function	environ(i:integer):string;
 | 
						|
.br
 | 
						|
procedure	argshift;
 | 
						|
 | 
						|
procedure	buff(var f:filetype);
 | 
						|
.br
 | 
						|
procedure	nobuff(var f:filetype);
 | 
						|
.br
 | 
						|
procedure	notext(var f:text);
 | 
						|
.br
 | 
						|
procedure	diag(var f:text);
 | 
						|
.br
 | 
						|
procedure	pcreat(var f:text; s:string);
 | 
						|
.br
 | 
						|
procedure	popen(var f:text; s:string);
 | 
						|
.br
 | 
						|
procedure	pclose(var f:filetype);
 | 
						|
 | 
						|
procedure	trap(err:integer);
 | 
						|
.br
 | 
						|
procedure	encaps(procedure p; procedure q(n:integer));
 | 
						|
 | 
						|
function	perrno:integer;
 | 
						|
.br
 | 
						|
function	uread(fd:integer; var b:buf; len:br1):br3;
 | 
						|
.br
 | 
						|
function	uwrite(fd:integer; var b:buf; len:br1):br3;
 | 
						|
 | 
						|
function	strbuf(var b:buf):string;
 | 
						|
.br
 | 
						|
function	strtobuf(s:string; var b:buf; len:br1):br2;
 | 
						|
.br
 | 
						|
function	strlen(s:string):integer;
 | 
						|
.br
 | 
						|
function	strfetch(s:string; i:integer):char;
 | 
						|
.br
 | 
						|
procedure	strstore(s:string; i:integer; c:char);
 | 
						|
 | 
						|
function	clock:integer;
 | 
						|
.SH DESCRIPTION
 | 
						|
This library contains some often used external routines for Pascal programs.
 | 
						|
The routines can be divided into several categories:
 | 
						|
.PP
 | 
						|
Argument control:
 | 
						|
.RS
 | 
						|
.IP argc 10
 | 
						|
Gives the number of arguments provided when the program is called.
 | 
						|
.PD 0
 | 
						|
.IP argv
 | 
						|
Selects the specified argument from the argument list and returns a
 | 
						|
pointer to it.
 | 
						|
This pointer is nil if the index is out of bounds (<0 or >=argc).
 | 
						|
.IP environ
 | 
						|
Returns a pointer to the i-th environment string (i>=0). Returns nil
 | 
						|
if i is beyond the end of the environment list (UNIX version 7).
 | 
						|
.IP argshift
 | 
						|
Effectively deletes the first argument from the argument list.
 | 
						|
Its function is equivalent to \fIshift\fP in the UNIX shell: argv[2] becomes
 | 
						|
argv[1], argv[3] becomes argv[2], etc.
 | 
						|
It is a useful procedure to skip optional flag arguments.
 | 
						|
Note that the matching of arguments and files
 | 
						|
is done at the time a file is opened by a call to reset or rewrite.
 | 
						|
.PD
 | 
						|
.PP
 | 
						|
.RE
 | 
						|
Additional file handling routines:
 | 
						|
.RS
 | 
						|
.IP buff 10
 | 
						|
Turn on buffering of a file. Not very useful, because all
 | 
						|
files are buffered except standard output to a terminal and diagnostic output.
 | 
						|
Input files are always buffered.
 | 
						|
.PD 0
 | 
						|
.IP nobuff
 | 
						|
Turn off buffering of an output file. It causes the current contents of the
 | 
						|
buffer to be flushed.
 | 
						|
.IP notext
 | 
						|
Only useful for input files.
 | 
						|
End of line characters are not replaced by a space and character codes out of
 | 
						|
the ASCII range (0..127) do not cause an error message.
 | 
						|
.IP diag
 | 
						|
Initialize a file for output on the diagnostic output stream (fd=2).
 | 
						|
Output is not buffered.
 | 
						|
.IP pcreat
 | 
						|
The same as rewrite(f), except that you must provide the filename yourself.
 | 
						|
The name must be zero terminated. Only text files are allowed.
 | 
						|
.IP popen
 | 
						|
The same as reset(f), except that you must provide the filename yourself.
 | 
						|
The name must be zero terminated. Only text files are allowed.
 | 
						|
.IP pclose
 | 
						|
Gives you the opportunity to close files hidden in records or arrays.
 | 
						|
All other files are closed automatically.
 | 
						|
.PD
 | 
						|
.PP
 | 
						|
.RE
 | 
						|
String handling:
 | 
						|
.RS
 | 
						|
.IP strbuf 10
 | 
						|
Type conversion from character array to string.
 | 
						|
It is your own responsibility that the string is zero terminated.
 | 
						|
.PD 0
 | 
						|
.IP strtobuf
 | 
						|
Copy string into buffer until the string terminating zero byte
 | 
						|
is found or until the buffer if full, whatever comes first.
 | 
						|
The zero byte is also copied.
 | 
						|
The number of copied characters, excluding the zero byte, is returned. So if
 | 
						|
the result is equal to the buffer length, then the end of buffer is reached
 | 
						|
before the end of string.
 | 
						|
.IP strlen
 | 
						|
Returns the string length excluding the terminating zero byte.
 | 
						|
.IP strfetch
 | 
						|
Fetches the i-th character from a string.
 | 
						|
There is no check against the string length.
 | 
						|
.IP strstore
 | 
						|
Stores a character in a string. There is no check against
 | 
						|
string length, so this is a dangerous procedure.
 | 
						|
.PD
 | 
						|
.PP
 | 
						|
.RE
 | 
						|
Trap handling:
 | 
						|
.RS
 | 
						|
These routines allow you to handle almost all
 | 
						|
the possible error situations yourself.
 | 
						|
You may define your own trap handler, written in Pascal, instead of the
 | 
						|
default handler that produces an error message and quits.
 | 
						|
You may also generate traps yourself.
 | 
						|
.IP trap 10
 | 
						|
Trap generates the trap passed as argument (0..252).
 | 
						|
The trap numbers 128..252 may be used freely. The others are reserved.
 | 
						|
.PD 0
 | 
						|
.IP encaps
 | 
						|
Encapsulate the execution of \fIp\fP with the trap handler \fIq\fP.
 | 
						|
Encaps replaces the previous trap handler by \fIq\fP, calls \fIp\fP
 | 
						|
and restores
 | 
						|
the previous handler when \fIp\fP returns.
 | 
						|
If, during the execution of \fIp\fP, a trap occurs,
 | 
						|
then \fIq\fP is called with the trap number as parameter.
 | 
						|
For the duration of \fIq\fP the previous trap handler is restored, so that
 | 
						|
you may handle only some of the errors in \fIq\fP. All the other errors must
 | 
						|
then be raised again by a call to \fItrap\fP.
 | 
						|
.br
 | 
						|
Encapsulations may be nested: you may encapsulate a procedure while executing
 | 
						|
an encapsulated routine.
 | 
						|
.br
 | 
						|
Jumping out of an encapsulated procedure (non-local goto) is dangerous,
 | 
						|
because the previous trap handler must be restored.
 | 
						|
Therefore, you may only jump out of procedure \fIp\fP from inside \fIq\fP and
 | 
						|
you may only jump out of one level of encapsulation.
 | 
						|
If you want to exit several levels of encapsulation, use traps.
 | 
						|
See pc_prlib(7) for lists of trap numbers
 | 
						|
for EM machine errors and Pascal run time system errors.
 | 
						|
Note that \fIp\fP may not have parameters.
 | 
						|
.PD
 | 
						|
.PP
 | 
						|
.RE
 | 
						|
UNIX system calls:
 | 
						|
.RS
 | 
						|
The routines of this category require global variables or routines
 | 
						|
of the monitor library libmon(7).
 | 
						|
.IP uread 10
 | 
						|
Equal to the read system call.
 | 
						|
Its normal name is blocked by the standard Pascal routine read.
 | 
						|
.PD 0
 | 
						|
.IP uwrite
 | 
						|
As above but for write(2).
 | 
						|
.IP perrno
 | 
						|
Because external data references are not possible in Pascal,
 | 
						|
this routine returns the global variable errno, indicating the result of
 | 
						|
the last system call.
 | 
						|
.PD
 | 
						|
.PP
 | 
						|
.RE
 | 
						|
Miscellaneous:
 | 
						|
.RS
 | 
						|
.IP clock 10
 | 
						|
Return the number of ticks of user and system time consumed by the program.
 | 
						|
.PD
 | 
						|
.PP
 | 
						|
.RE
 | 
						|
The following program presents an example of how these routines can be used.
 | 
						|
This program is equivalent to the UNIX command cat(1).
 | 
						|
.nf
 | 
						|
{$c+}
 | 
						|
program cat(input,inp,output);
 | 
						|
var	inp:text;
 | 
						|
	s:string;
 | 
						|
 | 
						|
function argc:integer; extern;
 | 
						|
function argv(i:integer):string; extern;
 | 
						|
procedure argshift; extern;
 | 
						|
function strlen(s:string):integer; extern;
 | 
						|
function strfetch(s:string; i:integer):char; extern;
 | 
						|
 | 
						|
procedure copy(var fi:text);
 | 
						|
var c:char;
 | 
						|
begin reset(fi);
 | 
						|
  while not eof(fi) do
 | 
						|
  begin
 | 
						|
    while not eoln(fi) do
 | 
						|
    begin
 | 
						|
      read(fi,c);
 | 
						|
      write(c)
 | 
						|
    end;
 | 
						|
    readln(fi);
 | 
						|
    writeln
 | 
						|
  end
 | 
						|
end;
 | 
						|
 | 
						|
begin  {main}
 | 
						|
  if argc = 1 then
 | 
						|
    	copy(input)
 | 
						|
  else
 | 
						|
    repeat
 | 
						|
      s := argv(1);
 | 
						|
      if (strlen(s) = 1) and (strfetch(s,1) = '-')
 | 
						|
      then copy(input)
 | 
						|
      else copy(inp);
 | 
						|
      argshift;
 | 
						|
    until argc <= 1;
 | 
						|
end.
 | 
						|
.fi
 | 
						|
.PP
 | 
						|
Another example gives some idea of the way to manage trap handling:
 | 
						|
.nf
 | 
						|
 | 
						|
program bigreal(output);
 | 
						|
const EFOVFL=4;
 | 
						|
var trapped:boolean;
 | 
						|
 | 
						|
procedure encaps(procedure p; procedure q(n:integer)); extern;
 | 
						|
procedure trap(n:integer); extern;
 | 
						|
 | 
						|
procedure traphandler(n:integer);
 | 
						|
begin if n=EFOVFL then trapped:=true else trap(n) end;
 | 
						|
 | 
						|
procedure work;
 | 
						|
var i,j:real;
 | 
						|
begin trapped:=false; i:=1;
 | 
						|
  while not trapped do
 | 
						|
    begin j:=i; i:=i*2 end;
 | 
						|
  writeln('bigreal = ',j);
 | 
						|
end;
 | 
						|
 | 
						|
begin
 | 
						|
  encaps(work,traphandler);
 | 
						|
end.
 | 
						|
.fi
 | 
						|
.SH FILES
 | 
						|
.IP ~em/lib/*/tail_pc 20
 | 
						|
.PD
 | 
						|
.SH "SEE ALSO"
 | 
						|
ack(1), pc_pem(6), pc_prlib(7), libmon(7)
 | 
						|
.SH DIAGNOSTICS
 | 
						|
Two routines may cause fatal error messages to be generated.
 | 
						|
These are:
 | 
						|
.IP pcreat 10
 | 
						|
Rewrite error (trap 77) if the file cannot be created.
 | 
						|
.PD 0
 | 
						|
.IP popen
 | 
						|
Reset error (trap 76) if the file cannot be opened for reading
 | 
						|
.PD
 | 
						|
.SH AUTHOR
 | 
						|
Johan Stevenson, Vrije Universiteit.
 | 
						|
.br
 | 
						|
encaps: Ed Keizer, Vrije Universiteit.
 |