Bitte rufen Sie den Interpreter 'boiler' ohne Optionen auf, um sich
einen Ueberblick der Optionen zu verschaffen.

BOIL (Brunnis Own Interpreter Language) ist stark an C angelehnt.
Unterschiede gegenueber C:

1.	Datentypen
---------------------------------------------------------------------------

Nur die Datentypen long,unsigned long,double,string und void sind erlaubt
(insb. keine Zeiger oder andere abgeleitete Datentypen). long, unsigned long
und double sind nach der Deklaration immer 0 und string undefiniert (analog
zu (char*) 0 in C). Zuweisungen, Funktionsargumente und Rueckgabewerte von
Funktionen mit undefinierten Strings sind moeglich, aber keine Ausdruecke.
Ob ein String undefiniert ist, kann nur mit der Library-Funktion defined()
abgefragt werden.

2.	Konversionen und Casten
---------------------------------------------------------------------------   

Automatische Konversionen zwischen den Datentypen finden nur in folgenden
Faellen statt:

-Zwischen long und unsigned long
-Von long oder unsigned long nach double

Bei operatoren und Funktionen ist darauf zu achten, welche Typen erlaubt sind,
ob eine implizite Konversion erfolgt, ob eine explizite Konversion (cast) mit
Datenverlust noetig ist und welche Typen zurueckgegeben werden. Casten ist
zwischen allen Typen moeglich. Beispiel: printf((string) 2.1);

3.	Fehlende Operatoren
---------------------------------------------------------------------------   

-Alle Zuweisungsoperatoren ausser '='
-Kommaoperator ','
-Konditionaloperator '?:'
-sizeof
-Einstelliger Operator '+'

4.	Kompilerdirektiven
---------------------------------------------------------------------------   

Es existiert nur '#include datei', wobei der Dateiname nicht durch '<', '>'
oder '"' eingeschlossen sein darf. Bei Verwendung von #include muss der
Interpreter mit der option '-r Zahl' aufgerufen werden, die die maximale
"Rekursionstiefe" des Parsers hinsichtlich #include angibt (default 0).

5.	Programmstruktur
---------------------------------------------------------------------------   

Eine Funktion main() muss nicht definiert werden. Feder Anweisungsblock ist
ein gueltiges Programm. beispiel:

{ printf("Hello World\n"); }

Wird der Code in ASCII/HTML eingebettet (Option -h) sieht das ganze z.B.
so aus:

Content-Type: text/html

<HTML>
<HEAD>
<TITLE>
Test
</TITLE>
</HEAD>
<BODY>
<? printf("Hello"); ?> <? printf("World"); ?>
</BODY>
</HTML>

Damit das ganze als CGI-Skript funktioniert, muss die erste Zeile

#!/pfad/zu/boiler -hi

lauten. die Option i steht fuer das Ignorieren der ersten Zeile, die der
Parser nicht schlucken wuerde.

6.	Bezeichner fuer Variablen und Funktionen
---------------------------------------------------------------------------   

Variablen und Funktionen koennen ueberall definiert werden. Der
Gueltigkeitsbereich ist der jeweilige Anweisungsblock der Definition.

Jeder Bezeichner einer Variable oder Funktion kann auch ein Ausdruck der Form
[ String-Ausdruck ] sein, wodurch ein Bezeichner entsprechenden Namens
referenziert wird. Beispiel:

{
 string s="printf";
 [s]("Hello World\n");

 s="Hello World\n";

 string [s]=s;
 printf([s]);

 void [s](string a) { printf(a); return; };
 [s](s);

 s="exit";
 [s]();
}

Bei einer Definition wird die entsprechende Variable oder Funktion im
gleichen Anweisungsblock angelegt und ist somit nur in diesem gueltig. Dies
ist nicht immer wuenschenswert, weswegen bei einer Referenzierung ueber
einen String-Ausdruck ein zweiter Long-Ausdruck angegeben werden kann, der
fuer den Gueltigkeitsbereich des Bezeichners relativ zum aktuellen
Anweisungsblock steht. '0' bedeutet aktueller Block, '1' ergibt den
uebergeordneten Block, '2' den Block darueber u.s.w. eine negative Zahl
steht fuer den Startblock - dient also zur Referenzierung "globaler"
Bezeichner, die Zahl -2 steht fuer den Systemblock, der von allen (auch
abgekapselten) Programmteilen verwendet werden kann. Im Systemblock finden sich
u.A. die Systemfunktionen und die Systemvariablen wie error und perror.

Der Aufruf von:

{
 string s="startblock\n";
 {
  string s="subblock 1\n";
  {
   string s="subblock 2\n";
   printf(s+["s",1]+["s",2]+["s",-1]);
  }
 }
}

ergibt die Ausgabe:

