pcs/sstring.asm

518 lines
21 KiB
NASM
Raw Permalink Normal View History

2023-05-20 05:57:06 -04:00
; =====> SSTRING.ASM
;************************************************************************
;* TIPC Scheme Runtime Support *
;* Interpreter -- String Operations *
;* *
;* (C) Copyright 1985 by Texas Instruments Incorporated. *
;* All rights reserved. *
;* *
;* Date Written: 18 January 1985 *
;* Last Modification: *
;* 4/27/88 (tc) - removed case conversion from characters in the range *
;* of 128 through 167 (see locases, hicases, collate). *
;* Our previous assumptions did not work for some inter-*
;* national character sets. *
;************************************************************************
include scheme.equ
include sinterp.mac
include sinterp.arg
DGROUP group data
data segment word public 'DATA'
assume DS:DGROUP
; Local data definitions
m_ch_eq db "CHAR=?",0
m_ceq_ci db "CHAR-CI=?",0
m_ch_lt db "CHAR<?",0
m_chl_ci db "CHAR-CI<?",0
m_ch_up db "CHAR-UPCASE",0
m_ch_dwn db "CHAR-DOWNCASE",0
m_mk_str db "MAKE-STRING",0
m_st_fl db "FILL-STRING!",0
m_st_ref db "STRING-REF",0
m_st_set db "STRING-SET!",0
m_one dw 1 ; a constant "one" (1)
m_two dw 2 ; a constant "two" (2)
m_soff dw STRING_OFFSET_ERROR ; error code
; Case tables (for characters between 40h and 0bfh)
public locases,hicases,collate
locases db 000,001,002,003,004,005,006,007
db 008,009,010,011,012,013,014,015
db 016,017,018,019,020,021,022,023
db 024,025,026,027,028,029,030,031
db " ","!",'"',"#","$","%","&","'"
db "(",")","*","+",",","-",".","/"
db "0","1","2","3","4","5","6","7"
db "8","9",":",";","<","=",">","?"
db "@","a","b","c","d","e","f","g"
db "h","i","j","k","l","m","n","o"
db "p","q","r","s","t","u","v","w"
db "x","y","z","[","\","]","^","_"
db "`","a","b","c","d","e","f","g"
db "h","i","j","k","l","m","n","o"
db "p","q","r","s","t","u","v","w"
db "x","y","z","{","|","}","~",127
; C .. ' ^ .. ` o c
; ' u e a a a a '
db 128,129,130,131,132,133,134,135 ;135,129,130,131,132,133,134,135
; ^ .. ` .. ^ ` .. o
; e e e i i i A A
db 136,137,138,139,140,141,142,143 ;136,137,138,139,140,141,132,134
; ' ^ .. ` ^ `
; E ae AE o o o u u
db 144,145,146,147,148,149,150,151 ;130,145,145,147,148,149,150,151
; .. .. ..
; y O U (currency symbols)
db 152,153,154,155,156,157,158,159 ;152,148,129,155,156,157,158,159
; ' ' ' ' ~ ~
; a i o u n N
db 160,161,162,163,164,165,166,167 ;160,161,162,163,164,164,166,167
db 168,169,170,171,172,173,174,175
db 176,177,178,179,180,181,182,183
db 184,185,186,187,188,189,190,191
db 192,193,194,195,196,197,198,199
db 200,201,202,203,204,205,206,207
db 208,209,210,211,212,213,214,215
db 216,217,218,219,220,221,222,223
; beta
db 224,225,226,227,228,229,230,231
db 232,233,234,235,236,237,238,239
db 240,241,242,243,244,245,246,247
db 248,249,250,251,252,253,254,255
hicases db 000,001,002,003,004,005,006,007
db 008,009,010,011,012,013,014,015
db 016,017,018,019,020,021,022,023
db 024,025,026,027,028,029,030,031
db " ","!",'"',"#","$","%","&","'"
db "(",")","*","+",",","-",".","/"
db "0","1","2","3","4","5","6","7"
db "8","9",":",";","<","=",">","?"
db "@","A","B","C","D","E","F","G"
db "H","I","J","K","L","M","N","O"
db "P","Q","R","S","T","U","V","W"
db "X","Y","Z","[","\","]","^","_"
db "`","A","B","C","D","E","F","G"
db "H","I","J","K","L","M","N","O"
db "P","Q","R","S","T","U","V","W"
db "X","Y","Z","{","|","}","~",127
; C .. ' ^ .. ` o c
; ' u e a a a a '
db 128,129,130,131,132,133,134,135 ;128,154,144,"A",142,"A",143,128
; ^ .. ` .. ^ ` .. o
; e e e i i i A A
db 136,137,138,139,140,141,142,143 ;"E","E","E","I","I","I",142,143
; ' ^ .. ` ^ `
; E ae AE o o o u u
db 144,145,146,147,148,149,150,151 ;144,146,146,"O",153,"O","U","U"
;.. .. ..
; y O U (currency symbols)
db 152,153,154,155,156,157,158,159 ;"Y",153,154,155,156,157,158,159
; ' ' ' ' ~ ~
; a i o u n N
db 160,161,162,163,164,165,166,167 ;"A","I","O","U",165,165,166,167
db 168,169,170,171,172,173,174,175
db 176,177,178,179,180,181,182,183
db 184,185,186,187,188,189,190,191
db 192,193,194,195,196,197,198,199
db 200,201,202,203,204,205,206,207
db 208,209,210,211,212,213,214,215
db 216,217,218,219,220,221,222,223
; beta
db 224,225,226,227,228,229,230,231
db 232,233,234,235,236,237,238,239
db 240,241,242,243,244,245,246,247
db 248,249,250,251,252,253,254,255
collate db 000,001,002,003,004,005,006,007
db 008,009,010,011,012,013,014,015
db 016,017,018,019,020,021,022,023
db 024,025,026,027,028,029,030,031
db " ","!",'"',"#","$","%","&","'"
db "(",")","*","+",",","-",".","/"
db "0","1","2","3","4","5","6","7"
db "8","9",":",";","<","=",">","?"
db "@","A","B","C","D","E","F","G"
db "H","I","J","K","L","M","N","O"
db "P","Q","R","S","T","U","V","W"
db "X","Y","Z","[","\","]","^","_"
db "`","a","b","c","d","e","f","g"
db "h","i","j","k","l","m","n","o"
db "p","q","r","s","t","u","v","w"
db "x","y","z","{","|","}","~",127
; C .. ' ^ .. ` o c
; ' u e a a a a '
db 128,129,130,131,132,133,134,135 ;"C","u","e","a","a","a","a","c"
; ^ .. ` .. ^ ` .. o
; e e e i i i A A
db 136,137,138,139,140,141,142,143 ;"e","e","e","i","i","i","A","A"
; ' ^ .. ` ^ `
; E ae AE o o o u u
db 144,145,146,147,148,149,150,151 ;"E","a","A","o","o","o","u","u"
; .. .. ..
;y O U (currency symbols)
db 152,153,154,155,156,157,158,159 ;"y","O","U","$","$","$","$","$"
; ' ' ' ' ~ ~
; a i o u n N
db 160,161,162,163,164,165,166,177 ;"a","i","o","u","n","N",166,167
db 168,169,170,171,172,173,174,175 ;"?",169,170,171,172,"!",'"','"'
db 176,177,178,179,180,181,182,183
db 184,185,186,187,188,189,190,191
db 192,193,194,195,196,197,198,199
db 200,201,202,203,204,205,206,207
db 208,209,210,211,212,213,214,215
db 216,217,218,219,220,221,222,223
; beta
db 224,"s",226,227,228,229,230,231
db 232,233,234,235,236,237,238,239
db 240,241,242,243,244,245,246,247
db 248,249,250,251,252,253,254,255
data ends
PGROUP group prog
prog segment byte public 'PROG'
assume CS:PGROUP
str_int proc near
; Entry points defined in "sinterp.asm"
extrn next:near ; Top of interpreter
extrn next_PC:near ; Reload ES,SI at top of interpreter
extrn next_SP:near ; mov SP,BP before next_PC
extrn src_err:near ; Source (operand) error print routine
extrn sch_err:near ; link to Scheme debugger
char_cmp macro comparison,case,operation
local w,x,y,z
lods word ptr ES:[SI] ; load operands
xor BX,BX
mov BL,AL ; copy the destination=source1 register
mov DI,BX ; number, copy into DI, and compute
add DI,offset reg0 ; the register's address
mov BL,AH ; copy the source2 register number
mov AL,byte ptr reg0_pag+[BX] ; load tag of src2 operand
cmp AL,SPECCHAR*2 ; is source2 a character?
jne z ; if not, error (jump)
cmp AL,byte ptr [DI].C_page ; is source1 a character?
jne z ; if not, error (jump)
IFIDN <case>,<CI>
mov AL,byte ptr reg0_dis+[BX] ; move character value of source2
mov BX,offset locases ; Fetch lower-case equivalents
xlat
mov AH,AL ; Save equivalent in AH
mov AL,byte ptr[DI].C_disp ; move char value of source1
xlat ; Fetch lower-case eqivalent
ELSE
mov AL,byte ptr [DI].C_disp ; Fetch characters
mov AH,byte ptr reg0_dis+[BX]
ENDIF
mov BX,offset collate ; Get collation values of chars
xlat
xchg AL,AH
xlat
cmp AH,AL ; Compare
j&comparison y ; jump, if test is satisfied
xor AX,AX ; place 'nil in destination
mov byte ptr [DI].C_page,AL ; register
mov [DI].C_disp,AX
jmp next ; return to interpreter
y: mov byte ptr [DI].C_page,T_PAGE*2 ; place 't in
mov [DI].C_disp,T_DISP ; destination register
jmp next ; return to interpreter
; ***error-- one (or both) operands aren't characters***
z: mov AX,offset operation
IFIDN <operation>,<m_ch_eq>
error_2: add BX,offset reg0 ; compute address of source 2
pushm <BX,DI,m_two,AX> ; push source 2, source 1, operation name
C_call set_src_,<SI>,Load_ES ; call: set_source_error
jmp sch_err ; link to Scheme debugger
ELSE
jmp error_2
ENDIF
endm
;************************************************************************
;* AL AH *
;* (char-= char1 char2) char-= dest,src *
;* *
;* Purpose: Scheme interpreter support for comparing the equality of *
;* character data objects. *
;* *
;* Description: The tags (page numbers) or the objects are compared *
;* for equality. If they are not equal, at least one of *
;* the operands is not a character, and an error is *
;* signaled. If they are equal, a second check to make *
;* sure both are characters is performed. *
;* *
;* After validating the tag fields, the displacement fields*
;* are compared for equality. If they are identical, the *
;* characters are equal and 't is returned in the destina- *
;* tion register. If not equal, 'nil is returned in the *
;* destination register. *
;************************************************************************
public ch_eq_p
ch_eq_p: char_cmp e,CS,m_ch_eq
;************************************************************************
;* AL AH *
;* (char-equal? char1 char2) char-eq? dest,src *
;* *
;* Purpose: Scheme interpreter support for comparing the equality of *
;* character data objects ignoring case. *
;* *
;* Description: The tags (page numbers) or the objects are compared *
;* for equality. If they are not equal, at least one of *
;* the operands is not a character, and an error is *
;* signaled. If they are equal, a second check to make *
;* sure both are characters is performed. *
;* *
;* The displacements of both operands are loaded and *
;* mapped to uppercase. They are then compared for *
;* equality. If equal, 't is returned in the destination *
;* registers. Otherwise, 'nil is returned. *
;************************************************************************
public ch_eq_ci
ch_eq_ci: char_cmp e,CI,m_ceq_ci
;************************************************************************
;* AL AH *
;* (char-<char1 char2) char-< dest,src *
;************************************************************************
public ch_lt_p
ch_lt_p: char_cmp b,CS,m_ch_lt
;************************************************************************
;* AL AH *
;* (char-less? char1 char2) char-less? dest,src *
;************************************************************************
public ch_lt_ci
ch_lt_ci: char_cmp b,CI,m_chl_ci
purge char_cmp
ch_case macro direction,name
local y
lods byte ptr ES:[SI]
mov DI,AX
add DI,offset reg0
cmp byte ptr [DI].C_page,SPECCHAR*2 ; is input char?
jne y ; if not a character, error (jump)
mov AL,byte ptr [DI].C_disp ; Put char in AL
IFIDN <direction>,<UP>
mov BX,offset hicases
ELSE
IFIDN <direction>,<DOWN>
mov BX,offset locases
ELSE
***error*** Invalid: direction
ENDIF
ENDIF
xlat ; Fetch alternate case
mov byte ptr [DI].C_disp,AL ; and store into dest register
jmp next
; ***error-- invalid source operand***
y: mov AX,offset name ; load the instruction's name text
IFIDN <direction>,<UP>
error_1: pushm <DI,m_one,AX> ; push operand, operand count, instr. name
C_call set_src_,<SI>,Load_ES ; call set_source_error
jmp sch_err ; link to Scheme debugger
ELSE
jmp error_1 ; jump to error routine
ENDIF
endm
;************************************************************************
;* AL *
;* (char-upcase char) char-upcase dest *
;* *
;* Purpose: Scheme interpreter support for conversion of characters *
;* to uppercase *
;************************************************************************
public ch_up
ch_up: ch_case UP,m_ch_up
;************************************************************************
;* AL *
;* (char-downcase char) char-downcase dest *
;* *
;* Purpose: Scheme interpreter support for conversion of characters *
;* to lowercase *
;************************************************************************
public ch_down
ch_down: ch_case DOWN,m_ch_dwn
purge ch_case
;************************************************************************
;* AL AH *
;* (make-string len init) make-string len,init*
;************************************************************************
public make_str
make_str: lods word ptr ES:[SI] ; load the operands of the instruction
save <AX,SI> ; save the operands and location pointer
xor BX,BX
mov BL,AL ; copy the destination register number
add BX,offset reg0 ; into BX and compute its address
cmp byte ptr [BX].C_page,SPECFIX*2 ; is length a fixnum?
jne mk_st_er ; if not, error (jump)
mov AX,[BX].C_disp ; load the immediate value for the size
shl AX,1 ; and sign extend it
sar AX,1
jl mk_st_er ; if size is negative, error
mov CX,STRTYPE ; load the tag value for the string object
pushm <AX,CX,BX> ; push arguments to "alloc_block"
C_call alloc_bl,,Load_ES ; call: alloc_block(reg, STRTYPE, len)
pop BX ; restore destination register address
mov DI,[BX].C_disp ; load a pointer to the newly allocated
mov BX,[BX].C_page ; string object
LoadPage ES,BX
;;; mov ES,pagetabl+[BX]
restore <AX> ; reload operands to instruction
mov BL,AH ; copy initial value register number
mov AL,byte ptr reg0_pag+[BX] ; load page number of init value
cmp AL,SPECCHAR*2 ; init value a character?
je st_fl_3 ; if a character, jump
cmp AL,NIL_PAGE*2 ; use default value? (nil?)
jne mk_st_er ; if not nil, error (jump)
mov AL," " ; load default string fill character
jmp short st_fl_4
mk_st_er: lea BX,m_mk_str ; load address of "make-string" text
jmp src_err ; display "source operand error" message
;************************************************************************
;* AL AH *
;* (string-fill! string char) string-fill! str,char *
;************************************************************************
public str_fill
str_fill: lods word ptr ES:[SI] ; load string-fill operands
save <SI> ; save current location pointer
xor BX,BX
mov BL,AL ; copy string register number
mov DI,BX
mov BL,byte ptr reg0_pag+[DI]
cmp byte ptr ptype+[BX],STRTYPE*2 ; is 1st operand a string?
jne st_fl_er ; if not, error (jump)
LoadPage ES,BX
;;; mov ES,pagetabl+[BX] ; load a pointer to the string object
mov DI,reg0_dis+[DI]
mov BL,AH ; copy initialization value register number
cmp reg0_pag+[BX],SPECCHAR*2 ; is it a char?
jne st_fl_er ; if not, error
st_fl_3: mov AL,byte ptr reg0_dis+[BX] ; load initialization character
st_fl_4: mov CX,ES:[DI].str_len ; load length of string object
cmp CX,0 ;;; check for small string
jge st_010
add CX,BLK_OVHD+PTRSIZE ;;; adjust for small string
st_010: sub CX,offset str_data ; compute number of characters
add DI,offset str_data ; advance index to 1st character position
rep stosb ; fill string object with init character
jmp next_SP ; return to interpreter
st_fl_er: lea BX,m_st_fl ; load address of "fill-string" text
jmp src_err ; display "source operand error" message
str_int endp
;************************************************************************
;* Macro Support for String ref/set *
;************************************************************************
st_thing macro ref_or_set,message
local w,x,y,z
lods word ptr ES:[SI] ; load string pointer and index regs
xor BX,BX
mov BL,AL ; copy string/dest reg number into DI
mov DI,BX
IFIDN <ref_or_set>,<SET>
lods byte ptr ES:[SI] ; load source operand register number
mov DL,AL ; and save it in TIPC register DL
ENDIF
save <SI> ; save the location pointer
mov BL,byte ptr reg0_pag+[DI] ; load string page number
cmp byte ptr ptype+[BX],STRTYPE*2 ; is it a string?
jne y ; if not a string, error (jump)
LoadPage ES,BX
;;; mov ES,pagetabl+[BX]
mov BL,AH ; copy index register number
cmp byte ptr reg0_pag+[BX],SPECFIX*2 ; is index a fixnum?
jne y ; if not a fixnum, error (jump)
mov AX,reg0_dis+[BX] ; load immediate value and
shl AX,1 ; sign extend to 16 bits
sar AX,1
jl z ; if index negative, error (jump)
add AX,offset str_data ; advance pointer past string header
mov SI,reg0_dis+[DI] ; load pointer to string object
mov CX,ES:[SI].str_len ; compare index with string length
cmp CX,0 ;;; check for small string
jge w
add CX,BLK_OVHD+PTRSIZE ;;; adjust for small string
w: cmp AX,CX
jge z ; if index too large, error (jump)
add SI,AX ; add index to string pointer
IFIDN <ref_or_set>,<REF>
mov byte ptr reg0_pag+[DI],SPECCHAR*2 ; set tag=character
mov BL,ES:[SI] ; fetch desired character
mov reg0_dis+[DI],BX ; and store into destination register
ELSE
IFIDN <ref_or_set>,<SET>
mov BL,DL ; copy source value register number
cmp byte ptr reg0_pag+[BX],SPECCHAR*2 ; is source a character?
jne y ; if not a character, error (jump)
mov AL,byte ptr reg0_dis+[BX] ; store source character into
mov ES:[SI],AL ; string at desired offset
ELSE
***error*** Invalid: ref_or_set
ENDIF
ENDIF
jmp next_PC ; return to interpreter
; ***error-- invalid source operand***
y: lea BX,message ; load address of operation name text
jmp src_err ; display "source operand error" message
; ***error-- invalid string offset***
z: mov BX,offset message ; load address of instruction name
IFIDN <ref_or_set>,<REF>
mov DX,3 ; STRING-REF is 3 bytes long
s_out_bn: restore <SI> ; load location pointer and
sub SI,DX ; back up to start of instruction in error
pushm <SI,BX> ; push instruction's offset, name
C_call disassem,,Load_ES ; disassemble instruction for *irritant*
pushm <tmp_adr,m_soff,m_one> ; push args to "set_numeric_error"
C_call set_nume ; set_numeric_error(1,ST_OFF_ERR,tmp_reg);
restore <SI> ; load offset of next instruction
jmp sch_err ; Link to Scheme debugger
ELSE
mov DX,4 ; STRING-SET! is 4 bytes long
jmp s_out_bn ; continue error processing
ENDIF
endm
;************************************************************************
;* AL AH *
;* (string-ref string index) string-ref str,index *
;************************************************************************
public st_ref
st_ref: st_thing REF,m_st_ref
;************************************************************************
;* AL AH AL *
;* (string-set! string index char) string-set! str,index,char *
;************************************************************************
public st_set
st_set: st_thing SET,m_st_set
purge st_thing
prog ends
end