3Fermer5
FarewellLe 10/06/2013 à 23:32
J'ai fait un truc assez similaire pour PedroM ya quelques semaines tongue

On part du principe que pour un fichier X, le fichier system\X est son fichier de conf. Il contient les switches qu'on a la flemme de taper à chaque fois. Il supporte les commentaires (#blabla). Le rapport avec ton code, c'est que ça découpe le fichier en un tableau de strings, de la forme (int argc, const char** argv), puis ça le passe à une autre fonction de la lib qui sait traiter (argc, argv), en appelant les fonctions qui correspondent à chaque switch. Par contre, je gère pas les quotes... Pas bête ^^
pdtlib::ParseConfigFile
;=============================================================================== ; ; pdtlib::ParseConfigFile ; ; in a1 char** argv ; d0.b char comment char ; ; 4(sp) CMDLINE* cl ; 8(sp) void* Data ; 12(sp) char* SwitchesList ; 16(sp) ushort (*Error) (void* Data asm (a0), ; char* ErrorToken (a1)) ; 20(sp) ushort (*ArgSwitch1) (void* Data asm (a0), ; short Sign asm (d1.w) ; ) ; 24(sp) (*) ... ; ; out ; ; destroy std ; ; Parse the config file of the calling program ; ;=============================================================================== DEFINE pdtlib@0011 movem.l d3-d6/a2-a3,-(sp) ;----------------------------------------------------------------------- ; The reject string of strcspn is built dynamically, ; to include comment char ;----------------------------------------------------------------------- move.l #$20090D00,d4 ; Space, htab, EOL, NULL move.b d0,d4 ; Comment char ;----------------------------------------------------------------------- ; Write the config file name in a stack frame, stripping folder name ;----------------------------------------------------------------------- lea -18(sp),sp movea.l sp,a2 RAMT RAM_kernel::SystemDir \Dir: move.b (a0)+,(a2)+ bne.s \Dir subq.l #1,a2 movea.l (a1),a0 \Strip: move.b (a0)+,d0 bne.s \Bs movea.l (a1),a0 bra.s \File \Bs: cmpi.b #'\',d0 bne.s \Strip \File: move.b (a0)+,(a2)+ bne.s \File ;----------------------------------------------------------------------- ; Check the existence and the type of the file ;----------------------------------------------------------------------- movea.l sp,a0 suba.l a1,a1 moveq.l #$FFFFFFE0,d1 ; TEXT_TAG bsr CheckFileType tst.w d0 beq \NoConfigFile bmi \NotAText ;----------------------------------------------------------------------- ; Alloc a handle (same size than the file) ;----------------------------------------------------------------------- movea.l sp,a0 bsr GetFilePtr move.w (a0),-(sp) clr.w -(sp) ROMT HeapAlloc addq.l #4,sp move.w d0,d3 ; d3 = handle beq \Memory movea.w d3,a0 trap #3 movea.l a0,a2 ; a2 = handle ptr movea.l sp,a0 bsr GetFilePtr ; a0 = file ptr addq.l #4,a0 ;----------------------------------------------------------------------- ; Parse the file to write data in the buffer ;----------------------------------------------------------------------- moveq.l #1,d5 ; d5 = argc (1, beacause it contains the program name) \Loop: suba.l a1,a1 move.b d4,d0 bsr SkipDummyLines pea (a0) clr.w -(sp) ; Reject string termination move.l d4,-(sp) pea (sp) pea (a0) ROMT strcspn lea 14(sp),sp movea.l (sp)+,a0 subq.w #1,d0 bmi.s \EOF \Copy: move.b (a0)+,(a2)+ dbf.w d0,\Copy addq.w #1,d5 ; argc ++ clr.b (a0)+ bra.s \Loop \EOF: ;----------------------------------------------------------------------- ; Get size used in the handle, even it and add the size of argv table ;----------------------------------------------------------------------- move.l a2,d6 movea.w d3,a0 trap #3 sub.l a0,d6 ; used size addq.l #2,d6 ; size must be even bclr.b #0,d6 ; d6 = size of the handle, before argv table move.w d5,d0 add.w d0,d0 add.w d0,d0 add.l d6,d0 move.l d0,-(sp) move.w d3,-(sp) ROMT HeapRealloc addq.l #6,sp tst.w d0 beq.s \MemoryAndFree ;----------------------------------------------------------------------- ; Fill argv table. First ptr is ignored ;----------------------------------------------------------------------- movea.w d0,a0 trap #3 ; a0 = base handle ptr lea 0(a0,d6.l),a2 ; a2 = argv lea 4(a2),a1 move.w d5,d0 beq.s \Exec subq.w #1,d0 \ArgvLoop: move.l a0,(a1)+ \Skip: tst.b (a0)+ bne.s \Skip dbf.w d0,\ArgvLoop \Exec: ;----------------------------------------------------------------------- ; Prepare stack for ManageCmdline, and fill CMDLINE struct ;----------------------------------------------------------------------- lea 18(sp),sp movea.l (sp)+,a3 movea.l (sp),a0 move.w d5,ARGC(a0) move.l a2,ARGV(a0) clr.w CURARG(a0) bsr ManageCmdline move.w d3,(sp) ROMT HeapFree pea (a3) bra.s \Final ;----------------------------------------------------------------------- ; Error handling ;----------------------------------------------------------------------- \MemoryAndFree: move.w d3,(sp) ROMT HeapFree \Memory: moveq.l #PDTLIB_MEMORY_ERROR,d0 bra.s \End \NotAText: moveq.l #PDTLIB_WRONG_CONFIG_FILE,d0 bra.s \End \NoConfigFile: moveq.l #PDTLIB_NO_CONFIG_FILE,d0 \End: lea 18(sp),sp \Final: movem.l (sp)+,d3-d6/a2-a3 rts
pdtlib::ManageCmdline
;=============================================================================== ; ; pdtlib::InitCmdline ; ; in a0 CMDLINE* cl ; a1 char** argv ; d0.w int argc ; ; out nothing ; ; destroy nothing ; ; Initialize command line parsing ; ;=============================================================================== DEFINE pdtlib@0000 move.l a1,ARGV(a0) move.w d0,ARGC(a0) ;=============================================================================== ; ; pdtlib::ResetCmdline ; ; in a0 CMDLINE* cl ; ; out nothing ; ; destroy nothing ; ; Reset command line parsing ; ;=============================================================================== DEFINE pdtlib@0010 clr.w CURARG(a0) rts ;=============================================================================== ; ; pdtlib::GetNextArg ; ; in a0 CMDLINE* cl ; ; out a0 char* NextArg ; ; destroy d0.w ; ; Return a pointer to the next arg while parsing with ManageCmdline, or ; NULL if no arg remain ; ;=============================================================================== DEFINE pdtlib@0003 GetNextArg: addq.w #1,CURARG(a0) ;=============================================================================== ; ; pdtlib::GetCurrentArg ; ; in a0 CMDLINE* cl ; ; out a0 char* CurrentArg ; ; destroy d0.w ; ; Return a pointer to the current arg while parsing with ManageCmdline, ; or NULL if parsing is finished ; ;=============================================================================== DEFINE pdtlib@0002 move.w CURARG(a0),d0 cmp.w ARGC(a0),d0 bls.s \Fail movea.l ARGV(a0),a0 movea.l 0(a0,d0.w),a0 rts \Fail: suba.l a0,a0 rts ;=============================================================================== ; ; pdtlib::ManageCmdline ; ; in 4(sp) CMDLINE* cl ; 8(sp) void* Data ; 12(sp) char* SwitchesList ; 16(sp) ushort (*ArgNotSwitch) (void* Data asm (a0)) ; 20(sp) ushort (*ArgSwitch1) (void* Data asm (a0), ; short Sign asm (d1.w) ; ) ; 24(sp) (*) ... ; ; out d0.w ushort ; ; destroy std ; ; Look at pdtlib.h for return values ; ; SwitchesList format: ; ; dc.b 'ShortSwitch1', "Long Switch 1", 0 ; dc.b 'ShortSwitch2', "Long Switch 2", 0 ; dc.b ... ; dc.b 0, 0 ; ; 'ShortSwitchX' or "Long Switch X" may be 0, if no such switch exists ; When both are 0, this is the end of the table ; ;=============================================================================== DEFINE pdtlib@0001 ManageCmdline: movem.l a2-a5,-(sp) movem.l 5*4(sp),a2-a5 \Loop: movea.l a2,a0 bsr.s GetNextArg move.l a0,d0 beq.s \EndOfParsing movea.l a4,a1 moveq.l #0,d2 move.w #'+',d1 ; Clear upper byte for (*ArgSwitch) cmp.b (a0)+,d1 beq.s \CheckSecondSign addq.w #2,d1 ; - cmp.b -1(a0),d1 bne.s \ArgNotSwitch \CheckSecondSign: cmp.b (a0)+,d1 beq.s \LongSwitch ; This is a short switch moveq.l #PDTLIB_INVALID_SWITCH,d0 tst.b (a0) bne.s \EndOfParsing tst.b -(a0) beq.s \EndOfParsing moveq.l #PDTLIB_SWITCH_NOT_FOUND,d0 \ShortSwitchLoop: tst.b (a1) bne.s \TestShortSwitch tst.b 1(a1) beq.s \EndOfParsing \TestShortSwitch: cmpm.b (a0)+,(a1)+ beq.s \ShortSwitchFound \SkipShortSwitchLoop: tst.b (a1)+ bne.s \SkipShortSwitchLoop addq.w #4,d2 subq.l #1,a0 bra.s \ShortSwitchLoop ; This is a long switch \LongSwitch: moveq.l #PDTLIB_INVALID_SWITCH,d0 tst.b (a0) beq.s \EndOfParsing moveq.l #PDTLIB_SWITCH_NOT_FOUND,d0 pea (a0) \LongSwitchLoop: movea.l (sp),a0 addq.l #1,a1 \TestLongSwitch: cmpm.b (a0)+,(a1)+ beq.s \TestEndOfLongSwitch subq.l #1,a1 \SkipLongSwitchLoop: tst.b (a1)+ bne.s \SkipLongSwitchLoop addq.w #4,d2 tst.b (a1) bne.s \LongSwitchLoop tst.b 1(a1) bne.s \LongSwitchLoop bra.s \EndOfParsing ; This is not a switch \ArgNotSwitch: movea.l a3,a0 jsr (a5) ; Check return value of callbacks \CheckReturnValue: subq.w #1,d0 beq.s \Loop subq.w #1,d0 bne.s \WrongReturnValue moveq.l #PDTLIB_STOP_PARSING,d0 bra.s \EndOfParsing \WrongReturnValue: moveq.l #PDTLIB_WRONG_RETURN_VALUE,d0 \EndOfParsing: movem.l (sp)+,a2-a5 rts \TestEndOfLongSwitch: tst.b -1(a0) bne.s \TestLongSwitch ; LongSwitchFound addq.l #4,sp \ShortSwitchFound: movea.l a3,a0 movea.l 9*4(sp,d2.w),a1 jsr (a1) bra.s \CheckReturnValue

Pour la petite histoire, un programme au standard PedroM à mon standard exporte sa table de switches en monprog@0000. Comme ça, un programme en appelant plusieurs autres (au pif, gcc), peut lire les arguments, savoir à quel softs ils appartiennent, et les passer au bon programme au bon moment.
La table des switches est simple, c'est une table de string, sachant que le premier caractère de chaque string représente la version courte du switch (-x ou +x), la suite la version longue (--zyx ou ++ xyz). Evidemment, une seule des deux versions peut être présente.