subblock 2
subblock 1
startblock
startblock

7.      Accounting
---------------------------------------------------------------------------

Es gibt vier Accounting-Typen:

0       Interne Rekursionen
1       Variablen
2       Funktionen
3       Aufrufe von Library-Funktionen

Die internen Rekursionen sind nicht Rekursionen des BOIL-Programms, es sind die
vielen kleinen Subfunktionsaufrufe die der Interpreter macht um eine Anweisung
auszufuehren. Wenn der Interpreter einen Subfunktionsaufruf mach, eine Variable
oder Funktion erzeugt oder eine Library-Funktion aufruft, erhoeht er die
entsprechenden Accouting-Zaehler. Wenn eine Subfunktion beeendet, eine Variable
oder Funktion geloescht oder eine Library-Funktion beendet wird, werden die
entsprechenden Accounting-Zaehler dekrementiert. Das Accounting wird am besten
anhand eines kleinen Beispiels deutlich (examples/accounting):

{
 for (unsigned long i=0;i!=10;i++) { printf("."); }
 printf("\n");
}

Wird dies aufgerufen mit

boiler -z on -s -a 0:0:0:0 -a 1:0:0:0 -a 2:0:0:0 -a 3:0:0:0 accounting

erhalten wir die Ausgabe:

..........
accounting-stats:
-----------------
type 0: sum: 169 (0 max) actual: 0 (0 max) time: 0.017135 (0 max)
type 1: sum: 1 (0 max) actual: 0 (0 max) time: 0.016029 (0 max)
type 2: sum: 0 (0 max) actual: 0 (0 max) time: 0.000000 (0 max)
type 3: sum: 11 (0 max) actual: 0 (0 max) time: 0.001578 (0 max)

Das bedeutet:
-Der Interpreter brauchte 169 Subfunktionsaufrufe in 0.017 Sekunden um das
 Programm auszufuehren.
-Eine Variable wurde definiert
-Keine Funktion wurde definiert
-Elf Aufrufe von printf wurden in 0.001 Sekunden gehandhabt

Es hat keinen Sinn Zeitlimits fuer Variablen und Funktionen zu setzen, bei
Library-Funktionsaufrufen und internen Rekursionen dagegen ist es sinnvoll.
Limits fuer die aktuellen Zaehler von Library-Funktionsaufrufen haben keinen
Sinn da der Interpreter maximal eine Library-Funktion zu jedem Zeitpunkt
ausfuehrt. Der Unterschied zwischen akkumulierten und aktuellen Instanzen ist
einfach: Werden zum Beispiel die akkumulierten Instanzen der internen
Rekursionen begrenzt, ist damit die "Laufzeit" des Programms begrenzt. Werden
dagegen die aktuellen Instanzen begrenzt, ist die Rekursionstiefe begrenzt.

8.	Neue Optionen fuer Funktionsbloecke
---------------------------------------------------------------------------   

Bei jeder Funktionsdeklaration kann vor die Liste der Argumente ein String-
Ausdruck gesetzt werden, der eine Optionsliste wie beim Aufruf des
Interpreters enthalten muss:

void print("-z off",string s) { printf(s); return; }

In diesem Beispiel werden Aufrufe der Funktion print vom Zeit-Accounting
ausgenommen.

Sobald sich der Interpreter beim Ausfuehren der Funktion befindet, gelten die
veraenderten Optionen. Hierbei gelten Folgende Regeln:

-Sobald die Option -a verwendet wurde, erhaelt die Funktion ein separates
 Accounting, das bei jedem Aufruf zurueckgesetzt wird (Ausnahme: Rekursion)

-Sobald die Option -x verwendet wurde, sind die bisherigen Verbote fuer
 Funktionsaufrufe ungueltig

Folgende Optionen koennen bei einer Funktionsdeklaration nicht angegeben
werden: -m -d -s

Folgende sind zusaetzlich moeglich:

-p Gibt ein Passwort fuer den externen Aufruf der Funktion an (Siehe weiter
   unten).

-l Loescht die Liste aller Handles fuer Dateien, Datenbankverbindungen, etc.
   so dass die Funktion nicht auf diese zugreifen kann, ohne sie vorher zu
   oeffnen.

-c typ:handle Uebergibt ein Handle (nur nach -l moeglich). Typen:
   1 Streams
   2 Postgres-Verbindungen
   3 Postgres-Abfragen
   4 RPC-Server
   5 RPC-Client
   6 Sockets
   7 Verzeichnisse
   8 msql-Verbindungen
   9 msql-Abfragen
   10 mysql-Verbindungen
   11 mysql-Abfragen

