Disclaimer This is old documentation in the style of personal notes (actually as you can see it is really just a dump of a library). More up to date documentation exists in IO.doc and FILES.doc. However, some of the internals may be here and nowhere else, so it remains. This file documents the main.olb library that goes with the Mp language. The library is C compatible. It contains the same routine for register save and restore that Conroys C system used with his first distribution of the c compiler. The whitesmiths C compiler will of course work too, but the save and restore routines from that compilers runtime had to be extracted. Since the names ain't the same, the two compilers are totally compatible. There are two methods of writing programs using this library. One assumes there are two files opened (like C except no stderr) when the user starts at routine main. Main is called like a C program (main[argc,argv]) and has the arguments broken up. The second method is similar except that no opened files exist. The second method therefore is much smaller and more suited to priv'd programs that must be small. Neither method bothers with a standard error stream. (However, stderr allways goes to the terminal using lun 5). Note that the file version of the `main' program uses buffered i/o (i.e. calls FO$PEN). The following copies stdin to stdout character by character. PROGRAM testf function main[argc,argv] do forever r4 := getc[stdin] break if r4 lt 0 putc[stdout,r4] od .end The build file is: ______________________{ This module contains the | { transfer address. testf,testf/-sp = fmpm,testf,main/lb / stack=250 libr=fcsres:ro // The module fmpm is the File-MP-Main (note the capital letters) module. The short version which contains no file redirection is in MPM.mac and would replace the fmpm reference in line 1 of the build file. The document IO.DOC describes a cleaned up version of this stuff where the name of fmpm has been changed to jplstart and the library is jplclib.olb each existing in [1,1] on the fast disk. The supported command line features are: >file redirect output (create next higher version) >file redirect output to end of file >=file redirect output into file (or create if no file) "..." quoted arguments (for imbeded spaces, tabs etc) Here are the modules in Main.olb. Note that some of the below are intended for use only by other routines in the library. For example, fo$pen is used by bopen; bopen is the user in level interface. Of course if the user wished to use only the low level routines, that would be ok since the high level routines are simply users as far as the low level routines are concerned. However, more knowledge of internals is necessary to use the low level stuff. Low level routines are marked by a `**' under the module name. ALLOC Taken from the Conroy dynamic storage handlers ** entrys: ALLOC CFREE FREE FREESP MALLOC MFREE $$ALOC $$FREE $$MAVL $$MLIM $$MTOP - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BUF A scratch buffer used by printf ** entrys: $BUF$ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CAT string concatonate cat[s,a,b,c...,#0] char *s,*a,... returns pointer to end of string s. moveb[a,b,n] char *a,*b; int n: moves n chars from a to b returns pointer to next char in b (where a null usually goes) scopy[a,b] copies b into a - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CLOSE Close a file. ** entrys: CLOSE close[fdb] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CSAV Register save and restore (from Conroy C) ** entrys: $$CRET $$CSAV - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CSI Handles file name parsing using CSI routines entrys: CSIBLK CS.DIF CS.DVF CS.EQU CS.INP CS.MOR CS.NMF CS.OUT CS.WLD C.CMLD C.DEVD C.DIRD C.DSDS C.FILD C.MKW1 C.MKW2 C.SIZE C.STAT C.SWAD C.TYPR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DELIMS Default delimeters for the FIELDS routine entrys: BSLASH COLON COMMA DQUOTE LBRACE RBRACE SLASH SPACE SQUOTE TAB UPARRO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EQ String equate entrys: eq[a,b,n] char *a,*b; int n; compares n chars returns 0=not eq 1=is eq - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DIR Rsx directive handler entrys: $$DIR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FIELDS Break a string into fields entrys: FIELDS | fields - returns fields delimitted by lots of things | | input string and address of pointer array, returns n pointers and value n | | fields are separated by: | whitespace | comma | slash | back slash | colon | fields can be quoted as follows: | {...} | ^x...x | "..." | '...' | | the separators can be equated to garbage (-1 is ok) to cancel their | meanings. | | fields(string,vector) | char *string | int *vector returns number of fields | | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FO$PEN Open a file ** entrys: FO$PEN | | FO$PEN(fdb,filename,option) returns fcs success/error code | char *fdb,*filename,*option | fdb is a pointer to a real rsx file descripter block (fcs style) | filename is an asciz string file name | option is an char string of "r" for read | w write | u update | a append - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FRERRO Free dynamic storage error routine entrys: FRERRO - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GET Get a record from a file ** entrys: GET | | get(fdb,string,maxchars) | char *fdb,*string; int maxchars | uses get$ macro to read a line from file fdb, into the string | no more than maxchars are actually transfered. string is null terminated | (this ain't no good for binary files of course) | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INR input record i/o fdb lun 1 - a static fdb ** entrys: INR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - I2A Integer to ascii entrys: i2a[i,a] int i; char *a; converts i into ascii at a returns place to put the null if that is what is desired. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LTOA Long to Ascii used by printf ** entrys: $$LTOA - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LFIELD Little fields routine. Accepts only comma and space/tab as delimeters. Calling sequence is the same as fields. Needs no definitions of delimiters. entrys: lfield - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MULL Multiply routines ** entrys: MUL$L MUL$LI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OUTR Output fdb, lun 2 - a static fdb ** entrys: OUTR - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PUT Put asciz record. ** entrys: put[fdb,string] returns f.err status byte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SPRINT printf routine entrys: SPRINT | | sprint(buffer,string,p1,p2... | char *buffer,*string | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STR string routines entrys: EQ POS SEG VAL | | String routines - these are taken from basic-11 string functions. | These are of course C callable too. | | FUNCTION eq[a,b,n] | | compares string at a to string at b, compares n chars, | returns 0 if not equal, 1 if equal | | FUNCTION pos[in,of,st] | | finds position in 'in' of 'of' starting the search at the 'st'-th | character position in 'in'. returns 0 if not found else position. | e.g. pos["in-here","he",#1] returns 4 | | FUNCTION val[s,base] | | returns the binary value of the ascii string in s. Base may be 2-10. | may have a '-' sign for two's compliment of resultant value. | | FUNCTION SEG[s,in,from,too] | | extracts segment in 'in' positions 'from' to 'to'. Result into s | returns length of s | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STRLEN string length entrys: STRLEN length=strlen[s] char *s; int length; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SYSTEM spawning routine entrys: SYSTEM exstat=system[s] char *s; int exstat; spawns s with stop for returns exit status 1st word - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TIME returns a string with time and date entrys: TIME time[s] char *s; | | return time as a string | looks like: dd/mm/yy hh:mm:ss | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $TYPE$ types via lun 5 onto terminal ** entrys: $TYPE$ | | push #address of asciz string | jsr pc,$type$ | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Doubly linked list routines ilist[lhead] Initialize a list head. List heads are 6 byte arrays where the 1st word is initialized to the address of the listhead itself, the 2nd and 3rd words are the links. If there was any data in this node then it would have been at word 4. Word one points to this location. All nodes look like: word 0 right link word 1 left link pointers->word 2-n data A listhead looks like: .word address-of-list .word pointer-to-right-link .word pointer-to-left-link address: (no data so nothing allocated here) Then the listhead array is used by referencing the contents of the first element which points to the first node. A three word list head is not really necessary but is convenient for the case of a zero length list. Thus no special checking needs to be done when deleting the last element of a list. Also, the first word of the three is actually a listhead to the other two in the 3 word array. delete[ptr] Deletes the node ptr from the list it is in. Returns ptr which is now a doubly linked list of one element. insert[x,newx] Inserts the node newx after the node x in the list x is in. returns pointer newx. prev[ptr] Returns a pointer to the previous node in the list. next[ptr] Returns a pointer to the next node in the list. release[ptr] This releases storage for the node pointed to by ptr. new[size] Allocates a node for a structure of size "size". Also allocates storage for the link fields (which precede the storage of "size" bytes. The pointer returned points to the start of the data (not the links which are a -2 and -4 from the data). Note that release must be used to return storage allocated by new since each of these routines know about the extra 4 bytes of linkage. New also initializes the link fields such that the node is a complete list of one item. ldump[listhead] This performs a quick dump of a doubly linked list using printf. it outputs all the pointers and the first word of each node (not the listhead). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Unix I/O emulator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To create an environment in which a file is thought of as a virtual memory, the following routines have been built. They can be thought of as a second level above the primitive FO$PEN/close get/put routines described above. There are two compatible versions of these routines. On uses a single disk block for buffering i/o to the file. It is smaller in size, but quite slow when many scattered accesses to the file is made. The second version contains more code and manages a list of block buffers (allocated from the heap) kept in a least recently used list. The user can call a routine to set the maximum number of buffers that the routines should allocate. Except for this one call, the lru management is transparent to the user. So the below will simply document that one routine and discuss all other routines relative to the single block version. The single block version is called uio.mac; the lru versions: muio.mac. The following functions are part of the file uio.mac which emulate files as on unix. That is, the array of bytes concept. Also supported are rsx "buffered" i/o routines for text files. Buffered means that one can use a get/put char routines with newline marking the end. Since Rsx fcs does not give a hint as to how one allocates fsr area (or better yet suppressing it) I chose not to allocate FDB's from the heap. Rather there are a few static ones in the library. They are: name lun type notes ---- --- ------- ----------------------------- stdin 1 rsx text stdin contains address of fdb stdout 2 rsx text stdout contains address of fdb lun3 3 rsx/unix global (lun3::) lun4 4 rsx/unix global (lun4::) stderr 5 qio's Not a file stream: qio only lun6 6 rsx/unix global (lun6::) The way to reference these is as follows: (lun3 4,6 similar) ---- extern char lun3[]; /* declaration somewhere */ bopen(lun3,"file.nam","write","unix"); putc(lun3,c); /* reference to do output */ bclose(lun3); but for stdin and stdout: (These need not be opened or closed) ----- ------ extern char *stdin,*stdout; getc(stdin,c); putc(stdout,c); and fprintf(stdout,"...",...); If you need more than 3 files (of unix type) just duplicate the file lun6 and change lun6 to lun7 everywhere. Note that unix type files do not require fsr areas as only block i/o is used with the block buffers allocated dynamically. Luns 3,4, and 6 are used for LUN3, LUN4, LUN6 respectively. These fdb's may be used for either unix or rsx type of I/O. However, tkb assignments have no affect, i.e. all file names are dynamic. Stdin and stdout can only be rsx type of files. Since there is user space overhead for opened files, stderr is not buffered and cannot be redirected. Also, the error function need not contain a newline character in the string since it is always assumed to be followed by one (does a single qiow with carr control=40(8)). Some of these routines are for C use only. I discovered quite late that a long is stored reverse of how I store them. So, seekl and markl are for C programs only. - - - - - - - - - - - - - - - - - - - function bclose[fdb] close a file opened via bopen file *fdb - - - - - - - - - - - - - - - - - - - function bopen[fdb,name,acc,ptype] file *fdb, char *fdb,*acc,*ptype open a file (buffered). access may be "append", "update", "read", or "write". If update, it will create the file if necessary. Only 1st char of word is required. If the string is longer than 1 char and an error occurs the routine will print on lun 5 (stderr) a diagnostic. ptype may be "unix" or "rsx". A unix file type on an existing file which is not created unix type will work. The close routine will attempt to correctly set the attributes again even though they had to be changed during access. Note that bopen only works on a special fdb. This is one which has 12 words preceding the fdb. (the pointer points to the beginning of the fdb, not these 12 words). They contain extra stuff for controlling buffered io etc. One word contains the integer value 12345. This is to verify that the fdb is correct. The following is a model of an fdb: stdin:: .word inr .word 0 ;b.lh listhead pointer .word -1,-1 ;b.lhl listhead links for LRU blocks ;b.peek or peek char if rsx i/o .byte 4. ;b.max maximum blocks (default = 4) .byte -1 ;b.cur current in list .word -1 ;b.type type of i/o 0=buffered record, 1=unix .word -1 ;b.dirty 0=dirty, 1=not written into yet .word 1 ;b.stat 1=ok <0=eof/err on last seek .word -1,-1 ;b.seek seek address double word .word -1 ;b.stype saved attributes (f.rtyp & f.ratt) .word -1 ;b.ssize saved record size .word -1 ;b.sracc saved record access .word -1 ;b.io direction of i/o -1=r,0=rw,1=w .word 0 ;b.prec pointer to record buffer if record i/o .word -1 ;b.pos position in record buffer if record i/o .word 12345. ;b.check check word (see if a valid fdb) INR: FDB 1 R einr: $$fdsz==einr-stdin-2 Note that b.prec must be initialized to zero and b.stat must be initialized to one. b.check must be 12345. and all others need no initial values. - - - - - - - - - - - - - - - - - - - function bopen[fdb,name,acc,ptype] fdb is a pointer to fcs fdb with 12 words preceding name is asciz acc is same as FO$PEN (i.e. "read", "write", etc.) ptype="unix" or "rsx" - - - - - - - - - - - - - - - - - - - function bclose[fdb] - - - - - - - - - - - - - - - - - - - function cattr[fdb1,fdb2] Copys attributes from fdb1 to fdb2. - - - - - - - - - - - - - - - - - - - function csattr[fdb1,fdb2] Copys `Saved' attributes from fdb1 to fdb2. These are saved during the bopen. - - - - - - - - - - - - - - - - - - - function flush[fdb] Flush a file, this is done automatically by bclose. - - - - - - - - - - - - - - - - - - - function getc[fdb] Get a char from fdb. - - - - - - - - - - - - - - - - - - - function getchar[xxx] Get a char from stdin - - - - - - - - - - - - - - - - - - - function mark[fdb,plong] returns a long into plong (my format) marking where the file is. - - - - - - - - - - - - - - - - - - - function markl[fdb] returns a long (in r0/r1) for a C program. - - - - - - - - - - - - - - - - - - - function putc[fdb,char] Put a char on file fdb - - - - - - - - - - - - - - - - - - - function putchar[ch] put a char on stdout - - - - - - - - - - - - - - - - - - - function seekl[fd,plong1,plong2] from an Mp program long seekl(fd,seekaddress) from a C program seek to location (32 bit byte address in file) - - - - - - - - - - - - - - - - - - - function seekm[fdb,plong] This is only callable by an Mp program. - - - - - - - - - - - - - - - - - - - function lrumax[fdb,max] Sets the maximum buffers to be allocated during file i/o. Can be increased as the program runs, but can not be decreased. The default is currently 4. - - - - - - - - - - - - - - - - - - -