; ; cmdLine.s ; ; Command line parsing (MDW) ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Sapphire library. ; ; Sapphire is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2, or (at your option) ; any later version. ; ; Sapphire is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with Sapphire. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis ;----- Main code ------------------------------------------------------------ AREA |Sapphire$$Code|,CODE,READONLY ; --- cl_next --- ; ; On entry: R0 == pointer to a command line string (ctrl terminated) ; R1 == pointer to a buffer (may be equal to R0) ; ; On exit: CS if another word found, and ; R0 == updated past next word ; R1 preserved, buffer filled with null terminated string ; R2 == pointer to terminating null character ; else CC and ; R0 == pointer to terminating character ; R1 preserved, buffer preserved ; R2 corrupted ; ; Use: Extracts the next word from a command line string. If the ; string is in a writable buffer, you can set R1 == R0 to ; start with. You can build up a C-like argv array like this: ; ; ; R0 == pointer to command line in writable buffer ; ; MOV R1,R0 ; ADR R3,argv ; MOV R4,#0 ; loop BL cl_next ; MOVCC R1,#0 ; STR R1,[R3],#4 ; ADDCS R4,#0 ; BCS loop ; ; ; R0-R3 corrupted ; ; R4 == argc ; ; This routine will handle quoted strings, considering them ; to be single arguments. Either type of quote will do, ; quote doubling is required to insert quotes in quoted ; strings. EXPORT cl_next cl_next ROUT STMFD R13!,{R1,R3,R14} ;Save some registers MOV R2,R1 ;Set up buffer pointer MOV R1,#0 ;No quotes found yet MOV R3,#0 ;Various flags: ; b0 == written a character ; b1 == currently in quotes ; b2 == just closed quotes ; --- Skip past leading spaces --- 00cl_next LDRB R14,[R0],#1 ;Load a byte from the string CMP R14,#' ' ;Is it a space? CMPNE R14,#9 ;Or a tab will do too BEQ %00cl_next ;Yes -- get another character ; --- Main character reading loop --- 10cl_next CMP R14,#' ' ;Is it the string end? SUBLO R0,R0,#1 ;Keep ptr at ctrl char TSTEQ R3,#2 ;Are we currently in quotes? BLS %90cl_next ;No -- deal with it nicely CMP R14,R1 ;Is it the last quote char? BEQ %30cl_next ;Yes -- deal with this BIC R3,R3,#4 ;Last one wasn't a quote CMP R14,#'"' ;Is it a double quote? CMPNE R14,#''' ;Or a single one? TSTEQ R3,#2 ;Make sure not in quoted BEQ %20cl_next ;Yes -- deal with this then STRB R14,[R2],#1 ;Otherwise store the byte ORR R3,R3,#1 ;Remember we've done it LDRB R14,[R0],#1 ;Load a byte from the string B %10cl_next ;And go round again ; --- Handle a new quote character --- 20cl_next MOV R1,R14 ;Remember the quote character ORR R3,R3,#2 ;We're now in quotes LDRB R14,[R0],#1 ;Load a byte from the string B %10cl_next ;And go round again ; --- Handle a matched quote character --- ; ; Now this may be a close quote, or it may be a double quote ; to indicate a literal. We handle this by the following: ; ; if lastWasCloseQuotes ; write literal quote char ; set inQuotes ; clear lastWasCloseQuotes ; else if inQuotes ; clear inQuotes ; set lastWasCloseQuotes ; end 30cl_next TST R3,#6 ;Was last quote, or inQuotes? BEQ %20cl_next ;No -- then it's an open TST R3,#4 ;Was last one a quote? STRNEB R14,[R2],#1 ;Yes -- then store quote ORRNE R3,R3,#1 ;Remember we store something EOR R3,R3,#6 ;And toggle the bits nicely LDRB R14,[R0],#1 ;Load a byte from the string B %10cl_next ;Return to the loop ; --- We reached the end of the string --- 90cl_next TST R3,#1 ;Did we write any text? MOVNE R14,#0 ;A terminating null STRNEB R14,[R2],#0 ;If so, terminate the text LDMFD R13!,{R1,R3,R14} ;Unstack the registers ORRNES PC,R14,#C_flag ;If so, set C on exit BICEQS PC,R14,#C_flag ;Otherwise clear C LTORG ; --- cl_buildArgv --- ; ; On entry: R0 == command line string (writable) ; R1 == address of argv buffer ; ; On exit: R1 == next unused location in argv buffer ; ; Use: Turns the given string into an argv array which will make ; argument scanning easier. This is pretty much the code ; given in the description of cl_next. EXPORT cl_buildArgv cl_buildArgv ROUT STMFD R13!,{R0,R2,R3,R14} ;Save some registers MOV R3,R1 ;Move the argv address away MOV R1,R0 ;Point to output buffer ; --- Copy the argument pointers over --- 00 BL cl_next ;Fetch the next argument MOVCC R1,#0 ;If done, null terminate list STR R1,[R3],#4 ;Store the pointer away MOVCS R1,R0 ;More to come -- reset buffer BCS %b00 ;And loop around ; --- Tidy up and leave --- SUB R1,R3,#4 ;Point at terminating zero LDMFD R13!,{R0,R2,R3,PC}^ ;And return to caller LTORG ; --- cl_getopt --- ; ; On entry: R1 = pointer to ; ; On exit: ;----- That's all, folks ---------------------------------------------------- END