-f Flags. Die angegebene Zahl regelt die Berechtigungen des Funktionsrumpfes
   beim Zugriff auf uebergeordnete Objekte:

   1	Funktionsaufrufe sind gestattet
   2	Zugriff auf Variablen ist gestattet (lesend und schreibend)
   4	Variablen koennen deklariert werden

   ist die Zahl 0, so ist der Funktionsrumpf bis auf die Argumente und den
   Rueckgabewert vom restlichen Programm abgekapselt. Sofern nicht -l
   angegeben wurde koennen aber weiterhin die Handles des rufenden Programms
   benutzt werden.

Eine Zugriffsbeschraenkung kann somit durch die Deklaration von Funktionen
mit Optionsstrings umgangen werden, wenn diese nicht mit "-o off" ausgeschaltet
wurden.

9.	Zur Laufzeit geparste Programmteile
---------------------------------------------------------------------------   

Bei einer Funktionsdeklaration kann anstatt des Rumpfes auch ein Ausdruck der
Form eval(code) angegeben werden. Der String-Ausdruck code muss ein korrektes
BOIL-Programm sein und wird zum Funktionsrumpf. Parser-Optionen koennen mit
Hilfe eines Optionsstrings angegeben werden. Beispiel:

void print(string a) eval("{ printf(a); return; }")

10.	Laufzeitfehler innerhalb von Funktionsaufrufen
---------------------------------------------------------------------------   

Laufzeitfehler oder Aufrufe von exit() innerhalb von Funktionsaufrufen
fuehren normalerweise zum Abbruch des Programms, was nicht immer
wuenschenswert ist (z.b. bei Funktionen, die waehrend der Laufzeit geparst
wurden). Durch Klammerung des Funktionsnamens beim Aufruf kann dies verhindert
werden. Zudem werden auf diese Art Accountinginformationen eines 
Funktionsrumpfes mit separatem Accounting dem aufrufenden Programm
zugaenglich. Ein Funktionsaufruf der Form

	(funktion)(argumente)

Setzt folgende Variablen im aktuellen Anweisungsblock:

unsigned long func_status		Status
					1=OK
					2=continue-Anweisung
					3=break-Anweisung
					4=return-Anweisung
					5=exit-Anweisung oder Laufzeitfehler
 
string func_error			Fehlermeldung

unsigned long func_error_line		Zeile des Fehlers

Fuer jeden Accounting-Typ wird gesetzt:

string func_acc_<typ>			X1:X2:X3
					X1=Akkumulierte Instanzen
					X2=Aktuelle Instanzen
					X3=Instanzlaufzeit Sekunden
					X4=Instanzlaufzeit Mikrosekunden

11	Externe Funktionen
---------------------------------------------------------------------------   

Die verteilte Programmierung wird von BOIL mit Hilfe der Remote Procedure Calls
(RPC) unterstuetzt. Der Aufruf einer Funktion kann zur Ausfuehrung eines
im gleichen Programm angegebenen Funktionsrumpfes fuehren oder - voellig
transparent - ueber einen RPC von einem entfernten BOIL-Server verarbeitet
werden.

Auf der Client-Seite werden hierfuer externe Funktionen deklariert. Der
Funktionsrumpf ist ein Ausdruck der Form

 external(Client-Handle,Funktionsname,Passwort)
z.B.:

 void print external(clnt,"print","geheim")

Die Client-Handles werden mit Hilfe der Library-Funktionen
clnt_create(host,rpc-programmnummer,version,protokoll) und clnt_destroy(handle)
verwaltet.

Auf der Server-Seite muss mit der Library-Funktion
svc_register(rpc-programmnummer,version,protokoll,fork,socket) ein oder mehrere
RPC-Server angemeldet werden. Mit der Funktion
svc_run(timeout_sek,timeout_usek) koennen dann Aufrufe entgegengenommen
werden. Ist fork=1, so wird vor dem Ausfuehren der aufgerufenen Funktion ein
Kindprozess erzeugt, so dass der Server fuer weitere Aufrufe zur Verfuegung
steht. Nachteil: Veraenderungen in den Datenstrukturen des Serverprogramms
gehen verloren. ACHTUNG: wenn svc_run zurueckkehrt koennen auch mehrere
Prozesse gestartet worden sein. Sofern eine globale Funktion
void fork_handler(long pid) definiert ist, wird sie nach der Erzeugung des
Kinprozesses mit dessen PID aufgerufen. Es koennen nur solche Funktionen des
Servers Aufgerufen werden, bei denen mit "-p" ein Passwort angegeben wurde.
Mit der Funktion svc_unregister(handle) werden die angemeldeten RPC-Server
wieder abgemeldet. 

Das Ende eines Kindprozesses wird vom Interpreter defaultmaessig ignoriert.
Dies kann mit dem Aufruf sigcld(1) veraendert werden, so dass das Ende jedes
Kindprozesses mit der Funktion long waidpid() abgefangen werden muss (ansonsten
entstehen Zombieprozesse).

