6 ; © 1995-1998 Straylight
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's core utilities (coreutils).
13 ; Coreutils is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
18 ; Coreutils is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
23 ; You should have received a copy of the GNU General Public License
24 ; along with Coreutils. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 ;----- Standard header ------------------------------------------------------
34 ;----- External dependencies ------------------------------------------------
38 ;----- Main code ------------------------------------------------------------
40 AREA |!!!Utility$$Code|,CODE,READONLY
44 ; On entry: R0 == pointer to command string
45 ; R1 == pointer to command tail
47 ; On exit: May return an error
49 ; Use: Performs a test, and does things appropriately.
53 STR R14,test_return ;Save the return address
55 ; --- Read the command line arguments ---
57 ADR R0,test_syntaxDef ;Find the definitions
58 ADR R2,test_args ;Point to argument buffer
59 MOV R3,#252 ;Get the buffer size
60 SWI XOS_ReadArgs ;Read the arguments
61 BVS test_error ;If it failed, return now
63 ; --- Check for some easy cases ---
65 LDR R14,tArg_help ;Load the help switch
66 CMP R14,#0 ;Is it enabled?
67 BNE test_help ;Yes -- give some help then
69 ; --- Sort out the test ---
71 ADR R0,tArg_file ;Point to file arg
72 ADR R1,tArg_exists ;And to the limit
73 BL test_which ;Which one is set?
74 ADRCC R0,test_noTest ;None -- point to error
75 BCC test_error ;And complain then
76 MOV R2,R0 ;Look after this
78 ADR R0,tArg_exists ;Point to file qualifiers
79 ADR R1,tArg_limit ;And to the very end
80 BL test_which ;Which one is set?
81 CMP R2,#0 ;Is this a file?
82 CMPNE R0,#-1 ;No -- make sure no quals
83 ADRNE R0,test_badQuals ;If there are, find error
84 BNE test_error ;And complain
85 MOV R10,R0 ;Look after this
87 ; --- Dispatch the test ---
89 MOV R14,PC ;Set up return address
90 ADD PC,PC,R2,LSL #2 ;Dispatch
91 B %f00 ;And continue when done
93 B test_file ;Handle a file test
94 B test_expr ;Handle an expression test
95 B test_key ;Handle a key test
96 B test_riscOs ;Handle an OS version test
97 B test_command ;Handle a command test
98 B test_true ;Handle a true test
99 B test_false ;Handle a false test
101 ; --- Now handle the results ---
103 00 LDR R14,tArg_multiLine ;Is this a multiline?
104 CMP R14,#0 ;Is the switch there?
105 BNE %50main ;Yes -- handle that then
106 CMP R0,#0 ;Was the condition true?
107 LDRNE R0,tArg_then ;Yes -- find then clause
108 LDREQ R0,tArg_else ;No -- find else clause
109 CMP R0,#0 ;Is the clause defined?
110 SWINE XOS_CLI ;Yes -- do it then
111 BVS test_error ;If it failed, die horribly
112 B test_end ;Otherwise end nicely
114 ; --- Deal with a multiline ---
116 50 CMP R0,#0 ;Did the test succeed?
117 ADR R0,test_uScore ;Point to variable name
118 ADRNE R1,test_vTrue ;Yes -- use true value
119 ADREQ R1,test_vFalse ;No -- use false value
120 BL test_setVar ;Set that up
122 ADR R0,test_else ;Point to variable name
123 ADRNE R1,test_eTrue ;Yes -- use true value
124 ADREQ R1,test_eFalse ;No -- use false value
125 BL test_setVar ;Set that up
127 ADR R0,test_endif ;Point to variable name
128 ADR R1,test_endVal ;Point to value
129 BL test_setVar ;Set that up
130 B test_end ;And return when done
132 test_uScore DCB "Alias$_",0
133 test_vTrue DCB "%*0",0
134 test_vFalse DCB "||",0
135 test_else DCB "Alias$Else",0
136 test_eTrue DCB "Set Alias$_ ||||",0
137 test_eFalse DCB "Set Alias$_ %%*0",0
138 test_endif DCB "Alias$EndIf",0
139 test_endVal DCB "Unset Alias$_|mUnset Alias$Else|m"
140 DCB "Unset Alias$EndIf",0
143 DCB "No condition to test",0
146 DCB "File qualifier found, but not -file test",0
149 test_syntaxDef DCB "help/s,"
172 ; On entry: R0 == pointer to base argument
173 ; R1 == pointer to limit argument
175 ; On exit: CS if an argument matched, and
176 ; R0 == index of argument chosen
180 ; Use: Works out which argument in a collection is actually chosen.
181 ; an error is raised if more than one is chosen.
185 STMFD R13!,{R1-R3,R14} ;Save some registers
186 MOV R2,R0 ;Look after base pointer
187 MOV R0,#-1 ;Initially, we have no choice
188 MOV R3,#-1 ;Initialise a counter
189 00 ADD R3,R3,#1 ;Increment the counter
190 CMP R2,R1 ;Finished scanning?
191 BEQ %10test_which ;Yes -- deal with that
192 LDR R14,[R2],#4 ;Load the argument
193 CMP R14,#0 ;Is this one enabled?
194 BEQ %b00 ;No -- ignore it then
195 CMP R0,#-1 ;Do we have a choice yet?
196 MOVEQ R0,R3 ;No -- we do now
197 BEQ %b00 ;So skip back again
199 ADR R0,test_badRadio ;Point to the error
200 B test_error ;And report it
202 10test_which CMP R0,#-1 ;Did we get an answer?
203 LDMFD R13!,{R1-R3,R14} ;Restore registers
204 ORRNES PC,R14,#C_flag ;Yes -- return C set
205 BICEQS PC,R14,#C_flag ;No -- return C clear
218 ; Use: Gives the user some help.
222 ADR R0,test_helpText ;Point to the help text
223 MOV R1,#0 ;Use the system dictionary
224 LDR R2,=version ;Find the version string
225 ADRL R14,main ;Point to the utility base
226 ADD R2,R14,R2 ;Relocate the pointer
227 SWI XOS_PrettyPrint ;Write the text out
228 B test_end ;And finish the program
230 test_helpText DCB "test ",27,0,13
232 DCB "Syntax: test <condition> <target>",13
234 DCB "Tests a condition and then performs an operation "
235 DCB "based on the result. Possible targets are:",13
237 DCB "[-then <command>] [-else <command>]",13
240 DCB "-then ... -else ... works as expected. "
241 DCB "-multiline defines a collection of alias "
242 DCB "commands, as follows:",13
244 DCB "_",9,9,"prefix normal commands with this",13
245 DCB "else",9,9,"toggles whether `_' executes commands",13
246 DCB "endif",9,9,"undefines `_', `else' and `endif'",13
248 DCB "Permitted tests are:",13
250 DCB "-file <file> <qualifier>",13
251 DCB "-expr <expression>",13
252 DCB "-key <key number>",13
253 DCB "-riscos <version number>",13
254 DCB "-command <*command>",13
255 DCB "-true | -false",13
257 DCB "The file qualifiers test various things about a "
260 DCB "-exists",9,9,"Ensure the file exists",13
261 DCB "-isDir",9,9,"Ensure it's a directory",13
262 DCB "-isFile",9,9,"Ensure it's a file",13
263 DCB "-isType <type>",9,"Ensure it's a file of given "
266 DCB "Key numbers are given either as internal key "
267 DCB "numbers (see sapphire:intKeys for bindings) or as "
268 DCB "BASIC-style -ve INKEY numbers",13
270 DCB "The -riscos test ensures that the current version "
271 DCB "of the OS is the same or later than that given.",13
273 DCB "The -command test runs a command and ensures that "
274 DCB "it didn't return an error. This may be useful "
275 DCB "just to suppress the error.",13
282 ; On entry: R10 == reason code
284 ; On exit: R0 == 0 if false, non-0 if true
287 ; Use: Performs a file operation and returns its truth.
291 ; --- Find the file information ---
293 MOV R0,#17 ;Read file information
294 LDR R1,tArg_file ;Get the filename
295 SWI XOS_File ;Try to get this information
296 MOVVS R0,#0 ;If failed, say not there
297 CMP R10,#0 ;Just checking existance?
298 CMPNE R0,#0 ;Or is the file not there?
299 MOVEQS PC,R14 ;Yes -- return now
301 CMP R10,#-1 ;Was one chosen?
302 ADDNE PC,PC,R10,LSL #2 ;Yes -- dispatch it
303 MOVS PC,R14 ;No op -- assume existance
305 MOVS PC,R14 ;Dealt with this already
306 B test_fDir ;Check it's a directory
307 B test_fFile ;Check it's a file
308 B test_fType ;Check its type
310 test_fDir AND R0,R0,#2 ;Leave only the dir bit
311 MOVS PC,R14 ;And return
313 test_fFile AND R0,R0,#1 ;Leave only the file bit
314 MOVS PC,R14 ;And return
316 test_fType ANDS R0,R0,#1 ;Test the file bit
317 MOVEQS PC,R14 ;If clear, skip on
318 MOV R3,R2,LSL #12 ;Look after the filetype
319 MOV R0,#31 ;Convert filetype name
320 LDR R1,tArg_isType ;Find the type string
321 SWI XOS_FSControl ;Try to convert it
322 BVS test_error ;Fail if we couldn't
323 CMP R2,R3,LSR #20 ;Compare the filetypes
324 MOVEQ R0,#1 ;If match, say true
325 MOVNE R0,#0 ;Otherwise say false
326 MOVS PC,R14 ;And return
334 ; On exit: R0 == 0 if false, non-0 if true
337 ; Use: Evaluates an expression and returns the result.
341 LDR R0,tArg_expr ;Find the expression result
342 B test_getValue ;Read the value
350 ; On exit: R0 == 0 if false, non-0 if true
353 ; Use: Tests a key on the keyboard.
355 test_key STMFD R13!,{R14} ;Save the link register
356 LDR R0,tArg_key ;Find the expression result
357 BL test_getValue ;Find the value
358 TST R0,#&80000000 ;Is the result negative?
359 EOREQ R0,R0,#&FF ;No -- then do that then
360 MOV R2,#&FF ;Scan for the key
361 AND R1,R0,#&FF ;Only have lowest byte
362 MOV R0,#&81 ;Get the OS_Byte code
363 SWI XOS_Byte ;Read the key pressedness
364 BVS test_error ;If it failed, return error
365 MOV R0,R1 ;Get the result
366 LDMFD R13!,{PC}^ ;And return
370 ; --- test_riscOs ---
374 ; On exit: R0 == 0 if false, and non-0 if true
377 ; Use: Returns the result of testing the OS version.
381 STMFD R13!,{R14} ;Save a register
382 LDR R0,tArg_riscOs ;Find the version string
383 BL test_getVersion ;Translate it for me
384 MOV R3,R0 ;Look after this result
386 MOV R0,#129 ;Read the OS version
387 MOV R1,#0 ;Want the OS version
388 MOV R2,#255 ;Still want it, dammit
389 SWI XOS_Byte ;Try to read it then
390 BVS test_error ;If it failed, report error
392 ADR R2,test_verTable ;Point to version table
393 MOV R0,#-1 ;Start off with bad value
394 00 LDMIA R2!,{R4,R5} ;Load the values out
395 CMP R4,R1 ;Does this version match?
396 MOVLE R0,R5 ;Yes -- use it then
397 BGT %b00 ;Otherwise loop back
399 CMP R0,R3 ;Compare with his version
400 MOVGE R0,#1 ;If later or same, return ok
401 MOVLT R0,#0 ;Otherwise return false
402 LDMFD R13!,{PC}^ ;And return to caller
404 test_verTable DCD &A5,350
414 ; --- test_command ---
418 ; On exit: R0 == 0 if false, non-0 if true
420 ; Use: Runs a command, and returns true if the command didn't
425 LDR R0,tArg_command ;Load the command string
426 SWI XOS_CLI ;Run the command
427 MOVVC R0,#1 ;If OK, return true
428 MOVVS R0,#0 ;Otherwise return false
429 MOVS PC,R14 ;And return to caller
433 ; --- test_true and test_false ---
437 ; On exit: R0 == 0 if false, non-0 if true
440 ; Use: Return particular values.
442 test_true MOV R0,#1 ;Return true
443 MOVS PC,R14 ;And return
445 test_false MOV R0,#0 ;Return false
446 MOVS PC,R14 ;And return
450 ; --- test_getValue ---
452 ; On entry: R0 == pointer to expression result
454 ; On exit: R0 == value read
456 ; Use: Reads the value of an expression from the OS_ReadArgs block.
460 STMFD R13!,{R1,R2,R14} ;Save some registers
461 LDRB R14,[R0],#1 ;Load the first byte
462 CMP R14,#0 ;Is this an integer?
463 ADRNE R0,test_notAnInt ;No -- then find error
464 BNE test_error ;And complain
465 AND R2,R0,#3 ;Find non-alignedness
466 BIC R0,R0,#3 ;Round down a little
467 LDMIA R0,{R0,R1} ;Load the value out
468 MOV R2,R2,LSL #3 ;Convert bits to bytes
469 RSB R14,R2,#32 ;And find the other shift
470 MOV R0,R0,LSR R2 ;Get the lower bits
471 ORR R0,R0,R1,LSL R14 ;And the upper bits
472 LDMFD R13!,{R1,R2,PC}^ ;And return to caller
475 DCB "Integer expected",0
479 ; --- test_getVersion ---
481 ; On entry: R0 == pointer to version string
483 ; On exit: R0 == value of version number-
485 ; Use: Reads a version umber
489 STMFD R13!,{R1,R2,R14} ;Save some registers
490 MOV R2,#0 ;Clear version accumulator
492 00 LDRB R1,[R0],#1 ;Load next byte from thing
493 SUB R14,R1,#'0' ;Convert digit to integer
494 CMP R14,#10 ;Is it in range?
495 ADDCC R2,R2,R2,LSL #2 ;Yes -- accumulate
496 ADDCC R2,R14,R2,LSL #1 ;Multiply by 10 and add
497 BCC %b00 ;And loop back round
499 ADD R2,R2,R2,LSL #2 ;Multiply version by 100
503 CMP R1,#'.' ;Is the character a dot?
504 BNE %f00 ;No -- skip on then
505 LDRB R1,[R0],#1 ;Load next byte from thing
506 SUB R14,R1,#'0' ;Convert digit to integer
507 CMP R14,#10 ;Is it in range?
508 ADDCC R14,R14,R14,LSL #2 ;Yes -- accumulate
509 ADDCC R2,R2,R14,LSL #1 ;Do it the other way round
510 LDRCCB R1,[R0],#1 ;Load next byte from thing
511 SUB R14,R1,#'0' ;Convert digit to integer
512 CMP R14,#10 ;Is it in range?
513 ADDCC R2,R2,R14 ;Yes -- add that on
514 LDRCCB R1,[R0],#1 ;Load next byte from thing
516 00 CMP R1,#&20 ;Is this the very end?
517 ADRCS R0,test_badVer ;Point to error message
518 BCS test_error ;And complain bitterly
519 MOV R0,R2 ;Get the version number
520 LDMFD R13!,{R1,R2,PC}^ ;And return to caller
523 DCB "Bad version number",0
527 ; --- test_setVar ---
529 ; On entry: R0 == variable name
530 ; R1 == pointer to value
534 ; Use: Sets the variable given to the given value.
538 STMFD R13!,{R0-R4,R14} ;Save some registers
539 MOV R2,R1 ;Point to the value
540 00 LDRB R14,[R2],#1 ;Load the next byte
541 CMP R14,#&20 ;Is this the end yet?
542 BCS %b00 ;No -- keep going
543 SUB R2,R2,R1 ;Find the string length
544 SUB R2,R2,#1 ;Don't count the terminator
545 MOV R3,#0 ;Start at the beginning
546 MOV R4,#0 ;Normal GS type variable
547 SWI XOS_SetVarVal ;Set the variable
548 BVS test_error ;If failed, abort
549 LDMFD R13!,{R0-R4,PC}^ ;And return to caller
559 ; Use: Returns to the operating system.
563 LDR R14,test_return ;Find the return address
564 BICS PC,R14,#V_flag ;And return with no error
570 ; On entry: R0 == pointer to error block
574 ; Use: Reports an error to the operating system.
578 LDR R14,test_return ;Find the return address
579 ORRS PC,R14,#V_flag ;And return the error
583 ;----- Workspace ------------------------------------------------------------
588 test_return # 4 ;Return address
590 test_args # 0 ;Argument output buffer
591 tArg_help # 4 ;Help switch
592 tArg_then # 4 ;Then command
593 tArg_else # 4 ;Else command
594 tArg_multiLine # 4 ;Multiline switch
595 tArg_file # 4 ;File condition
596 tArg_expr # 4 ;Expression condition
597 tArg_key # 4 ;Key condition
598 tArg_riscOs # 4 ;OS version condition
599 tArg_command # 4 ;Run a *command
600 tArg_true # 4 ;True condition
601 tArg_false # 4 ;False condition
602 tArg_exists # 4 ;Exists filetest
603 tArg_isDir # 4 ;IsDir filetest
604 tArg_isFile # 4 ;IsFile filetest
605 tArg_isType # 4 ;IsType filetest
606 tArg_limit # 4 ;End of the arguments
608 test_buffer EQU test_wStart+256 ;Misc buffer for things
610 ;----- That's all, folks ----------------------------------------------------