+ .align 2
+strtab: # translate table for detecting null and percent
+ .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .byte 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ .byte ' ,'!,'",'#,'$, 0,'&,'','(,'),'*,'+,',,'-,'.,'/
+ .byte '0,'1,'2,'3,'4,'5,'6,'7,'8,'9,':,';,'<,'=,'>,'?
+ .byte '@,'A,'B,'C,'D,'E,'F,'G,'H,'I,'J,'K,'L,'M,'N,'O
+ .byte 'P,'Q,'R,'S,'T,'U,'V,'W,'X,'Y,'Z,'[,'\,'],'^,'_
+ .byte '`,'a,'b,'c,'d,'e,'f,'g,'h,'i,'j,'k,'l,'m,'n,'o
+ .byte 'p,'q,'r,'s,'t,'u,'v,'w,'x,'y,'z,'{,'|,'},'~,127
+ .byte 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143
+ .byte 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159
+ .byte 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175
+ .byte 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191
+ .byte 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207
+ .byte 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
+ .byte 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239
+ .byte 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
+
+strfoo:
+ clrl r4 # fix interrupt race
+ jbr strok # and try again
+strmore:
+ movzbl (r1)+,r2 # one char
+ tstb (r3)[r2] # translate
+ jeql stresc2 # bad guy in disguise (outbuf is full)
+strout2: # enter here to force out r2; r0,r1 must be set
+ pushr $3 # save input descriptor
+ pushl fdesc # FILE
+ pushl r2 # the char
+ calls $2,__flsbuf # please empty the buffer and handle 1 char
+ tstl r0 # successful?
+ jgeq strm1 # yes
+ jbcs $31,nchar,strm1 # turn on sign bit of nchar to signify error
+strm1:
+ incl nchar # count the char
+ popr $3 # get input descriptor back
+strout: # enter via bsb with (r0,r1)=input descriptor
+ movab strtab,r3 # table address
+ movq *fdesc,r4 # output descriptor
+ jbs $31,r4,strfoo # negative count is a no no
+strok:
+ addl2 r0,nchar # we intend to move this many chars
+ movtuc r0,(r1),$0,(r3),r4,(r5)
+ movpsl r2 # squirrel away condition codes
+ movq r4,*fdesc # update output descriptor
+ subl2 r0,nchar # some chars not moved
+ jbs $vbit,r2,stresc # terminated by escape?
+ sobgeq r0,strmore # no; but out buffer might be full
+stresc:
+ rsb
+stresc2:
+ incl r0 # fix the length
+ decl r1 # and the addr
+ movl $1<vbit,r2 # fake condition codes
+ rsb
+
+errdone:
+ jbcs $31,nchar,prdone # set error bit
+prdone:
+ movl nchar,r0
+ ret
+