Ein Beispiel fuer den Aufbau von Server und Clients findet sich im Verzeichnis
examples/rpc.

12.	Library-Funktionen
---------------------------------------------------------------------------   

Tritt ein Fehler, EOF, etc. innerhalb einer Library-Funktion auf, wird die
Systemvariable 'error' auf 1 gesetzt (und behaelt diesen Wert, falls
nicht zurueckgesetzt wird). In perror steht dann ein entsprechender
Fehlertext. error und perror koennen auch von einem Cast von string zu long
oder double gesetzt werden. Bei Funktionen mit zweideutigem Rueckgabewert
empfiehlt sich die Abfrage von error (z.b. ist der Rueckgabewert von strlen()
bei einem undefinierten String 0).

Folgende Library-Funktionen wurden bis jetzt implementiert (R steht fuer
Rueckgabewert):

12.1	Standardfunktionen
---------------------------------------------------------------------------   

        unsigned long printf(string a)

R 0             a ist Leer oder Fehler
R               Anzahl der ausgegebenen Zeichen

        void sleep(unsigned long time)

time Sekunden warten.

        string getenv(string)

Eine Umgebungsvariable einlesen.

R undefiniert   Fehler
R               Inhalt der Umgebungsvariable

	unsigned long setenv(string name,string value,unsigned long overwrite)

Eine Umgebungsvariable setzen.

R 0		Fehler
R 1		OK

        void srandom(unsigned long seed)

Siehe 'man srandom'. Die Anzahl der Mikrosekunden beim Start des Interpreters
modulo 65536 bestimmt den Defaultseed.

        long random()

Siehe 'man random'.

	string crypt(string key)

Ein Passwort verschluesseln. Das im Gegensatz zur libc-Funktion fehlende
Argument 'salt' wird mit Hilfe von random() erzeugt.

R undefiniert	Fehler
R		Verschluesseltes Passwort

	long waitpid()

Auf das Ende eines Kindprozesses warten.

R -1		Fehler
R 0		Kein Kindprozess wurde beendet
R		PID des beendeten Kindes

	void sigcld(unsigned long flag)

Signal-Handling fuer SIGCLD umstellen:
flag==0		Ignorieren,defaulteinstellung
flag==1		Eigener Handler. Auf die Kinder muss mit waidpid() gewartet
		werden

	long getpid()

Eigene PID bestimmen.

R -1		Fehler
R		PID

	long system(string cmd)

Ein Shell-Kommando aufrufen.

R -1		Fehler
R		Exit-Code

12.2    Zeit
---------------------------------------------------------------------------

        unsigned long time()

R               Aktuelle Zeit

	unsigned long mktime(unsigned long year,
			     unsigned long month,
                             unsigned long day,
                             unsigned long hour,
                             unsigned long minute,
                             unsigned long second)

Konkrete Uhrzeit in Sekunden seit dem 1. Januar 1970 umrechnen.

R 0		Fehler oder 1. Jan 1970 00:00:00
R		Anzahl der Sekunden

	string strftime(string format,unsigned long seconds)

Anzahl der Sekunden in einen formatierten Datumsstring umwandeln. Es koennen
die gleichen Metazeichen wie bei 'man strftime' angegeben werden.

R undefiniert	Fehler
R		Datumsstring

12.3    Dateien und Verzeichnisse
---------------------------------------------------------------------------  

	unsigned long fileatime(string path)

atime eines Dateisystemobjektes ausgeben.

R 0		Fehler
R		atime

        unsigned long filemtime(string path)

mtime eines Dateisystemobjektes ausgeben.

R 0             Fehler
R               mtime 

	unsigned long unlink(string path)

Datei entfernen.

R 0		Fehler
R 1		OK

	string tmpnam()

Eindeutigen Dateinamen fuer eine temporaere Datei erzeugen.

R undefiniert	Fehler
R		Dateiname

	long opendir(string path)

Ein Verzeichnis oeffnen.

R -1		Fehler
R		Handle

	string readdir(long handle)

Naechsten Dateinamen holen ("." und ".." werden ebenfalls ausgegeben).

R undefiniert	Fehler
R		Dateiname

	unsigned long closedir(long handle)

Ein Verzeichnis schliessen.

R 0		Fehler
R 1		OK

	unsigned long mkdir(string path)

Ein Verzeichnis erzeugen.

R 0		Fehler
R 1		OK

        unsigned long rmdir(string path)

Ein Verzeichnis loeschen. Vorher muessen alle enthaltenen Dateien und
Verzeichnissse geloescht werden.

R 0             Fehler
R 1             OK

	unsigned long rename(string oldpath,string newpath)

