home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_7 / 6.ddi / TAEXMPL1.ZIP / IPARAM.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-02-13  |  12.4 KB  |  370 lines

  1.  
  2. ;   FILENAME: IPARAM.ASM
  3. ;
  4. ;   Copyright (c) 1988, 1990 by Borland International, Inc.
  5. ;
  6. ;   DESCRIPTION: This module implements two routines that manage the
  7. ;   command line parameters passed to the program. The routine ParamCount
  8. ;   returns the number of parameters passed to the program while the
  9. ;   routine ParamString returns a pointer to the referenced parameter
  10. ;   string. This module uses ideal mode syntax.
  11. ;
  12. ;   ASSEMBLY INSTRUCTIONS: To assemble this module use the following
  13. ;   TASM command line.
  14. ;
  15. ;       TASM /m /dMDL=memorymodel iparam
  16. ;
  17. ;   /m in the above command line allows TASM to resolve jumps and other
  18. ;   operations to their shortest form and get rid of extra NOPs.
  19. ;   'memorymodel' in the above command line may be replaced by TINY, SMALL,
  20. ;   MEDIUM, COMPACT, LARGE or HUGE. If assembling this module to run on
  21. ;   a 286/386 machine, turn on the P286 directive in order to take advantage of
  22. ;   286/386 specific instructions. I.E.
  23. ;
  24. ;       TASM /m /dMDL=memorymodel /jP286 iparam
  25. ;
  26. ;   NOTE: This module requires that the main program declare and initialize
  27. ;   the global variable PspAddress.
  28.  
  29. %tabsize 4
  30.  
  31. ifndef  MDL
  32.     display "Error: This module requires that you provide a memory model"
  33.     display "       definition on the command line. I.E. /dMDL=SMALL."
  34.     err ; Force a fatal error
  35. else
  36.  
  37.     ideal                           ; Use TASM's Ideal mode
  38.     model   MDL,pascal              ; Define the memory model
  39.  
  40.     include "dos.inc"
  41.     include "idos.inc"
  42.     include "kbd.inc"
  43.     include "iwhglobl.inc"
  44.  
  45.     NotCalled  equ 0FFh ; ParamCount was already called once
  46.  
  47.     dataseg
  48.         ; Declare variables to store the parsed parameters and parameter
  49.         ; count.
  50.  
  51.         ParmCount   DB  NotCalled       ; ParamCount initializes this variable
  52.                                         ; the first time it is called.
  53.         ParmList    DB  7Fh DUP (?)     ; Allocate enough space for a 127
  54.                                         ; character command line
  55.         global  PspAddress:word         ; Define extrn variable
  56.  
  57.     codeseg
  58.  
  59. ;    global  ParamCount:proc             ; Public procs
  60. ;    global  ParamString:proc
  61.  
  62. ;    global  LocateString:proc           ; Declare external procs
  63. ;    global  FindBytePos:proc
  64. ;    global  FindAndReplace:proc
  65. ;    global  ByteCopy:proc
  66. ;    global  SkipSpaces:proc
  67.  
  68.     proc    IsDelimiter
  69.     ;   This routine checks the character in AL to see if it is a delimiter.
  70.     ;   Valid delimiters are   ''  ""  []
  71.     ;
  72.     ;   Input
  73.     ;       al - Character to check
  74.     ;   Output
  75.     ;       al contained a delimiter:
  76.     ;            al - matching delimiter
  77.     ;            Carry set
  78.     ;       al did not contain a delimiter
  79.     ;            Carry not set
  80.     ;   Calling conventions
  81.     ;       NA
  82.     ;   Registers modified
  83.     ;       al
  84.  
  85.         cmp     al,'"'
  86.         je      ItIs
  87.         cmp     al,"'"
  88.         je      ItIs
  89.         cmp     al,"]"
  90.         je      ItIs
  91.         cmp     al,"["
  92.         je      ItIsSquare
  93.         jmp     IsNot
  94.     ItIsSquare:
  95.         mov     al,"]"
  96.     ItIs:
  97.         stc
  98.         ret
  99.     IsNot:
  100.         clc
  101.         ret
  102.     endp    IsDelimiter
  103.  
  104.     proc    ParamCount
  105.  
  106.     ;   This routine returns the number of command line parameters passed to
  107.     ;   the program. Parameters are delimited by spaces or tabs. Double or
  108.     ;   single quotes can enclose parameters that include spaces or tabs
  109.     ;   inside them.
  110.     ;
  111.     ;   While the function is parsing the command line it stores copies of
  112.     ;   each of the parameters in the modules data segment. The strings are
  113.     ;   stored in Turbo Pascal format. That is they are stored with a
  114.     ;   preceeding length byte. The first time the routine is called it also
  115.     ;   stores the result in the variable ParmCount in the modules data
  116.     ;   segment. Any subsequent calls simply return the contents of
  117.     ;   ParmCount.
  118.     ;
  119.     ;   Input
  120.     ;       none
  121.     ;   Output
  122.     ;       al - Number of parameters
  123.     ;   Calling conventions
  124.     ;       NA
  125.     ;   Registers modified
  126.     ;       ax, bx, cx, DX, di, si, es, Flags
  127.  
  128.     local   SearchChar:byte=LocalSymbolSize ; Declare local variables
  129.  
  130.         ; Point es:di to location where the parsed parameters will be stored
  131.  
  132.         if  @DataSize   eq  0
  133.             mov     ax, @data       ; Using near data model
  134.         else
  135.             mov     ax, @fardata    ; Using far data model
  136.         endif
  137.         mov     es, ax
  138.  
  139.         ; Check if the function was called previously. If it was we
  140.         ; don't want to parse the command line again.
  141.  
  142.         cmp     [es:ParmCount], NotCalled
  143.         je      FirstCall
  144.         jmp     AlreadyCalled
  145.  
  146.     FirstCall:
  147.         mov     di, offset ParmList ; es:di now points to modules storage
  148.         push    ds
  149.  
  150.         ; Note that we don't actually allocate any memory to store the
  151.         ; DOS Psp. We simply use the STRUC declaration to determine
  152.         ; the offsets of the fields in the memory allocated by DOS.
  153.  
  154.         mov     ds, [PspAddress]    ; Load the segment address of the Psp
  155.         mov     si, offset (Psp).CommandTail + 1
  156.  
  157.         xor     cx, cx              ; Initialize cx
  158.         xor     bx, bx              ; Store # of parameters in bx
  159.  
  160.  
  161.         ; Get the length of the DOS command line from the Psp.
  162.  
  163.         mov     cl, [ds:Psp.CommandTail.LengthByte]
  164.  
  165.         ; Check if the command line is empty and leave if it is.
  166.  
  167.         cmp     cl, 0
  168.         jne     ReplaceTabs
  169.         jmp     InitParmCount
  170.  
  171.     ReplaceTabs:
  172.  
  173.         ; Convert any tabs in the command line to spaces in order to
  174.         ; make the parsing simpler.
  175.  
  176.         push    cx  ; Store value of cx & es:di because call to
  177.         push    es  ; FindAndReplace modifies them.
  178.         push    di
  179.  
  180.         ; Push the address of the DOS command line
  181.  
  182.         push    ds
  183.         if (@Cpu and 100b) eq 100b
  184.             push    offset (Psp).CommandTail + 1
  185.         else
  186.             mov     ax, offset (Psp).CommandTail + 1
  187.             push    ax
  188.         endif
  189.  
  190.         ; Define the bytes to search/replace
  191.  
  192.         mov     ax, (SPACE shl 8) + TAB
  193.         call    FindAndReplace          ; Replace all tabs with spaces
  194.         pop     di es
  195.                                         ; Restore previous values of cx & es:di
  196.         pop     cx
  197.  
  198.         ; Skip any spaces at the beginning of the parameter list.
  199.  
  200.         push    es di                   ; Save registers that will be modified
  201.  
  202.         push    ds si                   ; Pass the address of the string
  203.         call    SkipSpaces
  204.         pop     si ds                   ; Update ds:si with start of next
  205.                                         ; parameter
  206.         pop     di es                   ; Restore es:di to point to location
  207.                                         ; to store the next parameter
  208.  
  209.         ; Now parse the command line. Note that after each iteration of
  210.         ; this loop ds:si points to the beginning of the next parameter
  211.         ; and es:di points to location in the modules data segment where
  212.         ; the next parameter will be stored.
  213.  
  214.     ParseCmdLine:
  215.         inc     bx                      ; Increment the parameter count
  216.         mov     al,[si]
  217.         call    IsDelimiter
  218.         jc      HandleDelimiter
  219.         jmp     WhiteSpace
  220.  
  221.     HandleDelimiter:
  222.         mov     [SearchChar], al
  223.         inc     si  ; Point to the next character in the parameter list
  224.         dec     cx  ; Adjust number of bytes left to check
  225.         jmp     FindDelimiter
  226.  
  227.     WhiteSpace:
  228.         mov     al, SPACE
  229.         mov     [SearchChar], al         ; Use space, tab or eoln as delimiter
  230.  
  231.     FindDelimiter:
  232.         push    bx es di                 ; Store bx, es:di
  233.  
  234.         ; Push the address of the start of the next parameter for the call
  235.         ; to FindBytePos
  236.  
  237.         push    ds
  238.         push    si
  239.  
  240.         ; Find the end of the parameter. After the call to FindBytePos
  241.         ; ax = the number of bytes searched and es:di is pointing to
  242.         ; the byte after the last one checked. cx=# of bytes left to
  243.         ; check in the command line string.
  244.  
  245.         call    FindBytePos
  246.         push    es                      ; Move the pointer returned by
  247.         pop     ds                      ; FindBytePos into ds:si
  248.         mov     si, di
  249.  
  250.         pop     di es bx                ; Restore es:di, bx
  251.  
  252.  
  253.     ; Now copy the parameter into its storage location
  254.  
  255.     CopyParameter:
  256.         mov     dx, si                  ; Calculate the offset of the source
  257.         sub     dx, ax                  ; string
  258.         dec     dx
  259.  
  260.         ; If there was a delimiter other than a space, we want to make
  261.         ; sure that we get the trailing delimiter too.
  262.         cmp     [SearchChar],SPACE
  263.         jne     BumpCopyCount
  264.  
  265.         or      cx,cx                   ; Check if CX=0 (If at end of arguments)
  266.         jnz     StoreLength
  267.  
  268.     BumpCopyCount:
  269.         inc     al   ; We need to copy and extra character
  270.  
  271.     StoreLength:
  272.         push    cx bx es si di          ; Save the values of registers
  273.                                         ; modified by the call to ByteCopy
  274.         mov     [byte es:di], al        ; Store length of parameter in
  275.         inc     di                      ; the length byte
  276.  
  277.         ; Copy the array of characters
  278.         call    ByteCopy,ds,dx,\  ; Source string
  279.                          es,di    ; Destination string
  280.  
  281.         pop     di si es bx cx          ; Restore the previous values of the
  282.                                         ; registers modified by ByteCopy
  283.         add     di, ax                  ; Move pointer past end of parameter
  284.         inc     di
  285.  
  286.         cmp     [byte ds:si], SPACE
  287.         jne     NoWhiteSpace
  288.  
  289.         ; Now find the first character of the next parameter.
  290.  
  291.         push    es di                   ; Save registers that will be modified
  292.  
  293.         push    ds si                   ; Pass the address of the string
  294.         call    SkipSpaces
  295.  
  296.         pop     si ds                   ; Update ds:si with start of next
  297.                                         ; parameter
  298.         pop     di es                   ; Restore es:di to point to location
  299.                                         ; to store the next parameter
  300.  
  301.     NoWhiteSpace:
  302.         jcxz    InitParmCount
  303.         jmp     ParseCmdLine            ; Get the next parameter on the
  304.                                         ; command line.
  305.     InitParmCount:
  306.  
  307.         ; Initialize ParmCount so the routine doesn't have to parse the
  308.         ; command line more than once.
  309.  
  310.         mov     [byte es:ParmCount], bl
  311.         pop     ds                      ; Restore the programs data segment
  312.  
  313.     AlreadyCalled:
  314.         mov     al, [byte es:ParmCount] ; Return the previously determined
  315.         ret
  316.     endp    ParamCount
  317.  
  318.     proc    ParamString
  319.  
  320.     ;   This routine returns a far pointer to the parameter referenced in
  321.     ;   al. Before looking for the parameter, the function calls ParamCount
  322.     ;   to assure that the parameter exists. This has the side-affect of
  323.     ;   assuring that ParamCount parses and copies the parameters into the
  324.     ;   modules data segment.
  325.     ;
  326.     ;   Input
  327.     ;       al - Parameter to return
  328.     ;   Output
  329.     ;       al = Desired Parameter
  330.     ;           es:di - Far pointer to parameter
  331.     ;       al = 0 - Parameter doesn't exist
  332.     ;   Calling conventions
  333.     ;       NA
  334.     ;   Registers modified
  335.     ;       ax, bx, cx, di, si, es, Flags
  336.  
  337.         ; First check if the parameter exists
  338.  
  339.         push    ax                  ; Save index to desired parameter
  340.         call    ParamCount
  341.         pop     bx                  ; Restore index to desired parameter
  342.         cmp     bl, al              ; Check if the parameter exists
  343.         jg      InvalidParameter
  344.         mov     al, bl              ; Pass parameter index in al
  345.  
  346.         ; Point to modules data segment
  347.  
  348.         if  @DataSize   eq  0
  349.             mov     bx, @data       ; Using near data model
  350.         else
  351.             mov     bx, @fardata    ; Using far data model
  352.         endif
  353.         mov     es, bx              ; Make es:si point to the data area
  354.         mov     di, offset ParmList
  355.  
  356.         call    LocateString        ; Determine the address of the string
  357.         jmp     Exit
  358.  
  359.     InvalidParameter:
  360.         xor     al, al
  361.  
  362.     Exit:
  363.         ret
  364.     endp    ParamString
  365.  
  366. endif   ; ifndef MDL
  367.  
  368. end
  369.  
  370.