.title xparse .ident "Y01.06" .enabl lc .nlist bex,cnd ; ; NOTE: No CX library documentation, as this is an "internal" routine ; for the setfnb() function. ; ; This file contains the RSX-11M special code for parsing a file ; specification and filling in the fields in the template FNB. ; If no UIC is given, the UIC cell in the OPNCLO impure area is ; zeroed out, signalling to the directory processing routine that ; it must find the default UIC. ; ; Edits: ; X01.00 15-Jul-81 RBD Initial edit ; X01.01 30-Jul-81 RBD Pass filespec pointer in r1 ; X01.02 31-Jul-81 RBD Set NB.DIR bit on explicit UIC ; Y01.03 31-Jul-81 RBD Disallow null string = ".;0" ; Y01.04 31-Jul-81 RBD Do not clear file extension in FNB. Permits ; support of default extension. ; Y01.05 26-Aug-82 RBD P-section changes for CX ; Y01.06 20-Oct-82 RBD Remove CSD copyright notice. Release to public ; domain. Ready for new C kit. Fix humorous bug ; which allowed blanks inside filenames! Also ; don't allow '#' signs (where'd that one slip ; in??). .psect C$CODE .sbttl SUBRTN - Parse filespec into FNB (RSX-11M only) ; ; -PARSE- Parse filespec into FNB (RSX-11M only) ; ; Inputs: ; r0 --> FNB to set up. N.FTYP treated as default extension. ; r1 --> Filespec string, null terminated. ; ; Outputs: ; C-Bit cleared: ; FNB Initialized -- ; N.FID Cleared ; N.FNAM Set in RAD50 ; N.FTYP Set in RAD50 (may default) ; N.FVER Set in binary. Default ";0" ; N.STAT Set appropriately ; N.NEXT Cleared ; N.DID First 2 words = UIC(RAD50) or null. Third = 0 ; N.DVNM Set in ASCII. Default "SY" ; N.UNIT Set in binary with octal interp. Default 0 ; C-Bit set: ; Syntax error. ; ; Registers preserved. ; EIS instructions used unless C$$NHD is defined. ; .mcall nbof$l nbof$l ; Define FNB offsets locally. PARSE:: call $saval ; Save all registers (SYSLIB) mov r1,r2 ; r2 --> filespec string ;01 mov r0,r4 ; r4 --> FNB ; ; Initialize FNB with defaults. ; mov r4,r0 ; r0 --> fnb mov n.ftyp(r4),-(sp) ; Save default extension ;02 mov #s.fnbw,r1 ; r1 = size of FNB 10$: clr (r0)+ ; Zero out the FNB .if ndf c$$nhd sob r1,10$ .iff dec r1 bne 10$ .endc mov (sp)+,n.ftyp(r4) ; Restore default extension ;02 mov #"SY,n.dvnm(r4) ; Device default "SY00:" ; ; Top level of scanner. Scan till we hit a special character ; or end of string. Dispatch accordingly. ; nxt: mov r2,r1 ; r1 --> current character movb (r2)+,r0 ; r0 = current character; r2 -> next. ;;; beq done ; Done if null bne .+6 jmp done cmp r0,#'[ ; Start of UIC? bne 10$ ; (no) call getuic ; UIC. Process it. bcc nxt ; If OK, proceed br errxit ; Bad UIC. Error exit. 10$: cmp r0,#': ; Device delimiter? beq dev ; Yes, process a device spec. cmp r0,#'. ; Filename delimiter? beq fil ; Yes, process a filename+extension cmp r0,#'; ; Extension delimiter? beq fil ; Yes, filename/null ext./explicit ver. movb (r2)+,r0 ; Nothing special, get another char beq fil ; If null, filename/null ext./null ver br 10$ ; Else, keep looping ; ; Device name processing. ; ; NOTE: RSX-11M device unit numbers are OCTAL. ; ; Inputs: ; r1 --> start of device name ; r2 --> terminating ":" ; ; Outputs: ; N.DVNM contains the ASCII 2 character device name ; N.UNIT contains the binary unit number (default = 0) ; NB.DEV flag in N.STAT is set. ; R2 --> character after the ":" ; R1 --> N.UNIT field of FNB ; dev: bis #nb.dev,n.stat(r4) ; Set the NB.DEV bit sub r1,r2 ; r2 = length of device name+1 cmp r2,#3 ; Must be "DD:" = 2 chars+":" blo errxit ; Device name error. mov r1,r2 ; r2 --> device name mov r4,r1 ; r1 --> FNB add #n.dvnm,r1 ; r1 --> device name field movb (r2)+,(r1) ; Set in a character bicb #' ,(r1)+ ; Force upper case movb (r2)+,(r1) ; Set in second character bicb #' ,(r1)+ ; Force it upper case; r1 --> N.UNIT clr (r1) ; Zero the N.UNIT field 10$: cmp (r1),#77 ; Unit 77 is max bhi errxit ; (too big; error) movb (r2)+,r0 ; Get next character cmp r0,#': ; Is it the ":"? beq nxt ; Yes, default to unit 0 sub #'0,r0 ; Unit number (maybe) bmi errxit ; Definitely not octal digit! Error. cmp r0,#7 ; Not octal digit? bhi errxit ; Nope; error. asl (r1) ; Place shift unit no. octally asl (r1) asl (r1) add r0,(r1) ; Add in a digit br 10$ ; ; Process file name up to 9 characters ; ; Inputs: ; r2 --> first character of file name ; r4 --> FNB ; Outputs: ; NB.NAM bit set in N.STAT ; File name in RAD50 in N.FNAM in the FNB ; r2 --> char following name ("." or ";" or null) ; fil: bis #nb.nam,n.stat(r4) ; Set the NB.NAM bit in N.STAT dec r2 ; r2 --> terminator mov r2,-(sp) ; Save this pointer mov r2,r0 ; r0 --> terminator sub r1,r0 ; r0 = length of string bhi 5$ ; Must not be null. tst (sp)+ ; Error. Junk saved r2. br errxit ; Exit. 5$: mov r4,r2 ; r2 --> FNB add #n.fnam,r2 ; r2 --> N.FNAM field mov #9.,r3 ; r3 = max length call move ; Fill in filename mov (sp)+,r2 ; Restore end pointer bcs errxit ; Error if C-bit is set movb (r2)+,r0 ; r0 = terminator beq done ; Null means we're done. cmp r0,#'. ; Dot means extension to do. bne 40$ ; (no, must be explicit version) ; ; Process explicit extension. ; ; Inputs: ; r2 --> first character after "." ; r4 --> FNB ; ; Outputs: ; NB.TYP bit set in N.STAT ; Extension in RAD50 in N.FTYP in the FNB ; r2 --> char following extension or terminating null ; bis #nb.typ,n.stat(r4) ; Set the NB.TYP bit in N.STAT mov r2,r1 ; r1 --> start of extension 20$: movb (r2)+,r0 ; Scan r2 to past ";" or null beq 30$ ; Null cmp r0,#'; bne 20$ ; Not ";" 30$: dec r2 ; r2 --> null or ";" mov r2,-(sp) ; Save this pointer mov r2,r0 sub r1,r0 ; r0 = length of extension mov r4,r2 ; r2 --> FNB add #n.ftyp,r2 ; r2 --> N.FTYP field mov #3,r3 ; r3 = max length call move ; Set in the RAD50 extension mov (sp)+,r2 ; Restore end pointer bcs errxit ; Error if C-bit set. tstb (r2)+ ; Scan by ";" or null beq done ; (null, we're done like a cake) ; ; Process explicit version. If a "-" is next, force "-1" (oldest) ; extension. All other negatives are illegal anyway. Therefore, ; any extension greater than (unsigned) 77777 will be rejected. ; ; Inputs: ; r2 --> first character after ";" ; r4 --> FNB ; ; Outputs: ; NB.VER bit set in N.STAT ; Binary version number in N.FVER of the FNB ; 40$: bis #nb.ver,n.stat(r4) ; Set the NB.VER bit. cmpb (r2),#'- ; Well ? bne 50$ ; No. mov #-1,r1 ; Use version -1 br 80$ 50$: clr r1 ; r1 will be binary version 60$: bmi errxit ; Versions of 100000(8) and over are illegal?? movb (r2)+,r0 ; r0 = digit beq 80$ ; (null char. ; done) sub #'0,r0 ; r0 = binary value blo errxit ; Must be ASCII 0-7 cmp r0,#7 bhi errxit .if ndf c$$nhd ash #3,r1 ; Place shift value octally .iff asl r1 ; Place shift value octally asl r1 asl r1 .endc add r0,r1 ; Add in this digit br 60$ 80$: mov r1,n.fver(r4) ; Put the explicit version into the FNB done: tst n.stat(r4) ; Make sure we got something! beq errxit ; (no) clc return errxit: sec return ; ; Parse a UIC string and convert to RAD50 for directory lookup. ; Place the RAD50 into N.DID and N.DID+2 of the FNB. Also, set ; the NB.DIR bit in N.STAT. ; ; Inputs: ; r2 --> first character after "[" ; r4 --> FNB ; ; Outputs: ; r2 --> first character after "]" ; NB.DIR bit set in N.STAT ; has RAD50 directory name ; getuic: call getf ; Convert group number bcs 10$ ; (error) mov r3,N.DID(r4) ; Place it into the FNB cmpb (r2)+,#', ; Scan by the comma bne 10$ ; (error) call getf ; Convert user number bcs 10$ ; (error) mov r3,N.DID+2(r4) ; Place it into the FNB cmpb (r2)+,#'] ; Scan by the "]" bne 10$ ; (error) bis #nb.dir,N.STAT(r4) ; Turn on the NB.DIR bit ;02 clc return 10$: sec ; Error; set C-bit return ; ; Convert an (up to three digit) octal field. ; ; Inputs: ; r2 --> ASCII octal digits ; ; Outputs: ; r2 --> first non octal character encountered ; r3 = RAD50 conversion of ASCII octal ; getf: clr r1 10$: movb (r2)+,r0 ; Pick up ASCII character sub #'0,r0 ; Convert to binary bmi 20$ ; Not octal character cmp r0,#7 ; Must be in range 0-7 bhi 20$ ; Not octal character .if ndf c$$nhd ash #3,r1 ; Place shift value octally .iff asl r1 ; Place shift value octally asl r1 ; asl r1 ; .endc add r0,r1 ; Add in this digit br 10$ ; Back for more 20$: dec r2 ; Point back at non-octal character cmp #377,r1 ; Is the value out of range? blo 30$ ; Yes, error. (C-bit set) clr r3 ; Convert to RAD50 in r3 .if ndf c$$nhd ash #7,r1 ; .iff swab r1 ; ash #7,r1 asrb r1 ; ror r1 ; .endc call 40$ call 40$ call 40$ clc 30$: return ; ; Convert 1 digit; accumulate RAD50 in r3. (tricky) ; 40$: clr r0 ; Clear MSH .if ndf c$$nhd ashc #3,r0 mul #50,r3 ; Place shift RAD50-ly .iff asl r1 ; ashc #3,r0 rol r0 ; asl r1 ; rol r0 ; asl r1 ; rol r0 ; call mul503 ; Place shift RAD50-ly .endc add r0,r3 ; Add in the digit add #36,r3 ; Adjust it return ; ; Move a field of characters, performing an ASCII to RAD50 conversion. ; A short source field is padded with blanks. ; ; Inputs: ; r0 = # of ASCII characters to process ; r1 --> Source of ASCII characters ; r2 --> Destination for RAD50 words ; r3 = Maximum number of ASCII characters ; ; Outputs: ; RAD50 data in destination ; ; move: cmp r3,r0 ; Too many characters? blo 30$ ; (yes -- error. set C-bit) 10$: mov r3,-(sp) ; Save r3 mov r2,-(sp) ; Save r2 clr r3 ; Clear RAD50 accumulator call movec ; Do 3 characters --> accumulator bcs 20$ ; (error; C-bit set) call movec bcs 20$ ; (error; C-bit set) call movec bcs 20$ ; (error; C-bit set) mov (sp)+,r2 ; Restore destination pointer mov r3,(r2)+ ; Store RAD50; advance destination pointer mov (sp)+,r3 ; Restore max # characters sub #3,r3 ; Count three bne 10$ ; Back for more if appropriate clc ; Done. Indicate success return ; Many happy returns 20$: mov (sp)+,r2 ; Error, clean up stack mov (sp)+,r3 30$: return ; Error return ; ; Move and translate 1 ASCII character. Used only by 'move'. ; If r0 < 0, it pads in blanks. Disallow non-alpahnum's!! ;06 ; ; Inputs: ; r0 = # characters left to convert ; r1 --> next ASCII character ; r3 = RAD50 accumulator ; ; Outputs: ; r0 decremented to count character ; r1 advanced to next character if r0 > 0 ; r3 <-- (r3 * 050) + baserad50(ASCII) ; movec: clr r2 ; Default to RAD50 blank (zero) dec r0 ; Count a character bmi 50$ ; (no more; pad with a blank) movb (r1)+,r2 ; Pick up the next character cmp r2,#40 ; Must be a legal RAD50 character ;06 blo 60$ ; Illegal if ord(ch) < blank (set C-bit) beq 40$ ; It is a blank; default. cmp r2,#'0 ; Range 0-9? ;06-- blo 60$ ; Error -- ord(ch) < 0 (set C-bit) cmp r2,#'9 blos 20$ ; (in range) cmp r2,#'A ; Range A-Z? blo 60$ ; Error -- ord(ch) < A (set C-bit) cmp r2,#'Z blos 10$ ; (in range) cmp r2,#'a ; Range a-z? blo 60$ ; Error -- ord(ch) < a (set C-bit) cmp #'z,r2 blo 60$ ; Error -- ord(ch) > z (set C-bit) sub #40,r2 ; a-z -- fold to upper case ; ; Adjust ordinal value of ascii to base RAD50 ; 10$: sub #56,r2 20$: sub #11,r2 30$: add #27,r2 40$: sub #40,r2 .if ndf c$$nhd 50$: mul #50,r3 ; Place shift value RAD50-ly .iff 50$: call mul503 ; Place shift value RAD50-ly .endc add r2,r3 ; Add in the new 'digit' clc ; (indicate OK) 60$: return .if ndf c$$nhd ; ; Multiply r3 by 50(8) and put result in r3. ; Thank you Dave Cutler. ; ; r3 = 050 * r3 ; mul503: asl r3 asl r3 asl r3 mov r3,-(sp) asl r3 asl r3 add (sp)+,r3 return .endc .end