Eine Datei umbenennen.

R 0             Fehler
R 1             OK

12.4    Funktionen fuer CGI-Skripten
---------------------------------------------------------------------------

	unsigned long cgiwrap(string path,string postdata,unsigned long head)

Spezialfunktion fuer eigene Zwecke.
Gibt ein Dokument zzgl. Content-Typ aus bzw. startet ein CGI-Skript, falls
file die Endung .cgi hat:

gif	image/gif
jpg	image/jpeg
jpeg	image/jpeg
jpe	image/jpeg
html	text/html
htm	text/html
cgi	Content-type wird vom aufgerufenen CGI-Skript bestimmt
sonst	application/octet-stream

Ist head==0, so wird "Content-type: text/html" nicht ausgegeben.
Hat die Datei keine Endung und ist ein Verzeichnis, so wird versucht
index.html bzw. index.htm in diesem auszugeben. Ansonsten Ergibt die Funktion
einen Fehler.

R 0		Fehler
R 1		OK

        unsigned long getpost()

Liest via POST (CGI) uebermittelte Daten in Variablen des aktuellen Blocks ein.

R 0             Fehler
R 1             OK

        unsigned long postdata(string postdata)

Liest via POST/GET (CGI) uebermittelte Daten in Variablen des aktuellen Blocks
ein. Die Daten werden als Argument uebergeben und mussen vorher aus der
Umgebungsvariable QUERY_STRING oder von stdin gelesen worden sein.

R 0             Fehler
R 1             OK

	string file_upload(long maxsize)

Liest via POST (CGI) uebermittelte Daten mit Encoding-Type
'multipart/form-data' ein. Derartige Formulare werden vor allem fuer
File-Uploads verwendet (<input type="file">). Es kann nur eine einzige Datei
uebertragen werden, deren temporaerer Filename der Rueckgabewert ist. Sonstige
POST-Daten werden als Variablen des aktuellen Blocks angelegt.

R undefiniert	Fehler
R		Dateiname

	string htmlenc(string data)

