; ; OPENIN ; ; This macro opens the file shows name is specified and associates ; the name replacing stream with that file. Several locations are ; defined whose name is derived from stream: ; .macro openin stream, filedesc, ?done ?help .show meb brw sk'stream ;Skip over the data flag'stream:.byte 0 ; Indicates if a record should be read size'stream:.long 0 ; # bytes in the buffer after read pos'stream: .long 0 ; position in buffer of next byte stream: .blkb 1 ; Indicates if at end of file .ascii /Can't Open File/ .byte 13,10 .psect ps'stream,long .align long ; Set up to read .noshow meb stream'_f: $fab stream'_rec:$rab fab=stream'_f, ubf=stream'_buf, usz=200 .show meb stream'_buf:.blkb 200 ; Buffer for file .psect ; Set up file name for open sk'stream: movl filedesc+4,stream'_f+fab$l_fna movb filedesc,stream'_f+fab$b_fns $open fab=stream'_f ;Open file blbs r0,help movab stream+1,r0 movl #17,r1 jsb writestr brw done help: movb #1, stream ; Indicate stream ready $connect rab=stream'_rec ;Associate RAB done: .endm openin ; ; CLOSEIN ; ; Close the input file ; .macro closein stream $close fab=stream'_f .endm closein ; ; READREC ; ; Read a record into the file buffer and put the record size in ; the sizestream area. Set the buffer position to the beginning. ; And make sure the buffer ends with a blank. ; .macro readrec stream, ?eof ?si pushr #^m $get rab=stream'_rec ; Read a record blbc r0, eof ; Check eof cvtwl stream'_rec+rab$w_rsz, size'stream clrl pos'stream ; Set record size and pos movb #1,flag'stream ; Indicate read not needed movab stream'_buf,r1 addl2 size'stream,r1 movb #^a/ /,(r1) ; Put space at end incl size'stream ; Set buffer size brb si eof: movb #0, stream ; If read fails, indicate eof si: popr #^m .endm readrec ; ; CHARIN ; ; Read one character from the stream, unless at eof. ; .macro charin stream, ch, ?hop ?done ?bad tstb flag'stream ; Test buffer position bneq hop ; If at end, readrec stream ; read a record blbc r0, bad ; Check for eof hop: movab stream'_buf,-(sp) ; Put buffer addr on stack addl2 pos'stream,(sp) ; Adjust addr to next char movb @0(sp), ch ; Put char at location ch incl pos'stream ; Adjust position cmpl pos'stream, size'stream bneq done ; If then at buffer end, movb #0, flag'stream ; set buffer flag done: tstl (sp)+ ; Restore stack bad: .endm charin ; ; STRINGIN ; ; Read a string from the stream. Skips leading spaces and reads ; consecutive characters to string location. Then, attaches a null ; character to the end of the string. ; .macro stringin stream, str, ?hold, ?skip, ?ignore - ?start, ?done, ?ok pushr #^m brb skip ; Skip the data area hold: .blkb 1 skip: movab str, r6 ignore: charin stream, hold ; Loop to ignore white space tstb stream ; Don't ignore eof bneq ok brw done ok: cmpb hold, #^a/ / bneq start brw ignore start: movb hold, (r6)+ ; Loop to move characters charin stream, hold ; to string until space found tstb stream ; Test for eof beql done cmpb hold, #^a/ / beql done brw start done: clrb (r6) ; Put null at string end popr #^m .endm stringin ; ; STRLEN ; ; Count number of characters in a string. Looks for the null at ; the end as it counts. ; .macro strlen str, ans ?top, ?done clrl ans ; Initialize count movab str,-(sp) ; Put string addr on stack top: tstb @0(sp) ; See if char is null beql done incl ans ; Increment count incl (sp) ; Increment address brb top done: tstl (sp)+ ; Restore stack at end .endm strlen ; ; INTIN ; ; Read in a digit string and store number as a longword at num. ; Numbers must be positive. Leading white space is skipped. ; .macro intin stream, num, ?safe ?pack ?skip - ?exit ?miss ?len ?pos ?nneg brb skip safe: .ascii / / ; For LSN string pack: .blkb 6 len: .blkl 1 pos: .blkl 1 skip: stringin stream, safe+1 ; Put digit string in place tstb stream ; Check for eof beql miss pushr #^m strlen safe+1,len ; Determine # digits movab safe,pos cmpb safe+1,#^a/-/ bneq nneg incl pos decl len nneg: cvtsp len,@pos,len,pack ; Convert to integer cvtpl len,pack,num exit: popr #^m miss: .endm intin ; ; SCREENOUT ; ; Output to the screen a string (if form is s), a character (if ; form is c), or an integer (if form is i). The value at loc ; is allowed to be any operand type - relative, literal, register, ; etc. This uses the easyio subroutines to do the output. ; .macro screenout form, loc ?hold, ?skip type__=%locate(form,) brb skip hold: .blkl 1 skip: movl loc, hold ; Put value in memory .if lt type__-2 movab loc, r0 ; Output a string strlen loc, r1 ; Get length of string jsb writestr .if_false movab hold, r0 .if lt type__-4 movl #1, r1 ; For character, length=1 jsb writestr .if_false .if lt type__-6 movl #11, r1 ; For integer, assume max size jsb writeint .endc .endc .endc .endm screenout ; ; FILEIN ; ; Read a string, character, or integer from an input file stream. ; Form indicates what is to be read: s - string, c - character, ; i - integer. Use other macros to do this. ; .macro filein stream, form, loc type2__=%locate(form,) .if lt type2__-2 stringin stream, loc ; String .if_false .if lt type2__-4 charin stream, loc ; Character .if_false .if lt type2__-6 intin stream, loc ; Integer (positive) .endc .endc .endc .endm filein ; ; BEOF ; ; Test stream for eof and branch to dest if at eof ; .macro beof stream, dest ?skip tstb stream bneq skip brw dest skip: .endm beof ; ; BEOL ; ; Test for end of line (as indicated by buffer empty) ; .macro beol stream, dest ?skip tstb flag'stream bneq skip brw dest skip: .endm beol