Author Topic: Parse command line  (Read 13430 times)

Offline TightCoderEx

  • Full Member
  • **
  • Posts: 103
Parse command line
« on: May 24, 2012, 05:48:45 PM »
Peculiar to my needs this algo finds all strings in command line that aren't delimited and if more than one, lets user select which one to return to caller.  I use this as a means of selecting a filename to be used by my application.

I realize delimiting the string I want with -f would be the most logical thing to do, but that doesn't address the hobby aspect of my code in so much as to dream it up and then see if I can make it work.

Code: [Select]
; * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * -
; Parse command line for qualifying filenames denoted by lack of delimiter

;       ENTRY:  ARG 1 = Pointer to ArgV passed by kernel

;       LEAVE:  RAX = Pointer to filename, otherwise null
;                R8 = Number of matching pointers, otherwise unchanged
;               RCX = undetermined
;               RDX = Could be modified

;       FLAGS:  ZR = 0 Success, othewise ZR = 1

;                                                                          0ACH =  172 bytes
; -------------------------------------------------------------------------------------------

        ; Looks a little unorthadox, but this method ensures RSI will be restore properly
        ; as procedure frame increases in size dynamically dependant upon contents of
        ; command line.
       
  ParseCL       push    rsi
                push    rbx
               
                push    rbp
                mov     rbp, rsp                ; Empty frame to accomadate STDCALL
               
        ; Determine if there is even anything to do. Maybe should have done this in caller
       
                mov     rsi, [rbp + 32]         ; Get pointer to ArgV
                lodsq                           ; Number of arguments passed to application
                dec     rax
                jz      .Exit                   ; ZR = 1, no arguments just app path & name
               
        ; Prepare for main body of procedure
       
                mov     rcx, rax                ; Copy arguments left
                lodsq                           ; Waste app path & name
       
        ; Cycle through each of the remaining arguments and ignore those beginning with
        ; GNU conventional delimiter being '-'
       
        .Next   lodsq                           ; Get pointer to next argument
                cmp     byte [rax], '-'         ; Is string prefixed with delimiter
                jz      $ + 3
                push    rax                     ; Probably a valid filename
                loop    .Next                   ; Continue till RCX = 0
               
        ; Now we need to determine how many pointers in the array and if more than one
        ; prompt operator which is the valid one. Start by calculating array size
       
                mov     rcx, rbp                ; Get TOS (Top Of Stack)               
                sub     rcx, rsp                ; RCX = Number of bytes
                shr     rcx, 3                  ; RCX /= 8 Actual number qword pntrs
                mov     rax, rcx
                jz      .Exit                   ; Bail if there weren't any matching
               
                cmp      cl, 1                  ; Hopefully less than 255 pointers
                ja      $ + 5
               
       ; Of all the arguments passed, only one qualified as a possible filename, so that
       ; is the one we'll return to caller.
       
                pop     rax
                jmp     .Exit

        ; In data section
        ;       NmeQuery      db      10, 10, 'Please select [ A - '
        ;       MaxQuery      db      '  ] ', 0             
        ; MaxQuery is dynamic and determined by the number of eligible strings in array
       
                mov      r8, rcx                ; We'll need this for comparison later
                mov      al, cl
                add      al, 64                 ; Determine A - Z
                mov     [MaxQuery], al          ; And write to proper position
               
        ; Values needed by ShowNme
       
                mov     rbx, rsp                ; Pointer to array of filename pointers               
                mov     rsi, NmePrompt          ; = 10, 9, '[?] - '
               
     .ShowNme   mov      al,  cl
                add      al, 0x40               ; Convert to uppercase A - Z
                mov     [rsi + 3], al           ; and post @ question mark position
                call    Console
               
                push    rsi                     ; Incase entry invalid, we'll need pointer again
                push    rcx
                dec     rcx                     ; Zero index to proper pointer
                mov     rsi, [rbx+rcx*8]
                call    Console                 ; and display
                pop     rcx
                pop     rsi
                loop    .ShowNme                ; Continue till RCX exhausted

        ; Now give operator oportunity to select which name
       
         .Ask   mov     rsi, NmeQuery
                call    Console                 ; Prompt operator
                push    0                       ; and make a small input buffer
                mov     rsi, rsp
                xor     rdx, rdx
                mov      dl, 2                  ; Single charater and return
                call    Keyboard
                mov      al, [rsp]              ; Get first character of input
                and      al, 31
                cmp      al, r8b
                ja      .Ask                    ; If invalid, ask again
               
                dec      R8
                mov     rax, [rbx+R8*8]         ; Grab pointer from array
               
        .Exit   leave                           ; Waste procedure frame
       
                pop     rbx
                pop     rsi
                or      rax, rax                ; Set appropriate flags
                ret     8                       ; RAX = NULL or pointer to filename