Diverse HTML-Metazeichen in data werden im Format &#%Zahl; geschuetzt, so dass
sie nicht als HTML interpretiert werden ('<','>','"','\','&').

R undefiniert	Fehler
R		Neue Zeichenkette

	unsigned long phtmlenc(string data)

Wie htmlenc, nur wird das Ergebnis gleich mit printf() ausgegeben.

R 0		Fehler
R 1		OK

	string fullhtmlenc(string data)

Jedes nicht alphanumerische Zeichen in data wird im Format %Zahl geschuetzt,
was beim Zusammenbau von POST- bzw. GET-Daten in der Default-Kodierung
'application/x-www-form-urlencoded' nuetzlich ist.

R undefiniert	Fehler
R		Neue Zeichenkette

12.5    Funktionen fuer BOIL-Interna
---------------------------------------------------------------------------

        void exit()

Sofortiger Programmabbruch.

        unsigned long isset(string)

Prueft auf Vorhandensein einer Variable.

R 0             Variable nicht vorhanden oder Fehler
R 1             Variable vorhanden

        unsigned long isfunc(string)

Prueft auf Vorhandensein einer Funktion.

R 0             Funktion nicht vorhanden oder Fehler
R 1             Funktion vorhanden

        unsigned long deletefunc(string name,long block)

Eine Funktion loeschen. Systemfunktionen koennen nicht geloescht werden.

R 0             Fehler
R 1             OK

        unsigned long deletevar(string name,long block)

Eine Variable loeschen. Systemvariablen koennen nicht geloescht werden.

R 0             Fehler
R 1             OK

        unsigned long parse(string code,string options)

Parsen des BOIL-Programms in code.

R 0             Fehler
R 1             OK

12.6    Locking
---------------------------------------------------------------------------

        long do_lock(string file)

Ein Lockfile fuer die Datei file (<file>.lck) anlegen.

R -1            Fehler
R 0             Bereits gelockt
R 1             OK

        long do_unlock(string file)

Einen Lock wieder freigeben.

R -1            Fehler
R 1             OK

12.7    Strings
---------------------------------------------------------------------------   

        unsigned long defined(string a)

R 0             String a undefiniert
R 1             String a definiert

        string strstr(string a,string needle)

Needle in a suchen und diesen String mit dem rest von a zurueckgeben.

R undefiniert   Fehler (z.B. needle nicht gefunden)
R               needle mit Rest von a

        string strtok(string a,string delim)

a entsprechend der angegebenen Trennzeichen aufteilen. Das 2. bis n. Token
erhaelt man ueber die Funktion token(). Als Token wird eine nichtleere
Zeichenkette aus Zeichen, die nicht in delim vorkommen, verstanden. Sie muss
mit 0 enden oder von einem Zeichen aus tokens gefolgt werden.

R undefiniert   Fehler (z.B. Token nicht gefunden)
R               1. Token

        string token(string delim)

Weitere Tokens extrahieren.

R undefiniert   Fehler (z.B. Token nicht gefunden)
R               Token

        string strtok_esc(string a,string delim)

Wie strtok, nur werden durch '\' geschuetzte Zeichen nicht fuer die Trennung
herangezogen.

R undefiniert   Fehler (z.B. Token nicht gefunden)
R               1. Token

        string token_esc(string delim)

R undefiniert   Fehler (z.B. Token nicht gefunden)
R               Token 

        string strtolower(string a)

Grossbuchstaben in Kleinbuchstaben.

R undefiniert   Fehler
R               Ergebnis

        string strtoupper(string a)

Kleinbuchstaben in Grossbuchstaben.

R undefiniert   Fehler
R               Ergebnis

        string substr(string a,unsigned long start,unsigned long length)

Eine Zeichenkette aus a extrahieren. Start beginnt bei 0, Length bei 1.

R undefiniert   Fehler (z.B. Startposition zu hoch)
R               Ergebnis

        unsigned long strlen(string a)

Laenge der Zeichenkette a.

R 0             Fehler oder Zeichenkette leer
R               Laenge

        string escape(string a,string escapes)

Die in escapes angegebenen Metazeichen durch \ schuetzen.

R undefiniert   Fehler
R               Geschuetzter String

        string unescape(string a)

Schutz von Metazeichen entfernen.

R undefiniert   Fehler
R               Ungeschuetzter String

        string escape1(string a)

Zeilenumbruch, Wagenruecklauf, vertikalen Tabulator und Seitenvorschub
durch "\n","\r","\v" und "\f" ersetzen.

R undefiniert   Fehler
R               Geschuetzter String

        string unescape1(string a)

escape1() rueckgaengig machen.

R undefiniert   Fehler
R               Ungeschuetzter String

	string textfile(string path)

Eine Textdatei einlesen.

R undefiniert	Fehler
R		Textdatei als Zeichenkette

	unsigned long getchar(string a,unsigned long pos)

Ein Zeichen aus einer Zeichenkette extrahieren. pos beginnt bei 0.

R 0		Fehler
R		Zeichen

        string sql_escape(string data)
        
Metazeichen von SQL (''','"','\') durch '\' schuetzen.

R undefiniert   Fehler
R               Geschuetzter String


12.8	Streams
---------------------------------------------------------------------------   

        long fopen(string filename,string mode)

Filename oeffnen und Handle zurueckgeben. Filename "STDIN" bzw. "STDOUT" kann
fuer die entsprechenden Streams angegeben werden.

R -1            Fehler
R               Handle

        long popen(string command,string mode)

Kommando ausfuehren und Handle zum Lesen/Schreiben der Ausgabe/Eingabe
zurueckgeben.

R -1            Fehler
R               Handle

	unsigned long exec(string path,string argname,
			   string inname,string outname)

Das Kommando 'path' mit der Funktion exec() aufrufen. Kommandozeilenargumente
werden mit Variablen der Form argname_Zaehler uebergeben. argname ist der
Basisname, der Zaehler faengt bei 0 an und hoert auf wenn die entsprechende
Stringvariable undefiniert ist. inname und outname sind die Namen der
long-Variablen in denen die Stream-Handles zum Schreiben der Eingabe und Lesen
der Ausgabe gespeichert werden. Anwendungsbeispiel:

 string arg_0="sendmail",arg_1="-bm",arg_2=bm,arg_3;
 long in,out;
 exec("/usr/sbin/sendmail","arg_","in","out");

R 0		Fehler
R 1		OK

        long feof(long handle)

R -1            Fehler
R 0             Kein EOF
R 1             EOF

        string fgets(long handle)

R undefiniert   Fehler oder EOF
R               Eingelesene Zeile

        unsigned long fputs(long handle,string data)

R 0             Fehler
R 1             OK

        unsigned long fclose(long handle)

R 0             Fehler
R 1             OK

        long pclose(long handle)

R -1            Fehler
R               Exit-Code des Programms

	unsigned long fflush(long handle)

R 0		Fehler
R 1		OK

	unsigned long setoutstream(long handle)

Der Ausgabestream (printf,?> <?,etc.) wird gesetzt. Voreingestellt ist stdout.

R 0		Fehler
R 1		OK

12.9	Postgres
---------------------------------------------------------------------------   

        unsigned long pg_close(long connection)

Verbindung zu einer Postgres-Datenbank schliessen.

R 0             Fehler
R 1             OK

        long pg_connect(string host,string port,string options,string tty,
                        string dbname)

Verbindung zu einer Postgres-Datenbank oeffnen. Es wird ein Handle fuer
die Verbindung zurueckgegeben.

R -1            Fehler
R               Handle

        long pg_exec(long connection,string query)

Postgres-Befehl ausfuehren. Es wird ein Handle fuer das Ergebnis
zurueckgegeben.

R -1            Fehler
R               Handle

        unsigned long pg_freeresult(long result)

Ergebnis eines Postgres-Befehls loeschen.

R 0             Fehler
R 1             OK

        unsigned long pg_numfields(long result)

Anzahl der Felder eines Ergebnisses.

R 0             Fehler oder 0 Felder
R               Anzahl

        unsigned long pg_numrows(long result)

Anzahl der Datensaetze eines Ergebnisses.

R 0             Fehler oder 0 Datensaetze
R               Anzahl

        string pg_fieldname(long result,unsigned long field)

Den Namen eines Feldes bestimmen.

R undefiniert   Fehler
R               Name

        string pg_fieldtype(long result,unsigned long field)

Den Typ eines Feldes bestimmen.   

R undefiniert   Fehler
R               Typ

        string pg_result(long result,unsigned long row,unsigned long field)

Den Wert eines Feldes auslesen.

R undefiniert   Fehler
R               Wert

12.10	msql
---------------------------------------------------------------------------

        unsigned long msql_close(long connection)

Verbindung zu einer Datenbank schliessen.

R 0             Fehler
R 1             OK

        long msql_connect(string host)

Verbindung zu einer Datenbank oeffnen. Es wird ein Handle fuer
die Verbindung zurueckgegeben.

R -1            Fehler
R               Handle

        unsigned long msql_selectdb(long connection,string database)

Datenbank auswaehlen.

R 0		Fehler
R 1		OK

        long msql_exec(long connection,string query)

SQL-Befehl ausfuehren. Es wird ein Handle fuer das Ergebnis
zurueckgegeben.

R -1            Fehler
R               Handle

        unsigned long msql_freeresult(long result)

Ergebnis eines Befehls loeschen.

R 0             Fehler
R 1             OK

        unsigned long msql_numfields(long result)

Anzahl der Felder eines Ergebnisses.

R 0             Fehler oder 0 Felder
R               Anzahl

        unsigned long msql_numrows(long result)

Anzahl der Datensaetze eines Ergebnisses.

R 0             Fehler oder 0 Datensaetze
R               Anzahl

        string msql_fieldname(long result,unsigned long field)

Den Namen eines Feldes bestimmen.

R undefiniert   Fehler
R               Name

        long msql_fieldtype(long result,unsigned long field)

Den Typ eines Feldes bestimmen.   

R -1	        Fehler
R               Typ

        string msql_result(long result,unsigned long row,unsigned long field)

Den Wert eines Feldes auslesen.

R undefiniert   Fehler
R               Wert

12.11	mysql
---------------------------------------------------------------------------

Entsprechend den msql-Funktionen mit Prefix "mysql_". mysql_connect() hat
allerdings drei Argumente:

	long mysql_connect(string host,string user,string password)

12.12	Sockets
---------------------------------------------------------------------------

	long makesock(string host,unsigned long port,long type,long protocol)

socket() und bind() aufrufen. Ist host=="" so wird an jede IP-Adresse des
Systems gebind()ed.

R -1		Fehler
R		Socket-Handle

	unsigned long closesock(long handle)

Einen Socket wieder schliessen.

R 0		Fehler
R 1		OK


12.13	RPC
---------------------------------------------------------------------------   

        long clnt_create(string host,
                         unsigned long program,
                         unsigned long version,
                         string protocol,
                         long socket)

Ein Handle fuer externe Funktionsaufrufe gewinnen. Achtung: das Protokoll wird
als String ("udp","tcp") angegeben.

R -1            Fehler
R               Handle

        unsigned long clnt_destroy(long handle)

Ein Handle fuer externe Funktionsaufrufe freigeben.

R 0             Fehler
R 1             OK

        long svc_register(unsigned long program,
                          unsigned long version,
                          unsigned long protocol,
                          unsigned long fork)

Einen RPC-Server anmelden. Ist fork==1, so wird bei jedem Request ein
Kindprozess erzeugt.

R -1            Fehler
R               Handle

        long svc_run(unsigned long timeout_sec,
                     unsigned long timeout_usec)       

Einen oder mehrere RPC-Requests entgegennehmen. Findet bis zum Timeout kein
Request statt, kehrt die Funktion zurueck.

R -1            Fehler
R 0             Timeout
R 1		OK

        unsigned long svc_unregister(long handle)

Einen RPC-Server abmelden.

R 0             Fehler
R 1             OK

        unsigned long clnt_timeout(long handle,unsigned long seconds)

Setzt den Timeout fuer RPC-Requests (UDP und TCP).

R 0             Fehler
R 1             OK

        unsigned long clnt_udp_retry(long handle,unsigned long seconds)

Setzt den Retry-Timeout fuer RPC-Requests (nur UDP).

R 0             Fehler
R 1             OK

13.	BNF-Grammatik (fuer die, denen das weiterhilft)
---------------------------------------------------------------------------   

Zuerst die mehrbuchstabigen Tokens:

Token		Syntaktischer Wert
----------------------------------
LONG		long
UNSIGNED	unsigned
DOUBLE		double
STRING		string
VOID 		void
IF		if
ELSE		else
FOR		for
WHILE		while
DO		do
BREAK		break
CONTINUE	continue
RETURN		return
EVAL		eval
EXTERNAL	external
OR		||
AND		&&
EQUAL		==
NOTEQUAL	!=
LE		<=
GE		>=
SHIFTLEFT	<<
SHIFTRIGHT	>>
PLUSPLUS	++
MINUSMINUS	--

Die terminalen Tokens sind CONST (Konstante), NAME (Bezeichner), und
PRINT (Textausgabe bei Einbettung in ASCII/HTML).

Die nichtterminalen Tokens sind wie folgt definiert:

type:                           LONG
			|	UNSIGNED LONG
                        |       DOUBLE
                        |       STRING
                        |       VOID

reference:                      NAME
                        |       '[' expr ']'
                        |       '[' expr ',' expr ']'

expr_list:                      expr
                        |       expr_list ',' expr

function_call:                  reference '(' expr_list ')'
                        |       reference '(' ')'
			|	'(' reference ')' '(' expr_list ')'
			|	'(' reference ')' '(' ')'

expr:                           CONST
                        |       reference
                        |       function_call
                        |       reference '=' expr
                        |       reference PLUSPLUS
                        |       reference MINUSMINUS
                        |       PLUSPLUS reference
                        |       MINUSMINUS reference
                        |       '(' type ')' expr
                        |       '(' expr ')'
                        |       '-' expr
                        |       '~' expr
                        |       '!' expr
                        |       expr '*' expr
                        |       expr '/' expr
                        |       expr '%' expr
                        |       expr '+' expr
                        |       expr '-' expr
                        |       expr SHIFTLEFT expr
                        |       expr SHIFTRIGHT expr
                        |       expr '<' expr
                        |       expr '>' expr
                        |       expr LE expr
                        |       expr GE expr
                        |       expr EQUAL expr
                        |       expr NOTEQUAL expr
                        |       expr '&' expr
                        |       expr '^' expr
                        |       expr '|' expr
                        |       expr AND expr
                        |       expr OR expr

arg_list_entry:                 type NAME

arg_list:                       arg_list_entry
                        |       arg_list ',' arg_list_entry

function_dekl:                  type reference external_stmt
                        |       type reference '(' arg_list ')' block
                        |       type reference '(' ')' block
                        |       type reference '(' arg_list ')' eval_stmt
                        |       type reference '(' ')' eval_stmt
                        |       type reference '(' expr ',' arg_list ')' block
                        |       type reference '(' expr ')' block
                        |       type reference '(' expr ',' arg_list ')'
				eval_stmt
                        |       type reference '(' expr ')' eval_stmt

dekl_list_entry:                reference
                        |       reference '=' expr


dekl_list:                      dekl_list_entry
                        |       dekl_list ',' dekl_list_entry

variable_dekl:                  type dekl_list ';'

expr_stmt:                      ';'
                        |       expr ';'

choice_stmt:                    IF '(' expr ')' stmt
                        |       IF '(' expr ')' stmt ELSE stmt

loop_stmt:                      WHILE '(' expr ')' stmt
                        |       DO stmt WHILE '(' expr ')' ';'
                        |       FOR '(' stmt expr ';' expr ')' stmt
                        |       FOR '(' stmt ';' expr ')' stmt
                        |       FOR '(' stmt expr ';' ')' stmt
                        |       FOR '(' stmt ';' ')' stmt

jump_stmt:                      BREAK ';'
                        |       CONTINUE ';'
                        |       RETURN ';'
                        |       RETURN expr ';'

eval_stmt:              |       EVAL '(' expr ')'

external_stmt:                  EXTERNAL '(' expr ',' expr ',' expr ')'

stmt:                           variable_dekl
                        |       function_dekl
                        |       expr_stmt
                        |       block
                        |       choice_stmt
                        |       loop_stmt
                        |       jump_stmt
                        |       PRINT

stmt_list:                      stmt
                        |       stmt_list stmt

block:                          '{' '}'
                        |       '{' stmt_list '}'

