📄 inpdsk.asm
字号:
page
;***
;B$FillBuf -- fill one input item into the buffer
;
;Purpose:
; According to the delimiters, fill in the buffer with one input item,
; which is still in the form of character stream, from a disk file or
; from a device.
;
; A data file for input could be created by any editor or by a BASIC
; program. If it is created by BASIC, we should keep our eyes on the
; continuation mark, LF, and the end-of-line mark, "CR LF."
;
; This routine abides by two rules. The first rule is for inputing
; a quoted string and the second is for unquoted string and numbers
; as well. The first rule says to pick up all characters between
; two '"'s inclusively. The second rule says that, when a combination
; of continuation marks and end-of-line marks has been encountered,
; within the input character stream, if a LF precedes a CR, the CR is
; ignored. These rules are for INPUT # stmt. LINE INPUT # statement
; follows the second rule, except that, if a LF precedes a CR, the CR
; is still stored as part of the character stream.
;
; This routine checks for the situation mentioned above.
;
; Note: The continuation mark, LF, is treated as a regular character
; and is stored in the buffer as part of the item if the input
; is for a number; whereas the LF is NOT stored if the input
; is for a unquoted string. One reason for this is that the
; next call, B$FIN, will take care of the LF when converting
; the digital stream into a number.
;
;Entry:
; [DX] = 0 if LINE INPUT #
; = ","+" " if INPUT #, numberVar
; = ","+"," if INPUT #, stringVar
; [b$FInput] = DskInp
; [b$PTRFIL] = *FDB
;Exit:
; [SI] = *sd of the character stream of the input item
;Uses:
; none
;Exceptions:
; read pass end -- _BERR_RPE
;*******************************************************************************
cProc B$FillBuf,<PUBLIC,NEAR>,<DI,ES> ;save DI,ES
cBegin
PUSH DS
POP ES ; make sure ES=DS
SkipLeading:
CALL B$$RCH ;get next char in AL
JC ERCRPE ;Brif no char got, give "read pass end"
OR DL,DL ;line input?
JZ Get1stChar ;Brif yes
CMP AL," " ;is blank ?
JZ SkipLeading ;skip it
Get1stChar:
MOV SI,OFFSET DGROUP:b$SDBuf1 ; initialze string to b$Buf1
MOV DI,OFFSET DGROUP:b$Buf1
MOV CL,255 ;allow max of 255 characters per buffer
CMP AL,'"' ;quoted string?
JNZ CharLoop ;Brif not
CMP DL,"," ;looking for a string?
JNZ CharLoop ;Brif not
cCall StoreChar ;save '"' at start of string so FIN can match it
MOV DX,'""' ;Set delimiters to '"'
CALL B$$RCH ;get next char
JC Quit ;Brif null string
CharLoop:
CMP DH,'"' ;getting a quoted string?
JZ NotCRLF ;Brif yes, don't check LF CR
CMP AL,NEWLINE ;end of a line? (unquoted string or number)
JZ EndCR ;Brif yes
CMP AL,ASCLF ;check LF CR, the CR will be ignored
JNZ NotCRLF ;Brif not
GotLF: ;have a continuation mark and not a quoted str
CMP DL,"," ;getting an unquoted string?
JZ ChkLFCR ;don't store linefeeds if unquoted strings
cCall StoreChar ;store LF for numbers
ChkLFCR:
CALL B$$RCH ;get next char
JC QUIT ; quit if eof.
CMP AL,ASCLF ;check for LF after LF
JZ GotLF ;Brif yes
CMP AL,NEWLINE ;ignore CR after LF if NOT LINE INPUT
JNZ NotCRLF ;Brif not
OR DL,DL ;is LINE INPUT ?
JNZ NextChar ;Brif not (ignore CR)
NotCRLF:
OR AL,AL
JZ NextChar ;ignore nulls
CMP AL,DH ;check for first terminator
JZ Quit ;Brif yes
CMP AL,DL ;check for second terminator
JZ Quit ;Brif yes
cCall StoreChar ;store the character
NextChar:
CALL B$$RCH ;read next char
JNC CharLoop ;loop again
Quit: ;AL="," or '"' or " "
CMP AL,"," ;must has more item
JZ PutZero
SkipEnding: ;skip ending blanks
CALL B$$RCH
JC PutZero
CMP AL," "
JZ SkipEnding
CMP AL,"," ;has more item to go
JZ PutZero
CMP AL,NEWLINE ;ends ?
JNZ BackOneChar ;back up one char for next time
EndCR:
MOV BX,[b$PTRFIL] ;get file pointer (never 0000)
MOV AL,[BX].FD_DEVICE ; Get device type
CMP AL,DN_PIPE ; are we piping?
JZ ENDCR_PIPE ; Then just process like a file
OR AL,AL ; See if other special device
JS PutZero ;do not look for LF if special device
ENDCR_PIPE:
CALL B$$RCH
JC PutZero
CMP AL,ASCLF
JZ PutZero
BackOneChar:
PUSH SI ; Save SI
MOV SI,[b$PTRFIL] ; Get File pointer (not 0)
MOV AH,DV_BAKC ; Back up one char
CALL B$PtrDispatch
POP SI ; Restore SI
PutZero:
XOR AL,AL
STOSB ;terminated by 00H
MOV BX,OFFSET DGROUP:b$Buf1
CALL B$STGETSTRLEN ;find length of string in input buffer
INC AX ;ensure room for terminating zero
MOV b$SDBuf1,AX ; make sd
cCall Concat ;concatenate buffer to string, if necessary
;on return SI=*sd of concatenated string
cEnd ;exit to caller
page
;***
;StoreChar -- store char in buffer
;
;Purpose:
; Store character in AL into location ES:DI. If the buffer is full,
; then concatenate the buffer into a string, and reset the buffer for
; next input.
;Entry:
; [SI] = *sd of result string
; [AL] = char
; ES:DI = buffer location
; [CL] = buffer count
;Exit:
; if buffer is not full then
; SI = *sd of result string
; character is stored in buffer pointed by ES:DI
; DI is incremented by one (buffer pointer)
; CL is decremented by one (buffer count)
; else
; SI = *sd of concatenated string
; DI = *b$Buf1
; CL = 255
; endif
;Uses:
; none
;Preserves: (optional)
; DX
;Exceptions:
; none
;*******************************************************************************
cProc StoreChar,<NEAR>
cBegin
OR AL,AL
JZ StoreExit ;no char, exit
STOSB ;store in ES:DI, DI incremented
DEC CL ;Buffer full?
JNZ StoreExit ;no, continue
MOV b$SDBuf1,255 ; yes, note buffer length
PUSH DX ; Save DX Flags (trashed in Concat + below)
cCall Concat ;concatenate buffer to string, if necessary
JNZ BufferReset ;already had a string, return concatenated one
;first buffer overflow, need initial string
MOV BX,255 ;string length
MOV DX,[SI+2] ;point to the string
CALL B$STALCTMPCPY ;copy contents of b$Buf1 into temp string
MOV SI,BX ;note string as start of input data
BufferReset:
POP DX ; Restore Flags
MOV DI,OFFSET DGROUP:b$Buf1
MOV CL,255 ;reset input to start of buffer
StoreExit:
cEnd ;exit to caller
page
;***
;Concat -- concatenate the buffer into a string
;
;Purpose:
; Concatenate the buffer b$Buf1, whose sd is b$SDBuf1, into the
; current string pointed by SI, if the current one is not b$Buf1.
;Entry:
; SI = *sd of current string
;Exit:
; ZR if no concatenation happened (SI = addr of b$SDBuf1)
; NZ & SI=*sd of concatenated string
;Uses:
; none
;Exceptions:
; none
;*******************************************************************************
DbPub Concat
cProc Concat,<NEAR>
cBegin
MOV BX,OFFSET DGROUP:b$SDBuf1
CMP BX,SI ;is the current string the input buffer
JZ ConcatExit ;yes, just return it with ZR
cCall B$SCAT,<SI,BX> ; concatenate buffer to current string
MOV SI,AX ;SI has the concatenated string
ConcatExit:
cEnd ;exit to caller
page
;***
;DeviceFin
;
;Purpose:
; Device (disk) float or string input.
;
; Allocating the string could make all temp string offsets changed.
; Only string descriptor is still valid in that case.
;
; For device (disk) input, if an input string is longer than 255
; bytes, we use a temp string instead of the static buffer. (Refer
; to the above routine, B$FillBuf) This caused problem when we use
; B$FIN for disk input.
;
; B$FIN takes the pointer of the given string (NOT *SD) and does
; the string move using that string pointer after allocating a temp.
; This will be fine if the pointer passed to B$FIN is a static one.
; However, device (disk) input isn't the case if the length of input
; string is longer than 255.
;
; In this routine, it takes *SD instead of *string for a string input.
;
;Entry:
; [b$VTYP] = type of var
; [SI] = *sd of variable character string
;Exit:
; AC has integer value ([b$VTYP] = VT_I2) (calls B$FIN)
; AC has integer value ([b$VTYP] = VT_I4) (calls B$FIN)
; AC has the address of string descriptor ([b$VTYP] = VT_SD)
; AC has S.P. value ([b$VTYP] = VT_R4) (calls B$FIN)
; DAC has D.P. value ([b$VTYP] = VT_R8) (calls B$FIN)
; DAC has CY value ([b$VTYP] = VT_CY) (calls B$FIN)
; endif
;Uses:
; none
;Exceptions:
; if error, runtime error handler is invoked, and this never returns
;*******************************************************************************
DbPub DeviceFin
cProc DeviceFin,<NEAR>,<SI,DI,ES>
cBegin
PUSH SI ;save *sd one more copy for later use
MOV SI,[SI+2] ;B$FIN likes string offset...
CMP [b$VTYP],VT_SD ; test if string
JZ GetString ;jump to special case
CALL B$FIN ;process non-string value
JMP SHORT FinExit ;jump to finish up
GetString:
PUSH DS
POP ES ; make ES=DS
CALL B$STRSCAN ; get string from buffer pointed by ES:SI
; do all of $GETSTR except for temp string
; creation, on return DX=*string, CX=length
POP DI ;get input string description (pushed as SI)
PUSH DI ;and put it back on stack
MOV AX,DX ;get offset of the string
SUB AX,[DI+2] ;skip count for leading white spaces
MOV BX,CX ;get length of new string
CALL B$STALCTMP ;allocate a temporary string
MOV DI,[BX+2] ;get new string pointer
POP SI ;get old descriptor again
PUSH SI ;still want it on stack
MOV SI,[SI+2] ;get pointer of the old string
ADD SI,AX ;get pointer of the old string without white
; white spaces
INC CX ;roundup byte count
SHR CX,1 ;make a word count for transfer
REP MOVSW ;move from old to new string
MOV [B$AC],BX ;put output string desc in BX
FinExit:
POP BX ;done - restore descriptor
;this was pushed as SI
CALL B$STDALCTMP ;delete if temporary
cEnd ;pop registers and return to caller
sEnd ;DK_TEXT
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -