Initial revision
[ssr] / StraySrc / Libraries / Sapphire / sail / _s / termite
1 ;
2 ; termite.s
3 ;
4 ; Implementation of Termite specific instructions
5 ;
6 ; © 1995 Straylight
7 ;
8
9 ;----- Standard header ------------------------------------------------------
10
11 GET libs:header
12 GET libs:swis
13
14 GET libs:stream
15
16 ;----- External dependencies ------------------------------------------------
17
18 GET sh.anchor
19 GET sh.ctrl
20 GET sh.errNum
21 GET sh.error
22 GET sh.express
23 GET sh.getToken
24 GET sh.interp
25 GET sh.stracc
26 GET sh.strBucket
27 GET sh.termscript
28 GET sh.tokens
29 GET sh.upcalls
30 GET sh.var
31
32 ;----- Main code ------------------------------------------------------------
33
34 AREA |TermScript$$Code|,CODE,READONLY
35
36 ; --- termite_beep ---
37
38 EXPORT termite_beep
39 termite_beep ROUT
40
41 TCALL termite_makeBeep ;Make a beep
42 B interp_next ;And go for more
43
44 LTORG
45
46 ; --- termite_break ---
47
48 EXPORT termite_break
49 termite_break ROUT
50
51 TCALL termite_sendBreak ;Send the break
52 BL termite__error ;Handle possible error
53 B interp_next ;And go for more
54
55 LTORG
56
57 ; --- termite_call ---
58
59 EXPORT termite_call
60 termite_call ROUT
61
62 BL ctrl_setUpRegs ;Set up the regs then
63
64 CMP R10,#vType_integer ;Is this an integer?
65 MOVNE R0,#err_numNeeded ;No -- get error number
66 BNE error_report ;...and report the error
67
68 MOV R14,PC ;Set up return address
69 MOV PC,R9 ;Execute the code
70
71 LDR R9,=termite__retned ;Point to some space
72 STMIA R9!,{R0-R8} ;Store returned registers
73 MOV R14,PC,LSR #28 ;Get the flags
74 STMIA R9,{R14} ;Strore the flags too
75 LDMFD R13!,{R7-R12} ;Load back position info
76 LDMFD R13!,{R0} ;Load stracc offset
77 BL stracc_free ;Free any strings I had
78
79 ; --- We have now done the SWI instr ---
80
81 LDR R0,=termite__retned ;Point to the returned regs
82 BL ctrl_resolveRegs ;Do the other half now
83 B interp_next ;If flags -- return
84
85 LTORG
86
87 ; --- termite_chain ---
88
89 EXPORT termite_chain
90 termite_chain ROUT
91
92 ; --- Read a parameter ---
93
94 MOV R0,#0 ;Read an rvalue
95 BL express_read ;Read it then
96 BL express_pop ;And get it off the stack
97 CMP R1,#vType_string ;Is this a string?
98 MOVNE R0,#err_strNeeded ;Nope -- get error number
99 BNE error_report ;...and report the error
100
101 LDR R1,tsc_stracc ;Get the stracc address
102 LDR R1,[R1]
103 ADD R1,R1,R0,LSR #8 ;Point to the string
104 AND R2,R0,#&FF ;Get the length
105
106 ADR R0,tsc_misc+8*4 ;Point to the misc buffer
107 BL termite_copyString ;Copy the string over
108 B tsc_end ;End the script, and chain
109
110 LTORG
111
112 ; --- termite_close ---
113
114 EXPORT termite_close
115 termite_close ROUT
116
117 MOV R0,#-1 ;Close the session
118 B tsc_end ;Do that then
119
120 LTORG
121
122 ; --- termite_cls ---
123
124 EXPORT termite_cls
125 termite_cls ROUT
126
127 TCALL termite_clearScreen ;Clear the screen
128 BL termite__error ;Handle possible error
129 B interp_next ;And go for more
130
131 LTORG
132
133 ; --- termite_download ---
134
135 EXPORT termite_download
136 termite_download ROUT
137
138 MOV R0,#0 ;Read an rvalue
139 BL express_read ;Read it then
140 BL express_pop ;And get it off the stack
141 CMP R1,#vType_string ;Is this a string?
142 MOVNE R0,#err_strNeeded ;Nope -- get error number
143 BNE error_report ;...and report the error
144
145 ; --- Null terminate this ---
146
147 MOV R2,R0 ;Look after the offset
148 MOV R5,#0 ;Useful, t' be sure
149 BL stracc_ensure ;Ensure we have space
150 STRB R5,[R0,#0] ;Terminate the string
151 ORR R0,R1,#1 ;Get the rvalue
152 BL stracc_added ;Tell stracc about terminator
153
154 ; --- Check for another string ---
155
156 CMP R9,#',' ;Do we have a comma?
157 MOVNE R3,#0 ;No -- use default then
158 BNE %10termite_download ;...and jump ahead
159
160 BL getToken ;Skip over the comma
161 MOV R0,#0 ;Read an rvalue
162 BL express_read ;Read it then
163 BL express_pop ;And get it off the stack
164 CMP R1,#vType_string ;Is this a string?
165 MOVNE R0,#err_strNeeded ;Nope -- get error number
166 BNE error_report ;...and report the error
167
168 ; --- Null terminate this ---
169
170 MOV R3,R0 ;Look after the offset
171 MOV R5,#0 ;Useful, t' be sure
172 BL stracc_ensure ;Ensure we have space
173 STRB R5,[R0,#0] ;Terminate the string
174 ORR R0,R1,#1 ;Get the rvalue
175 BL stracc_added ;Tell stracc about terminator
176
177 ; --- Do the download now ---
178
179 10 LDR R1,tsc_stracc ;Load stracc address
180 MOV R4,R2 ;Look after the offet
181 ADD R2,R1,R2 ;Point to protocal name
182 CMP R3,#0 ;Do we have a filename?
183 ADDNE R3,R1,R3 ;Yes -- point to it then
184 TCALL termite_downLoad ;Do the download
185 BL termite__error ;Handle possible error
186 MOV R0,R4 ;Get offset of protocol name
187 BL stracc_free ;Free it now
188 B interp_next ;Do another instruction
189
190 LTORG
191
192 ; --- termite_error ---
193
194 EXPORT termite_error
195 termite_error ROUT
196
197 CMP R9,#tok_on ;Is this an option?
198 CMPNE R9,#tok_off
199 BEQ %50termite_error ;Yes -- jump ahead
200
201 ; --- Read a parameter ---
202
203 MOV R0,#0 ;Read an rvalue
204 BL express_read ;Read it then
205 BL express_pop ;And get it off the stack
206 CMP R1,#vType_string ;Is this a string?
207 MOVNE R0,#err_strNeeded ;Nope -- get error number
208 BNE error_report ;...and report the error
209
210 LDR R1,tsc_stracc ;Get the stracc address
211 LDR R1,[R1]
212 ADD R1,R1,R0,LSR #8 ;Point to the string
213 AND R2,R0,#&FF ;Get the length
214
215 MOV R5,R0 ;look after the rvalue
216 ADR R0,tsc_misc ;Point to the misc buffer
217 MOV R14,#1 ;A sillu error number
218 STR R14,[R0],#4 ;Store that
219 BL termite_copyString ;Copy the string over
220 ADR R0,tsc_misc ;Point to the misc buffer
221 B tsc_error ;Return the error
222
223 ; --- There was an option ---
224
225 50termite_error LDR R0,tsc_flags ;Load the flags word
226 CMP R9,#tok_on ;Turn on the errors?
227 ORREQ R0,R0,#tscFlag_error ;Yes -- set the bit then
228 BICEQ R0,R0,#tscFlag_error ;No -- clear it then
229 STR R0,tsc_flags ;Store the flags back
230 BL getToken ;Skip over the token
231 B interp_next ;Do the next one
232
233 LTORG
234
235 ; --- termite_exec ---
236
237 EXPORT termite_exec
238 termite_exec ROUT
239
240 ; --- Read a parameter ---
241
242 MOV R0,#0 ;Read an rvalue
243 BL express_read ;Read it then
244 BL express_pop ;And get it off the stack
245 CMP R1,#vType_string ;Is this a string?
246 MOVNE R0,#err_strNeeded ;Nope -- get error number
247 BNE error_report ;...and report the error
248
249 LDR R1,tsc_stracc ;Get the stracc address
250 LDR R1,[R1]
251 ADD R1,R1,R0,LSR #8 ;Point to the string
252 AND R2,R0,#&FF ;Get the length
253
254 MOV R5,R0 ;look after the rvalue
255 ADR R0,tsc_misc+8*4 ;Point to the misc buffer
256 BL termite_copyString ;Copy the string over
257 MOV R0,R5 ;Get the rvalue
258 BL stracc_free ;Free the string from stracc
259 ADR R0,tsc_misc+8*4 ;Point to the misc buffer
260 ORR R0,R0,#(1<<30) ;Make this into an exec
261 BL tsc_end ;Exec new script
262 B interp_next ;Continue happily
263
264 LTORG
265
266 ; --- termite_finish ---
267
268 EXPORT termite_finish
269 termite_finish ROUT
270
271 TCALL termite_finishSession ;Finish the session
272 B interp_next ;And go round for more
273
274 LTORG
275
276 ; --- termite_hangup ---
277
278 EXPORT termite_hangup
279 termite_hangup ROUT
280
281 TCALL termite_dropCarrier ;Hang up the modem
282 B interp_next ;And go for more
283
284 LTORG
285
286 ; --- termite_lclear ---
287
288 EXPORT termite_lclear
289 termite_lclear ROUT
290
291 TCALL termite_clearLocal ;Clear the buffer
292 B interp_next ;And go for more
293
294 LTORG
295
296 ; --- termite_lecho ---
297
298 EXPORT termite_lecho
299 termite_lecho ROUT
300
301 CMP R9,#tok_off ;Is this an option thingy?
302 CMPNE R9,#tok_local
303 CMPNE R9,#tok_remote
304 CMPNE R9,#tok_both
305 BEQ %50termite_lecho ;Yes -- deal seperately
306
307 ; --- Just echo the result to the screen then ---
308
309 MOV R0,#0 ;Read an rvalue
310 BL express_read ;Read the next expression
311 BL express_pop ;Get the value in R0,R1
312 CMP R1,#vType_integer ;Is this an integer?
313 BEQ %10termite_lecho ;Yes -- jump ahead
314 CMP R1,#vType_string ;Or a string?
315 MOVNE R0,#err_arrayBad
316 BNE error_report
317
318 ; --- Display a string ---
319
320 LDR R2,tsc_stracc ;Get the stracc address
321 LDR R2,[R2]
322 ADD R2,R2,R0,LSR #8 ;Point to the string
323 AND R3,R0,#&FF ;Get the length
324 BL termite__doSpool ;Maybe spool this lot
325 TCALL termite_sendLocal ;Write out the message
326 BL termite__error ;Handle possible error
327 BL stracc_free ;Free the string from stracc
328 B %20termite_lecho ;Jump ahead
329
330 ; --- Display an integer on the screen ---
331
332 10termite_lecho ADR R1,tsc_misc ;Point to a nice buffer
333 MOV R2,#256 ;The buffer is big
334 SWI OS_ConvertInteger4 ;Convert the number to a str
335 SUB R3,R1,R0 ;Get the length
336 MOV R2,R0 ;Point at the block
337 BL termite__doSpool ;Maybe spool this lot
338 TCALL termite_sendLocal ;Write out the message
339 BL termite__error ;Handle possible error
340
341 ; --- Maybe write out the return char ---
342
343 20termite_lecho CMP R9,#';' ;Is there a semicolon now?
344 BLEQ getToken ;Yes -- get a token
345 BEQ interp_next ;...read another instr
346
347 LDR R2,tsc_bucket ;Get the bucket anchor
348 LDR R2,[R2]
349 LDR R0,tsc_lnewline ;Load the newline offset
350 CMP R0,#0 ;Is there one?
351 BEQ interp_next ;No -- stop here then
352 ADD R2,R2,R0 ;Point to the string
353 LDRB R3,[R2,#-1] ;Load out the length
354 BL termite__doSpool ;Maybe spool this lot
355 TCALL termite_sendLocal ;Write out the terminator
356 BL termite__error ;Handle possible error
357 B interp_next ;And read another instruction
358
359 ; --- Handle the options ---
360
361 50termite_lecho LDR R0,tsc_flags ;Load the flags word
362 BIC R0,R0,#tscFlag_echoLR+tscFlag_echoLL
363 CMP R9,#tok_local ;Do we require local echoing?
364 CMPNE R9,#tok_both
365 ORREQ R0,R0,#tscFlag_echoLL ;Yes -- set the flag
366 CMP R9,#tok_remote ;Do we require remote echos?
367 CMPNE R9,#tok_both
368 ORREQ R0,R0,#tscFlag_echoLR ;Yes -- set the flag
369 STR R0,tsc_flags ;Store back the flags word
370 BL getToken ;Get another token
371
372 B interp_next ;Keep on going then!
373
374 LTORG
375
376 ; -- termite_linput ---
377
378 EXPORT termite_linput
379 termite_linput ROUT
380
381 MOV R0,#1 ;Read an lvalue
382 BL express_read ;Read it in
383
384 ; --- Now enter a string reading loop ---
385
386 BL stracc_ensure ;Make sure that there's room
387 MOV R2,R0 ;Look after address
388 MOV R4,R0 ;Twice
389 MOV R5,#0 ;The length so far
390 MOV R3,#1 ;Length of buffer to echo
391
392 00
393 TCALL termite_readLocal ;Read a byte from the buffer
394 CMP R0,#-1 ;Was there one?
395 BLEQ tsc_wait ;No -- wait for it then
396 LDREQ R2,tsc_stracc
397 LDREQ R2,[R2]
398 ADDEQ R2,R2,R1,LSR #8
399 ADDEQ R2,R2,R5
400 BEQ %b00
401 CMP R0,#127 ;Is this a delete?
402 CMPNE R0,#8
403 BEQ %f05 ;Yes -- deal with that then
404 CMP R0,#32 ;Was it valid?
405 STRGEB R0,[R2,#0] ;Yes -- store the byte
406 BLGE termite_doLEcho ;Echo the buffer
407 ADDGE R2,R2,#1 ;Increment the pointer
408 ADDGE R5,R5,#1 ;Increment the length
409 CMP R0,#13 ;Are we finished?
410 CMPNE R5,#256
411 BLT %b00 ;No -- get some more then
412 B %f10 ;Finished -- jump ahead
413
414 ; --- Do a delete operation ---
415
416 05 CMP R5,#0 ;Is the buffer empty?
417 BLE %b00 ;Yes -- do nothing
418 MOV R14,#8 ;Get a backspace
419 STRB R14,[R2,#0] ;Store it...
420 STRB R14,[R2,#2] ;In two places
421 MOV R14,#32 ;And a space too
422 STRB R14,[R2,#1] ;Put that in the middle
423 MOV R3,#3 ;Send 3 characters
424 BLGE termite_doLEcho ;Echo the buffer
425 SUB R2,R2,#1 ;Reduce the address
426 SUB R5,R5,#1 ;And the number of chars
427 MOV R3,#1 ;Put R3 back to 1
428 B %b00 ;Join main loop again
429
430 ; --- We have finished reading the string ---
431
432 10 ORR R0,R1,R5 ;Get the rvalue
433 MOV R1,#vType_string ;This is a string
434 BL stracc_added ;Tell stracc about this
435 MOV R3,R1 ;Move these up a little
436 MOV R2,R0
437 BL express_pop ;Get my lvalue off
438 BL ctrl_store ;Store this away
439 B interp_next ;Do another command
440
441 LTORG
442
443 ; --- termite_lnewline ---
444
445 EXPORT termite_lnewline
446 termite_lnewline ROUT
447
448 CMP R9,#'=' ;Next char must be `='
449 MOVNE R0,#err_expEq ;If it isn't, moan
450 BNE error_report
451 BL getToken ;Skip past the equals sign
452
453 LDR R0,tsc_lnewline ;Get existing offset
454 BL strBucket_free ;Free it
455 MOV R0,#0 ;Prepare to read rvalue
456 BL express_read ;Read it then
457 BL express_pop ;Pop it off the stack
458 CMP R1,#vType_string ;Is it a string?
459 MOVNE R0,#err_strNeeded ;No -- get error number
460 BNE error_report ;And report the error
461 BL termite__storeStr ;Store in the bucket
462 STR R0,tsc_lnewline ;Store the new offset
463 B interp_next ;And do the next instruction
464
465 ; --- termite_log ---
466
467 EXPORT termite_log
468 termite_log ROUT
469
470 ; --- Load the first parameter ---
471
472 MOV R0,#0 ;Read an rvalue
473 BL express_read ;Read it then
474 BL express_pop ;And get it off the stack
475 CMP R1,#vType_string ;Is this a string?
476 MOVNE R0,#err_strNeeded ;Nope -- get error number
477 BNE error_report ;...and report the error
478
479 LDR R1,tsc_stracc ;Get the stracc address
480 LDR R1,[R1]
481 ADD R1,R1,R0,LSR #8 ;Point to the string
482 AND R2,R0,#&FF ;Get the length
483
484 MOV R5,R0 ;Look after the rvalue
485 ADR R0,tsc_misc ;Point to the misc buffer
486 BL termite_copyString ;Copy the string over
487 TCALL termite_logFileAdd ;Add the string to the log
488 BL termite__error ;Handle possible error
489 MOV R0,R5 ;Get the rvalue back
490 BL stracc_free ;Free it from stracc
491 B interp_next ;Return to main loop
492
493 LTORG
494
495 ; --- termite_newsession ---
496
497 EXPORT termite_newsession
498 termite_newsession ROUT
499
500 ; --- Read the base name ---
501
502 MOV R0,#0 ;Read an rvalue
503 BL express_read ;Read it then
504 BL express_pop ;Get the rvalue
505 CMP R1,#vType_string ;Is it a string?
506 MOVNE R0,#err_numNeeded ;No -- get the error number
507 BNE error_report ;And report the error
508
509 ; --- NULL terminate it ---
510 ;
511 ; We rely on the fact that there can't be anything else
512 ; after this string. It is also important that we remember
513 ; the stracc offset of this string, so that all the strings
514 ; can be removed from stracc in one go.
515
516 MOV R3,R1 ;Look after the offset
517 MOV R5,#0 ;Useful, t' be sure
518 BL stracc_ensure ;Ensure we have space
519 STRB R5,[R0,#0] ;Terminate the string
520 ORR R0,R1,#1 ;Get the rvalue
521 BL stracc_added ;Tell stracc about terminator
522
523 ; --- Read the sub-style name ---
524
525 MOV R0,#0 ;Read an rvalue
526 BL express_read ;Read it then
527 BL express_pop ;Get the rvalue
528 CMP R1,#vType_string ;Is it a string?
529 MOVNE R0,#err_numNeeded ;No -- get the error number
530 BNE error_report ;And report the error
531
532 ; --- NULL terminate it ---
533
534 MOV R6,R1 ;Look after the offset
535 BL stracc_ensure ;Ensure we have space
536 STRB R5,[R0,#0] ;Terminate the string
537 ADD R4,R1,#(1<<8) ;The next string will go here
538 ORR R0,R1,#1 ;Get the rvalue
539 BL stracc_added ;Tell stracc about terminator
540
541 ; --- Now we keep on adding strings to the list ---
542
543 05 CMP R9,#',' ;Do we have a comma?
544 BNE %50termite_newsession ;No -- do the deed then
545 BL getToken ;Skip over the comma
546
547 MOV R0,#0 ;Read an rvalue
548 BL express_read ;Read it then
549 BL express_pop ;Pop off the string
550 CMP R1,#vType_dimStr ;Is this a string array?
551 BEQ %10termite_newsession ;Yes -- jump ahead
552 CMP R1,#vType_string ;Is it a string?
553 MOVNE R0,#err_strNeeded ;No -- get the error number
554 BNE error_report ;And report the error
555
556 ; --- We have a string then ---
557
558 CMP R0,#0 ;Does it have a length?
559 BEQ %05termite_newsession ;No -- find another one then
560 BL stracc_ensure ;Ensure we have space
561 STRB R5,[R0,#0] ;Terminate the string
562 ORR R0,R1,#1 ;Get the rvalue
563 BL stracc_added ;Tell stracc about terminator
564 B %05termite_newsession ;Find another string
565
566 ; --- We have a string array ---
567
568 10 MOV R3,R0 ;Look after rvalue
569 MOV R2,#0 ;Start from the beginning
570 15 MOV R1,R3 ;Put it in R1
571 BL termite__enumArray ;Get an element
572 BCC %05termite_newsession ;No more, get another string
573 ANDS R14,R0,#&FF ;Get the length
574 BEQ %15termite_newsession ;Zero -- get another one then
575 BL stracc_ensure ;Ensure we have space
576 STRB R5,[R0,#0] ;Terminate the string
577 ORR R0,R1,#1 ;Get the rvalue
578 BL stracc_added ;Tell stracc about terminator
579 B %15termite_newsession ;Find another element
580
581 ; --- All the strings are in stracc now ---
582 ;
583 ; First, we terminate the list
584
585 50 BL stracc_ensure ;Ensure we have space
586 STRB R5,[R0,#0] ;Terminate the string
587 ORR R0,R1,#1 ;Get the rvalue
588 BL stracc_added ;Tell stracc about terminator
589
590 ; --- Now, point to the strings ---
591
592 LDR R5,tsc_stracc ;Load stracc anchor
593 LDR R5,[R5]
594 ADD R0,R5,R3,LSR #8 ;Point to the base name
595 ADD R1,R5,R6,LSR #8 ;Point to the sub-style
596 ADD R2,R5,R4,LSR #8 ;Point to strings
597
598 TCALL termite_newSession ;Open the session
599 BL termite__error ;Handle possible error
600
601 MOV R0,R3 ;Put the offset in R0
602 BL stracc_free ;Free all those strings!
603 B interp_next ;Do the next instruction
604
605 LTORG
606
607 ; --- termite_oscli ---
608
609 EXPORT termite_oscli
610 termite_oscli ROUT
611
612 ; --- Read a parameter ---
613
614 MOV R0,#0 ;Read an rvalue
615 BL express_read ;Read it then
616 BL express_pop ;And get it off the stack
617 CMP R1,#vType_string ;Is this a string?
618 MOVNE R0,#err_strNeeded ;Nope -- get error number
619 BNE error_report ;...and report the error
620
621 LDR R1,tsc_stracc ;Get the stracc address
622 LDR R1,[R1]
623 ADD R1,R1,R0,LSR #8 ;Point to the string
624 AND R2,R0,#&FF ;Get the length
625
626 MOV R5,R0 ;look after the rvalue
627 ADR R0,tsc_misc ;Point to the misc buffer
628 BL termite_copyString ;Copy the string over
629 SWI Wimp_StartTask ;Do the command
630 MOV R0,R5 ;Get the rvalue back
631 BL stracc_free ;Free the string from stracc
632 B interp_next ;Continue happily
633
634 LTORG
635
636 ; --- termite_rclear ---
637
638 EXPORT termite_rclear
639 termite_rclear ROUT
640
641 TCALL termite_clearRemote ;Clear the buffer
642 B interp_next ;And go for more
643
644 LTORG
645
646 ; --- termite_recho ---
647
648 EXPORT termite_recho
649 termite_recho ROUT
650
651 CMP R9,#tok_off ;Is this an option thingy?
652 CMPNE R9,#tok_local
653 CMPNE R9,#tok_remote
654 CMPNE R9,#tok_both
655 BEQ %50termite_recho ;Yes -- deal seperately
656
657 ; --- Just echo the result to the screen then ---
658
659 MOV R0,#0 ;Read an rvalue
660 BL express_read ;Read the next expression
661 BL express_pop ;Get the value in R0,R1
662 CMP R1,#vType_integer ;Is this an integer?
663 BEQ %10termite_recho ;Yes -- jump ahead
664 CMP R1,#vType_string ;Or a string?
665 MOVNE R0,#err_arrayBad
666 BNE error_report
667
668 ; --- Display a string ---
669
670 LDR R2,tsc_stracc ;Get the stracc address
671 LDR R2,[R2]
672 ADD R2,R2,R0,LSR #8 ;Point to the string
673 AND R3,R0,#&FF ;Get the length
674 TCALL termite_sendRemote ;Write out the message
675 BL termite__error ;Handle possible error
676 BL stracc_free ;Free the string from stracc
677 B %20termite_recho ;Maybe write out return char
678
679 ; --- Display an integer on the screen ---
680
681 10termite_recho ADR R1,tsc_misc ;Point to a nice buffer
682 MOV R2,#256 ;The buffer is big
683 SWI OS_ConvertInteger4 ;Convert the number to a str
684 SUB R3,R1,R0 ;Get the length
685 MOV R2,R0 ;Point at the block
686 TCALL termite_sendRemote ;Write out the message
687 BL termite__error ;Handle possible error
688
689 ; --- Maybe write out the return char ---
690
691 20termite_recho CMP R9,#';' ;Is there a semicolon now?
692 BLEQ getToken ;Yes -- get a token
693 BEQ interp_next ;...read another instr
694
695 LDR R2,tsc_bucket ;Get the bucket anchor
696 LDR R2,[R2]
697 LDR R0,tsc_rnewline ;Load the newline offset
698 CMP R0,#0 ;Is there one?
699 BEQ interp_next ;No -- stop here then
700 ADD R2,R2,R0 ;Point to the string
701 LDRB R3,[R2,#-1] ;Load out the length
702 TCALL termite_sendRemote ;Write out the terminator
703 BL termite__error ;Handle possible error
704 B interp_next ;And read another instruction
705
706 ; --- Handle the options ---
707
708 50termite_recho LDR R0,tsc_flags ;Load the flags word
709 BIC R0,R0,#tscFlag_echoRR+tscFlag_echoRL
710 CMP R9,#tok_local ;Do we require local echoing?
711 CMPNE R9,#tok_both
712 ORREQ R0,R0,#tscFlag_echoRL ;Yes -- set the flag
713 CMP R9,#tok_remote ;Do we require remote echos?
714 CMPNE R9,#tok_both
715 ORREQ R0,R0,#tscFlag_echoRR ;Yes -- set the flag
716 STR R0,tsc_flags ;Store back the flags word
717 BL getToken ;Get another token
718
719 B interp_next ;Keep on going then!
720
721 LTORG
722
723 ; --- termite_report ---
724
725 EXPORT termite_report
726 termite_report ROUT
727
728 ; --- Read a parameter ---
729
730 MOV R0,#0 ;Read an rvalue
731 BL express_read ;Read it then
732 BL express_pop ;And get it off the stack
733 CMP R1,#vType_string ;Is this a string?
734 MOVNE R0,#err_strNeeded ;Nope -- get error number
735 BNE error_report ;...and report the error
736
737 LDR R1,tsc_stracc ;Get the stracc address
738 LDR R1,[R1]
739 ADD R1,R1,R0,LSR #8 ;Point to the string
740 AND R2,R0,#&FF ;Get the length
741
742 MOV R5,R0 ;look after the rvalue
743 ADR R0,tsc_misc ;Point to the misc buffer
744 BL termite_copyString ;Copy the string over
745 TCALL termite_printMessage ;Report the message
746 MOV R0,R5 ;Get the rvalue back
747 BL stracc_free ;Free the string from stracc
748 B interp_next ;Continue happily
749
750 LTORG
751
752 ; --- termite_rinput ---
753
754 EXPORT termite_rinput
755 termite_rinput ROUT
756
757 MOV R0,#1 ;Read an lvalue
758 BL express_read ;Read it in
759
760 ; --- Now enter a string reading loop ---
761
762 BL stracc_ensure ;Make sure that there's room
763 MOV R2,R0 ;Look after address
764 MOV R4,R0 ;Twice
765 MOV R5,#0 ;The length so far
766 MOV R3,#1 ;Length of buffer to echo
767
768 00
769 TCALL termite_checkCarrier ;Get current carrier state
770 CMP R0,#0 ;Is there one?
771 MOVEQ R0,#0 ;No, return ""
772 BEQ %90termite_rinput ;And jump ahead
773
774 TCALL termite_readRemote ;Read a byte from the buffer
775 CMP R0,#-1 ;Was there one?
776 BLEQ tsc_wait ;No -- wait for it then
777 LDREQ R2,tsc_stracc
778 LDREQ R2,[R2]
779 ADDEQ R2,R2,R1,LSR #8
780 ADDEQ R2,R2,R5
781 BEQ %b00
782 CMP R0,#127 ;Is this a delete?
783 CMPNE R0,#8
784 BEQ %f05 ;Yes -- deal with that then
785 CMP R0,#32 ;Was it valid?
786 STRGEB R0,[R2,#0] ;Yes -- store the byte
787 BLGE termite_doREcho ;Echo the buffer
788 ADDGE R2,R2,#1 ;Increment the pointer
789 ADDGE R5,R5,#1 ;Increment the length
790 CMP R0,#13 ;Are we finished?
791 CMPNE R5,#256
792 BLT %b00 ;No -- get some more then
793 B %f10 ;Finished -- jump ahead
794
795 ; --- Do a delete operation ---
796
797 05 CMP R5,#0 ;Is the buffer empty?
798 BLE %b00 ;Yes -- do nothing
799 MOV R14,#8 ;Get a backspace
800 STRB R14,[R2,#0] ;Store it...
801 STRB R14,[R2,#2] ;In two places
802 MOV R14,#32 ;And a space too
803 STRB R14,[R2,#1] ;Put that in the middle
804 MOV R3,#3 ;Send 3 characters
805 BLGE termite_doREcho ;Echo the buffer
806 SUB R2,R2,#1 ;Reduce the address
807 SUB R5,R5,#1 ;And the number of chars
808 MOV R3,#1 ;Put R3 back to 1
809 B %b00 ;Join main loop again
810
811 ; --- We have finished reading the string ---
812
813 10 ORR R0,R1,R5 ;Get the rvalue
814 90 MOV R1,#vType_string ;This is a string
815 BL stracc_added ;Tell stracc about this
816 MOV R3,R1 ;Move these up a little
817 MOV R2,R0
818 BL express_pop ;Get my lvalue off
819 BL ctrl_store ;Store this away
820 B interp_next ;Do another command
821
822 LTORG
823
824 ; --- termite_rnewline ---
825
826 EXPORT termite_rnewline
827 termite_rnewline ROUT
828
829 CMP R9,#'=' ;Next char must be `='
830 MOVNE R0,#err_expEq ;If it isn't, moan
831 BNE error_report
832 BL getToken ;Skip past the equals sign
833
834 LDR R0,tsc_rnewline ;Get existing offset
835 BL strBucket_free ;Free it
836 MOV R0,#0 ;Prepare to read rvalue
837 BL express_read ;Read it then
838 BL express_pop ;Pop it off the stack
839 CMP R1,#vType_string ;Is it a string?
840 MOVNE R0,#err_strNeeded ;No -- get error number
841 BNE error_report ;And report the error
842 BL termite__storeStr ;Store inthe bucket
843 STR R0,tsc_rnewline ;Store the new offset
844 B interp_next ;And do the next instruction
845
846 ; --- termite_spool ---
847
848 EXPORT termite_spool
849 termite_spool ROUT
850
851 CMP R9,#10 ;Is this a newline?
852 CMPNE R9,#':' ;Or a colon
853 CMPNE R9,#&FF ;Or the end of the file?
854 CMPNE R9,#tok_else ;Or an else
855 BEQ %50 ;Yes -- turn off spooling
856
857 ; --- Turn on spooling ---
858 ;
859 ; Ooh, spooling, I really dig you.
860
861 MOV R0,#0 ;Read an rvalue
862 BL express_read ;Read the expression
863 BL express_pop ;Pop the result
864 CMP R1,#vType_string ;Do we have a string?
865 MOVNE R0,#err_strNeeded ;No -- moan at thick user
866 BNE error_report ;Do that then
867
868 ; --- Copy the string to the misc buffer ---
869
870 LDR R1,tsc_stracc ;Find the stracc buffer
871 LDR R1,[R1,#0] ;Load the pointer out
872 MOV R2,R0 ;Look after the rvalue
873 ADD R0,R1,R0,LSR #8 ;Find the string base
874 AND R1,R2,#&FF ;And get the length
875 ADR R3,tsc_misc ;Point to destination buffer
876 00 LDRB R14,[R0],#1 ;Load byte from string
877 STRB R14,[R3],#1 ;Store in destination
878 SUBS R1,R1,#1 ;Decrement the counter
879 BGT %b00 ;And carry on going
880 MOV R14,#0 ;Terminate the string
881 STRB R14,[R3],#1 ;Stick that on the end
882
883 MOV R0,R2 ;Find the string rvalue
884 BL stracc_free ;Remove it from stracc
885
886 ; --- Make sure we're not spooling right now ---
887
888 LDR R1,tsc_spool ;Load the current handle
889 CMP R1,#0 ;Are we spooling?
890 MOVNE R0,#0 ;Yes -- close current file
891 SWINE XOS_Find ;So do that then
892
893 ; --- Now open the file ---
894
895 MOV R0,#&8F ;Give me lots of errors
896 ADR R1,tsc_misc ;Point to the buffer
897 SWI XOS_Find ;Find a file handle for it
898 BVS error_reportReal ;If failed, report the error
899 STR R0,tsc_spool ;Save the file handle
900 B interp_next ;Now do another instruction
901
902 ; --- Close the current file ---
903
904 50termite_spool LDR R1,tsc_spool ;Load the current handle
905 CMP R1,#0 ;Are we spooling?
906 MOVNE R0,#0 ;Yes -- close current file
907 SWINE XOS_Find ;So do that then
908 BVS error_reportReal
909 MOV R14,#0 ;Get a zero value
910 STR R14,tsc_spool ;Clear the file handle
911 B interp_next ;Now do another instruction
912
913 LTORG
914
915 ; --- termite_syscall ---
916
917 EXPORT termite_syscall
918 termite_syscall ROUT
919
920 BL ctrl_setUpRegs ;Set up the regs then
921
922 CMP R10,#vType_string ;Is this a string?
923 LDREQ R14,tsc_stracc ;Yes -- load the stracc addr#
924 LDREQ R14,[R14] ;Grrrr...
925 ADDEQ R9,R14,R9,LSR #8 ;Point to the string
926 MOVEQ R14,PC ;Yes -- set up return address
927 ADDEQ PC,R11,#termite_sysNumString
928 BVS error_reportReal ;Report possible error
929 CMPNE R10,#vType_integer ;Is this an integer?
930 MOVNE R0,#err_arrayBad ;No -- get error number
931 BNE error_report ;...and report the error
932
933 TCALL termite_sysCall ;Call the call then!
934
935 ADR R10,termite__retned ;Point to some space
936 STMIA R10!,{R0-R8} ;Store returned registers
937 MOV R14,PC,LSR #28 ;Get the flags
938 STMIA R10!,{R14} ;Strore the flags too
939
940 ; --- Convert the string if needed ---
941
942 LDMFD R13!,{R7-R12} ;Load back position info
943 LDMFD R13!,{R0} ;Load stracc offset
944 BL stracc_free ;Free any strings I had
945
946 ; --- We have now done the SYSCALL instr ---
947
948 ADR R0,termite__retned ;Point to the returned regs
949 BL ctrl_resolveRegs ;Do the other half now
950 B interp_next ;No error -- happy
951
952 termite__retned DCD 0,0,0,0,0,0,0,0,0,0,0 ;For SYSCALL, CALL
953
954 LTORG
955
956 ; --- termite_upload ---
957
958 EXPORT termite_upload
959 termite_upload ROUT
960
961 ; --- Read the protocol name ---
962
963 MOV R0,#0 ;Read an rvalue
964 BL express_read ;Read it then
965 BL express_pop ;Get the rvalue
966 CMP R1,#vType_string ;Is it a string?
967 MOVNE R0,#err_numNeeded ;No -- get the error number
968 BNE error_report ;And report the error
969
970 ; --- NULL terminate it ---
971 ;
972 ; We rely on the fact that there can't be anything else
973 ; after this string. It is also important that we remember
974 ; the stracc offset of this string, so that all the strings
975 ; can be removed from stracc in one go.
976
977
978 MOV R3,R1 ;Look after the offset
979 MOV R5,#0 ;Useful, t' be sure
980 BL stracc_ensure ;Ensure we have space
981 STRB R5,[R0,#0] ;Terminate the string
982 ADD R4,R1,#(1<<8) ;The next string will go here
983 ORR R0,R1,#1 ;Get the rvalue
984 BL stracc_added ;Tell stracc about terminator
985
986 ; --- Now we keep on adding strings to the list ---
987
988 05 CMP R9,#',' ;Do we have a comma?
989 BNE %50termite_upload ;No -- do the deed then
990 BL getToken ;Skip over the comma
991
992 MOV R0,#0 ;Read an rvalue
993 BL express_read ;Read it then
994 BL express_pop ;Pop off the string
995 CMP R1,#vType_dimStr ;Is this a string array?
996 BEQ %10termite_upload ;Yes -- jump ahead
997 CMP R1,#vType_string ;Is it a string?
998 MOVNE R0,#err_strNeeded ;No -- get the error number
999 BNE error_report ;And report the error
1000
1001 ; --- We have a string then ---
1002
1003 CMP R0,#0 ;Does it have a length?
1004 BEQ %05termite_upload ;No -- find another one then
1005 BL stracc_ensure ;Ensure we have space
1006 STRB R5,[R0,#0] ;Terminate the string
1007 ORR R0,R1,#1 ;Get the rvalue
1008 BL stracc_added ;Tell stracc about terminator
1009 B %05termite_upload ;Find another string
1010
1011 ; --- We have a string array ---
1012
1013 10 MOV R3,R0 ;Look after rvalue
1014 MOV R2,#0 ;Start from the beginning
1015 15 MOV R1,R3 ;Put it in R1
1016 BL termite__enumArray ;Get an element
1017 BCC %05termite_upload ;No more, get another string
1018 ANDS R14,R0,#&FF ;Get the length
1019 BEQ %15termite_upload ;Zero -- get another one then
1020 BL stracc_ensure ;Ensure we have space
1021 STRB R5,[R0,#0] ;Terminate the string
1022 ORR R0,R1,#1 ;Get the rvalue
1023 BL stracc_added ;Tell stracc about terminator
1024 B %15termite_upload ;Find another element
1025
1026 ; --- All the strings are in stracc now ---
1027 ;
1028 ; First, we terminate the list
1029
1030 50 BL stracc_ensure ;Ensure we have space
1031 STRB R5,[R0,#0] ;Terminate the string
1032 ORR R0,R1,#1 ;Get the rvalue
1033 BL stracc_added ;Tell stracc about terminator
1034
1035 ; --- Now, point to the strings ---
1036
1037 LDR R1,tsc_stracc ;Load stracc anchor
1038 LDR R1,[R1]
1039 MOV R5,R3 ;Look after offset
1040 ADD R2,R1,R3,LSR #8 ;Point to the protocol name
1041 ADD R3,R1,R4,LSR #8 ;Point to files to upload
1042
1043 TCALL termite_upLoad ;Upload the files
1044 BL termite__error ;Handle possible error
1045
1046 MOV R0,R5 ;Put the offset in R0
1047 BL stracc_free ;Free all those strings!
1048 B interp_next ;Do the next instruction
1049
1050 LTORG
1051
1052 ; --- termite_wait ---
1053
1054 EXPORT termite_wait
1055 termite_wait ROUT
1056
1057 ; --- Read a parameter ---
1058
1059 MOV R0,#0 ;Read an rvalue
1060 BL express_read ;Read it then
1061 BL express_pop ;And get it off the stack
1062 CMP R1,#vType_integer ;Is this an integer
1063 MOVNE R0,#err_numNeeded ;Nope -- get error number
1064 BNE error_report ;...and report the error
1065
1066 MOV R1,R0 ;Remember this time
1067 SWI OS_ReadMonotonicTime ;Read the current time
1068 ADD R1,R1,R0 ;Return after this time
1069
1070 ; --- Now enter a waiting loop ---
1071
1072 00 SWI OS_ReadMonotonicTime ;Read the current time
1073 CMP R0,R1 ;Have we finished waiting?
1074 BLCC tsc_wait ;No -- wait some more
1075 BCC %b00 ;...and keep on looping
1076
1077 B interp_next ;Go round for next command
1078
1079 LTORG
1080
1081 ; --- termite_watchfor ---
1082
1083 EXPORT termite_watchfor
1084 termite_watchfor ROUT
1085
1086 ; --- See if we are ending the WATCHFOR ---
1087
1088 CMP R9,#tok_end ;Are we ending it?
1089 BEQ %70termite_watchfor ;Yes -- jump ahead
1090
1091 ; --- First, we must set up strings ---
1092 ;
1093 ; We actually store the strings in the strBucket.
1094 ; In the string list, we have a word for the pointer into
1095 ; the string list, and a byte for the match position so far.
1096
1097 MOV R5,#0 ;Number so far
1098 ADR R3,tsc_wForStrings ;Point to the block
1099 MOV R4,#0 ;For the match position
1100 STR R5,tsc_wForState ;Reset the state to 0
1101
1102 10 CMP R5,#32 ;Are we at the maximum?
1103 MOVGE R0,#err_WFTooMany ;Yes -- get error number
1104 BEQ error_report ;And report the error
1105
1106 ; --- Now read the strings one at a time ---
1107
1108 MOV R0,#0 ;Read an rvalue
1109 BL express_read ;Read it then
1110 BL express_pop ;Pop off this value
1111 CMP R1,#vType_dimStr ;Is this a string array?
1112 BNE %19termite_watchfor ;No -- jump ahead
1113
1114 ; --- We have a string array ---
1115
1116 MOV R1,R0 ;Put the array in R1
1117 MOV R2,#0 ;Start from the beginning
1118 00 BL termite__enumArray ;Get the next string
1119 BCC %15termite_watchfor ;No more -- jump ahead
1120 BL termite__storeStr ;Store the string
1121 CMP R9,#&7e ;Are we case insensitive?
1122 ORREQ R0,R0,#(1<<31) ;Yes -- set the flag
1123 STMIA R3!,{R0,R4} ;Store information
1124 ADD R5,R5,#1 ;Increment the counter
1125 B %b00 ;And keep doing this
1126
1127 ; --- The array has finished ---
1128
1129 15 CMP R9,#&7e ;Should we skip a token?
1130 BLEQ getToken ;Yes - do that then
1131 B %25termite_watchfor ;Jump ahead a little
1132
1133 ; --- See if it's a string then ---
1134
1135 19 CMP R1,#vType_string ;Is it a string?
1136 MOVNE R0,#err_strNeeded ;No -- get the error
1137 BNE error_report ;And then report it
1138
1139 ; --- We have a string in stracc ---
1140
1141 CMP R9,#&7e ;Case insensitive? (#'~')
1142 BLEQ getToken ;Yes -- skip over it
1143 20 BL termite__storeStr ;Put it in the bucket
1144 ORREQ R0,R0,#(1<<31) ;Set the top bit for insens
1145 STMIA R3!,{R0,R4} ;Store inforamtion
1146 ADD R5,R5,#1 ;Increment the counter
1147
1148 ; --- Do any more we have ---
1149
1150 25 CMP R9,#',' ;Do we have a comma
1151 BLEQ getToken ;Yes -- skip over it
1152 BEQ %10termite_watchfor ;...and then go round
1153 STR R5,tsc_wForNumber ;Store the number of strings
1154
1155 ; --- Now we must check the ring buffer ---
1156 ;
1157 ; We keep taking bytes off until either a match is achieved,
1158 ; we have read 255 chars or there are no more in the
1159 ; buffer. In any case we then on the buffer.
1160 ; If we have 255 chars we simply start all over again.
1161
1162 ADR R2,tsc_misc ;Point to the buffer
1163 MOV R3,#0 ;Number read so far
1164 00
1165 TCALL termite_readRemote ;Get a byte
1166 CMP R0,#-1 ;Was there a byte?
1167 BEQ %50termite_watchfor ;No -- jump ahead
1168 ADD R3,R3,#1 ;Increment the count
1169 STRB R0,[R2],#1 ;Store it in the buffer
1170 BL termite__checkWF ;Does this make a match?
1171 BCS %50termite_watchfor ;Yes -- jump ahead
1172 CMP R3,#255 ;Have we had 255 bytes now?
1173 BNE %b00 ;No -- keep on going then
1174
1175 ; --- Send on the buffer ---
1176
1177 ADR R2,tsc_misc ;Point to the buffer
1178 BL termite_doREcho ;Echo it appropriately
1179 MOV R3,#0 ;Reset the count to 0
1180 B %b00 ;And start all over again
1181
1182 ; --- We have stopped reading bytes ---
1183 ;
1184 ; Either we ran out of bytes, or we got a match,
1185 ; for either case we do the same thing
1186
1187 50 ADR R2,tsc_misc ;Point to the buffer
1188 BL termite_doREcho ;Echo it appropriately
1189 B interp_next ;Do the next instruction
1190
1191 ; --- We are ending the watchfor ---
1192
1193 70 BL getToken ;Gobble up the END
1194 BL termite__endWF ;End the WATCHFOR
1195 B interp_next ;Do the next command
1196
1197 LTORG
1198
1199 ; --- termite__endWF ---
1200 ;
1201 ; On entry: --
1202 ;
1203 ; On exit: --
1204 ;
1205 ; Use: Ends a WATCHFOR condition.
1206
1207 termite__endWF ROUT
1208
1209 STMFD R13!,{R0-R3,R14} ;Stack some regsiters
1210 ADR R1,tsc_wForStrings ;Point to the string list
1211 LDR R2,tsc_wForNumber ;Get the number of strings
1212 CMP R2,#0 ;Are there any?
1213 BEQ %f05 ;No -- jump ahead then
1214 MOV R3,R2,LSL #3 ;Multiply by 8
1215 ADD R1,R1,R3 ;Point just past the last one
1216 00 LDR R0,[R1,#-8]! ;Load out an offset
1217 BIC R0,R0,#(1<<31) ;Clear the flag
1218 BL strBucket_free ;Remove the string
1219 SUBS R2,R2,#1 ;Reduce the count
1220 BGT %b00 ;And free the rest
1221
1222 05 STR R2,tsc_wForNumber ;Make that clear
1223 LDMFD R13!,{R0-R3,PC}^ ;Return to caller
1224
1225 LTORG
1226
1227 ; --- termite__checkWF ---
1228 ;
1229 ; On entry: R0 == byte to check
1230 ;
1231 ; On exit: CS if that byte caused a match,
1232 ; CC otherwise
1233 ;
1234 ; Use: Tests all the strings in the WATCHFOR list, to see if
1235 ; the character caused a match. If it did, then WATCH
1236 ; is set.
1237
1238 termite__checkWF ROUT
1239
1240 STMFD R13!,{R0-R9,R14} ;Stack registers
1241 LDR R1,tsc_bucket ;Load the bucket anchor
1242 LDR R1,[R1,#0] ;Point to it
1243 ADR R2,tsc_wForStrings ;Point to the strings
1244 LDR R3,tsc_wForNumber ;Load the number of strings
1245
1246 ; --- Get the information on the string ---
1247
1248 00 LDR R7,[R2],#4 ;Load the offset
1249 CMP R7,#0 ;Is this one blank?
1250 ADDEQ R2,R2,#4 ;Yes -- skip over position
1251 BEQ %10termite__checkWF ;Zero length -- ignore
1252 BICS R4,R7,#(1<<31) ;Clear the 'insens' bit
1253 LDR R5,[R2],#4 ;Load position so far
1254 ADD R4,R1,R4 ;Point to the string
1255 LDRB R6,[R4,#-1] ;Load the string length
1256 ADD R4,R4,R5 ;Point to the character
1257
1258 ; --- Now do the comparison ---
1259
1260 02 LDRB R14,[R4,#0] ;Load the next byte
1261 MOV R9,R0 ;Put byte to comapre in R8
1262 TST R7,#(1<<31) ;Case insensitive?
1263 ORRNE R9,R9,#32 ;Yes -- make lower case
1264 ORRNE R14,R14,#32 ;Both of them
1265 CMP R9,R14 ;Are they the same?
1266 BEQ %05termite__checkWF ;Yes -- jump ahead
1267 CMP R5,#0 ;Was that the first char?
1268 SUB R4,R4,R5 ;Point to the string start
1269 MOV R5,#0 ;Put it back to 0
1270 BNE %02termite__checkWF ;No -- test first char
1271 STR R5,[R2,#-4] ;...store that back
1272 B %10termite__checkWF ;...jump ahead
1273
1274 ; --- The characters matched ---
1275
1276 05 ADD R5,R5,#1 ;Increment position
1277 CMP R5,R6 ;Has the string been done?
1278 BEQ %20termite__checkWF ;Yes -- we jump ahead then
1279 STR R5,[R2,#-4] ;Store the new position
1280
1281 ; --- Move onto the next string ---
1282
1283 10 SUBS R3,R3,#1 ;Decrement the string count
1284 BGT %00termite__checkWF ;And keep on looking
1285 LDMFD R13!,{R0-R9,R14} ;Load back registers
1286 BICS PC,R14,#C_flag ;And return to caller
1287
1288 ; --- We found a matching string ---
1289
1290 20 LDR R14,tsc_wForNumber ;Get teh number of strings
1291 SUB R14,R14,R3 ;Get index-1
1292 ADD R14,R14,#1 ;Get the index
1293 STR R14,tsc_wForState ;Store as the state
1294 BL termite__endWF ;End the current watchfor
1295 LDMFD R13!,{R0-R9,R14} ;Load back registers
1296 ORRS PC,R14,#C_flag ;And return to caller
1297
1298 LTORG
1299
1300 ; --- termite_remoteInput ---
1301 ;
1302 ; On entry: R0 == handle of script
1303 ; R2 == buffer containing bytes read
1304 ; R3 == number of bytes in buffer
1305 ; R11 == upcall block
1306 ;
1307 ; On exit: R2 == new buffer containing bytes to put into ring buffer
1308 ; R3 == number of bytes in this buffer
1309 ;
1310 ; Use: If we are not doing a watchfor, then this call will return
1311 ; immediately, resulting in all the buffer being sent
1312 ; to the ring buffer.
1313 ; If we are in a watchfor, then all data received, up until
1314 ; a match, is echoed immediatley, and not sent to the buffer.
1315
1316 EXPORT termite_remoteInput
1317 termite_remoteInput ROUT
1318
1319 STMFD R13!,{R14} ;Stack the link register
1320 LDR R14,[R0,#:INDEX:tsc_wForNumber]
1321 CMP R14,#0 ;Are we in a WATCHFOR?
1322 LDMEQFD R13!,{PC}^ ;No -- return AQAP then
1323
1324 STMFD R13!,{R0,R4,R5,R12} ;Stack some more registers
1325 MOV R12,R0 ;Put workspace in R12
1326 MOV R4,R2 ;Look after buffer address
1327 MOV R5,R3 ;Remember number of bytes
1328
1329 ; --- Scan the buffer ---
1330
1331 00 LDRB R0,[R4],#1 ;Load a byte
1332 SUB R5,R5,#1 ;Reduce the count
1333 BL termite__checkWF ;Does this cause a match
1334 BCS %10termite_remoteInput ;We have a match
1335 CMP R5,#0 ;Have we finished?
1336 BGT %b00 ;More to go -- loop
1337
1338 ; -- Send this buffer then ---
1339
1340 BL termite_doREcho ;Send the buffer
1341 MOV R3,#0 ;Put nothing in the buffer
1342 B %90termite_remoteInput ;And return to caller
1343
1344 ; --- We got a match ---
1345
1346 10 SUB R3,R3,R5 ;Get number to send
1347 BL termite_doREcho ;Send the buffer
1348 MOV R3,R5 ;Get bytes left
1349 MOV R2,R4 ;Point to rest of buffer
1350
1351 90 LDMFD R13!,{R0,R4,R5,R12,PC}^ ;Return to caller
1352
1353 LTORG
1354
1355 ;----- Utility routines -----------------------------------------------------
1356
1357 ; --- termite_copyString ---
1358 ;
1359 ; On entry: R0 == buffer to copy string to
1360 ; R1 == point to the string
1361 ; R2 == length of string to copy
1362 ;
1363 ; On exit: --
1364 ;
1365 ; Use: Copies the string into the buffer.
1366
1367 EXPORT termite_copyString
1368 termite_copyString ROUT
1369
1370 STMFD R13!,{R0-R2,R14} ;Stack registers
1371 CMP R2,#0 ;Is this a short string?
1372 00 LDRGTB R14,[R1],#1 ;Load a character
1373 STRGTB R14,[R0],#1 ;And then store it
1374 SUBS R2,R2,#1 ;Reduce the count
1375 BGT %b00 ;And keep on goin'
1376 MOV R14,#0 ;Get a terminator
1377 STRB R14,[R0],#1 ;Store the byte and return
1378 LDMFD R13!,{R0-R2,PC}^ ;Return to caller
1379
1380 LTORG
1381
1382 ; --- termite_doLEcho ---
1383 ;
1384 ; On entry: R2 == pointer to the buffer
1385 ; R3 == number of bytes to send
1386 ;
1387 ; On exit: --
1388 ;
1389 ; Use: Echos the buffer to local and remote according to the
1390 ; current flags, assuming the buffer came from the local input
1391
1392 EXPORT termite_doLEcho
1393 termite_doLEcho ROUT
1394
1395 STMFD R13!,{R0,R3,R14} ;Stack some registers
1396 LDR R0,tsc_flags ;Load the flags word
1397 TST R0,#tscFlag_echoLR ;Should we echo to remote?
1398 MOVNE R14,PC ;Yes -- set up return address
1399 ADDNE PC,R11,#termite_sendRemote ;...and send the bytes
1400 TST R0,#tscFlag_echoLL ;Should we echo to local?
1401 BLNE termite__doSpool ;Yes -- check for spooling
1402 MOVNE R14,PC ;Yes -- set up return address
1403 ADDNE PC,R11,#termite_sendLocal ;...and send the bytes
1404 LDMFD R13!,{R0,R3,PC}^ ;Return to caller
1405
1406 LTORG
1407
1408 ; --- termite_doREcho ---
1409 ;
1410 ; On entry: R2 == pointer to the buffer
1411 ; R3 == number of bytes to send
1412 ;
1413 ; On exit: --
1414 ;
1415 ; Use: Echos the buffer to local and remote according to the
1416 ; current flags, assuming the buffer came from remote input
1417
1418 EXPORT termite_doREcho
1419 termite_doREcho ROUT
1420
1421 STMFD R13!,{R0,R3,R14} ;Stack some registers
1422 LDR R0,tsc_flags ;Load the flags word
1423 TST R0,#tscFlag_echoRR ;Should we echo to remote?
1424 MOVNE R14,PC ;Yes -- set up return address
1425 ADDNE PC,R11,#termite_sendRemote ;...and send the bytes
1426 TST R0,#tscFlag_echoRL ;Should we echo to local?
1427 BLNE termite__doSpool ;Yes -- check for spooling
1428 MOVNE R14,PC ;Yes -- set up return address
1429 ADDNE PC,R11,#termite_sendLocal ;...and send the bytes
1430 LDMFD R13!,{R0,R3,PC}^ ;Return to caller
1431
1432 LTORG
1433
1434 ; --- termite__doSpool ---
1435 ;
1436 ; On entry: R2 == pointer to data to spool
1437 ; R3 == size of the data
1438 ;
1439 ; On exit: --
1440 ;
1441 ; Use: Maybe writes the data to the current spool file.
1442
1443 termite__doSpool ROUT
1444
1445 STMFD R13!,{R0-R4,R14} ;Save some registers
1446 LDR R1,tsc_spool ;Load the spool handle
1447 CMP R1,#0 ;Is spooling enabled?
1448 MOVNE R0,#2 ;Yes -- write to the file
1449 SWINE XOS_GBPB ;Do the write
1450 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
1451
1452 LTORG
1453
1454 ; --- termite__storeStr ---
1455 ;
1456 ; On entry: R0 == rvalue of string
1457 ;
1458 ; On exit: R0 == offset into bucket of string
1459 ;
1460 ; Use: Puts the string in stracc, into the string bucket.
1461
1462 termite__storeStr ROUT
1463
1464 STMFD R13!,{R1-R4,R14} ;Stack some registers
1465 MOV R2,R0 ;Put the string in R2
1466 MOV R4,R0 ;And in R4
1467 ANDS R0,R2,#&FF ;Get the length
1468 MOVEQ R0,#0 ;Zero length, get a zero
1469 BEQ %90termite__storeStr ;And return to caller
1470 BL strBucket_alloc ;Allocate the bucket
1471 LDR R3,tsc_stracc ;Load the bucket anchor
1472 LDR R3,[R3] ;This is getting annoying
1473 ADD R3,R3,R2,LSR #8 ;Point to the string
1474 AND R2,R2,#&FF ;Get the length
1475 00 LDRB R14,[R3],#1 ;Load a character
1476 STRB R14,[R0],#1 ;Copy it over
1477 SUBS R2,R2,#1 ;Reduce the counter
1478 BGT %b00 ;Keep on looping
1479 MOV R0,R4 ;Put the rvalue in R0
1480 BL stracc_free ;Remove it from stracc
1481 MOV R0,R1 ;Return offset in R0
1482
1483 90 LDMFD R13!,{R1-R4,PC}^ ;Return to caller
1484
1485 LTORG
1486
1487 ; --- termite__enumArray ---
1488 ;
1489 ; On entry: R1 == offset of array definition
1490 ; R2 == item to read next
1491 ;
1492 ; On exit: CS if item found, and
1493 ; R0 == rvalue of item
1494 ; R2 == updated
1495 ; CC otherwise
1496 ;
1497 ; Use: Goes through an string array, returning each item.
1498
1499 termite__enumArray ROUT
1500
1501 STMFD R13!,{R1,R3,R4,R14} ;Stack registers
1502 LDR R3,tsc_varTree ;Point at the tree
1503 LDR R3,[R3]
1504 ADD R0,R3,R1 ;Point at the array
1505 MOV R4,R2 ;Remember the count
1506 LDR R14,[R0,#8] ;Load number of items
1507 CMP R2,R14 ;Have we finished?
1508 BEQ %95termite__enumArray ;Yes -- return then
1509
1510 LDR R14,[R0,#4] ;Load number of subscripts
1511 ADD R0,R0,#12 ;Point to them
1512 ADD R0,R0,R14,LSL #2 ;Point past them
1513 ADD R0,R0,R2,LSL #2 ;Point at the item
1514 SUB R0,R0,R3 ;Make that an offset
1515 MOV R1,#vType_lvString ;The item is a string
1516 BL ctrl_load ;Load it out
1517 MOV R0,R2 ;Put the rvalue in R0
1518 ADD R2,R4,#1 ;Increment the item pos
1519
1520 LDMFD R13!,{R1,R3,R4,R14} ;Load back registers
1521 ORRS PC,R14,#C_flag ;And return success
1522
1523 95 LDMFD R13!,{R1,R3,R4,R14} ;Load back registers
1524 BICS PC,R14,#C_flag ;And return failure
1525
1526 LTORG
1527
1528 ; --- termite__error ---
1529 ;
1530 ; On entry: V flag and R0 determine error condition
1531 ;
1532 ; On exit: --
1533 ;
1534 ; Use: This call will generate an error, if ERROR ON has been
1535 ; done, or set the ERROR$ variable otherwise.
1536
1537 termite__error ROUT
1538
1539 STMFD R13!,{R0-R2,R14} ;Save regiters
1540 LDR R1,tsc_flags ;Load the fags word
1541 BVS %50termite__error ;Jump ahead if there's an err
1542
1543 ; --- There was no error ---
1544
1545 TST R1,#tscFlag_error ;Do we generate errors?
1546 BNE %90termite__error ;Yes -- just return then
1547
1548 ; --- Put a NULL string into ERROR$ ---
1549
1550 LDR R0,tsc_errorS ;Get the exesting offset
1551 BL strBucket_free ;Free it
1552 MOV R0,#0 ;Get a 0 length string
1553 STR R0,tsc_errorS ;Save that away
1554 B %90termite__error ;Return to caller
1555
1556 ; --- There was an error ---
1557
1558 50 TST R1,#tscFlag_error ;Do we generate errors?
1559 BNE error_reportReal ;Yes -- report the error then
1560
1561 ; --- Copy the string into ERROR$ ---
1562
1563 ADD R2,R0,#4 ;Put string pointer in R2
1564 LDR R0,tsc_errorS ;Get the exesting offset
1565 BL strBucket_free ;Free it
1566 MOV R1,R2 ;Point to the string
1567 MOV R0,#0 ;Current sting length
1568 00 LDRB R14,[R1],#1 ;Load a byte
1569 CMP R14,#0 ;Is it a NULL one?
1570 ADDNE R0,R0,#1 ;No -- increment the length
1571 BNE %b00 ;And keep on going
1572
1573 ; --- Now copy over the string ---
1574
1575 BL strBucket_alloc ;We need this much room
1576 STR R1,tsc_errorS ;Store this offset away
1577 00 LDRB R14,[R2],#1 ;Load a byte from string
1578 CMP R14,#0 ;Is this the end?
1579 STRNE R14,[R0],#1 ;No -- store in ERROR$
1580 BNE %b00 ;And keep doing this
1581
1582 ; --- Return to caller ---
1583
1584 90 LDMFD R13!,{R0-R2,PC}^ ;Return to caller
1585
1586 LTORG
1587
1588 ;----- That's all, folks ----------------------------------------------------
1589
1590 END