; =====> 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","?" 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 , 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 , error_2: add BX,offset reg0 ; compute address of source 2 pushm ; push source 2, source 1, operation name C_call set_src_,,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-, mov BX,offset hicases ELSE IFIDN , 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 , error_1: pushm ; push operand, operand count, instr. name C_call set_src_,,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 ; 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 ; 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 ; 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 ; 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 , lods byte ptr ES:[SI] ; load source operand register number mov DL,AL ; and save it in TIPC register DL ENDIF save ; 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 , 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 , 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 , mov DX,3 ; STRING-REF is 3 bytes long s_out_bn: restore ; load location pointer and sub SI,DX ; back up to start of instruction in error pushm ; push instruction's offset, name C_call disassem,,Load_ES ; disassemble instruction for *irritant* pushm ; push args to "set_numeric_error" C_call set_nume ; set_numeric_error(1,ST_OFF_ERR,tmp_reg); restore ; 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