home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / batch / library / batutl2 / ask.asm < prev    next >
Assembly Source File  |  1988-04-19  |  10KB  |  351 lines

  1. ; ASK program to enable you to ask questions and let users type in a
  2. ; one-character response. This allows you to build simple menu-driven
  3. ; batch file or yes/no type questions.
  4. ;
  5. ; See the external docuementation for more details.
  6. ; Written by Peter Wu; April, 1986
  7. ; UUCP: {seismo|ihnp4|harvard|ucbvax|allegra|topaz}!uwvax!uwmacc!pwu
  8. ; ARPA: pwu@unix.macc.uwisc.edu
  9. ;
  10. ; Slightly tweaked by David Kirschbaum, Toad Hall
  11.  
  12. ARGL    equ    80h        ; start of command line
  13. SPECIAL equ     '^'        ; the special escape character
  14. SWITCH    equ     '/'        ; switch character preceeding options
  15. CMDLEN    equ    150        ; max length of converted cmd line
  16. MAXARGC    equ    4        ; max # of arguements
  17. SQUOTE    equ    39        ; ASCII of '
  18. CR    equ    0DH
  19. LF    equ    0AH
  20.  
  21. All    SEGMENT 'CODE'
  22.     ASSUME    CS:All,DS:All
  23.     ORG    100h
  24.  
  25. Entry    proc    near
  26.     jmp    Start
  27.  
  28. ;********************** data area ***********************
  29. line    db    CMDLEN dup(?)    ; store the converted command line
  30. argc    db    ?
  31. argv    dw    MAXARGC * 2 dup(?)    ; *argv[]
  32. option    db    1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1
  33.           ; a b c d e f g h i j k l m n o p q r s t u v w x y z
  34.         ; 0 = option off, 1=invalid option, 2 = option on
  35. cry    db      'unknown option ',SQUOTE
  36. unkopt    db    ?        ; fill in the unknown option here
  37.     db    SQUOTE,' ignored',CR,LF,'$'
  38.  
  39. ;*********************** code area **********************
  40. ; GetC returns a converted character. bx should point to command line
  41. ; cl should contain the length of the command line
  42. ; ah=0 if normal character; ah='\' if special character.
  43.  
  44. three    db    ?        ; for counting down from 3
  45. ten    db    10        ; for multiplying
  46. Entry    endp
  47.  
  48.  
  49. GetC    proc    near
  50.     xor    ax,ax        ; clear character
  51.     sub    cl,1        ; len = len - 1
  52.     jc    Eoln        ; reached end of command line
  53.  
  54.     mov    al,[bx]        ; get a character
  55.     inc    bx        ; point to next one
  56.     cmp    al,SPECIAL    ; is it the special char '\' ?
  57.     jnz    Normal        ; nop; just a normal character
  58.  
  59.     sub    cl,1        ; len = len - 1
  60.     jc    Eoln        ; last character is '\'; ignore it
  61.  
  62.     mov    ah,al        ; flag special char
  63.     mov    al,[bx]        ; get the next char
  64.     inc    bx        ; point to next char
  65.  
  66. ; translate \nnn characters into ascii
  67.     cmp    al,'0'        ; see if first n is a digit
  68.     jb    NotDig        ; not a digit
  69.     cmp    al,'9'
  70.     ja    NotDig        ; not a digit
  71.  
  72. ; first n is a digit
  73.     xor    ch,ch        ; init accumulator
  74.     mov    three,3        ; convert 3 digits at most
  75.  
  76. Digit:    sub    al,'0'        ; convert to binary
  77. ; now multiply cl by ten and add al to it
  78.     xchg    al,ch        ; do this so we can use al to multiply
  79.     mul    ten        ; assume result is still 8 bits
  80.     add    ch,al        ; one digit is done.
  81.  
  82. ; more digits?
  83.     dec    three
  84.     jz    GotIt        ; converted all three digits
  85.     mov    al,[bx]        ; examine next char
  86.     cmp    al,'0'        ; is it a digit
  87.     jb    GotIt        ; not a digit; end translation
  88.     cmp    al,'9'
  89.     ja    GotIt        ; not a digit; end translation
  90.     inc    bx        ; point to next char
  91.     jmp    Digit        ; process digit
  92.  
  93. GotIt:    mov    ah,SPECIAL    ; flag special char even for \nnn
  94.     mov    al,ch        ; return char in al
  95. Normal:    ret
  96.  
  97. NotDig:                ; not \nnn (e.g. \a \b \c \d ...)
  98.     cmp    al,SPECIAL    ; \\ => \
  99.     je    Skip
  100.     cmp    al,'"'          ; \" => "
  101.     je    Skip
  102.     and    al,31        ; \a => ctrl-a; \b => ctrl-b; ...
  103. Skip:    ret
  104.  
  105. Eoln:    xor    ax,ax        ; return end-of-line char
  106.     ret
  107.  
  108. GetC    endp
  109.  
  110. ;*********************** PrtS **********************
  111. count    dw    ?
  112. p    dw    ?
  113.  
  114. PrtS    proc    near        ; print string to stdout; si points to string
  115.     mov    ax,[si+2]    ; pointer to string
  116.     mov    p,ax        ; save pointer
  117.     mov    ax,[si]        ; get length of string
  118.     mov    count,ax
  119.  
  120. Ploop:  sub    count,1
  121.     jc    D1        ; end of string
  122.     mov    bx,p
  123.     mov    dl,[bx]        ; current character to be printed
  124.     inc    p        ; point to next character
  125.     mov    ah,2        ; function number for print character
  126.     int    21h        ; print character
  127.     jmp    Ploop        ; repeat
  128.  
  129. D1:    ret
  130. PrtS    endp
  131.  
  132. ;********************* main *********************
  133.  
  134. mc    db    ?        ; loop index
  135. char    db    ?        ; key pressed by user
  136.  
  137. crlf    db    CR,LF,'$'    ; crlf string
  138.  
  139. helpms  db      'Usage:',CR,LF
  140.  db '  ask [',SWITCH,'c',SWITCH,'q] '
  141.  db '"prompt message" "expected response"',CR,LF,LF
  142.  db '    ',SWITCH,'c makes the response case sensitive',CR,LF
  143.  db '    ',SWITCH,'q will accept non-expected response (returns 0)',CR,LF
  144.  db '    "prompt message" and "expected response" are quoted strings',CR,LF
  145.  db '    To embed special characters use ',SPECIAL
  146.  db 'nnn where nnn is a 3-digit ASCII',CR,LF
  147.  db '    or ',SPECIAL,'a for ctrl-a, ',SPECIAL,'b for'
  148.  db ' ctrl-b, ... (except ',SPECIAL,SPECIAL,' for ',SPECIAL,' itself',CR,LF
  149.  db '    and ^" for the quote character)',CR,LF
  150.  db '  Response can be tested with if errorlevel',CR,LF
  151.  db '  Errorlevel is set to index("expected response",key pressed)',CR,LF,LF
  152.  db 'See the external document for more information',CR,LF
  153.  db '$'
  154. nom    db      '*BEEP*  Unexpected response',CR,LF,LF,'$'
  155.  
  156. Start    proc    near
  157.  
  158.     mov    bx,ARGL        ; start of parameters
  159.     mov    cl,[bx]        ; length of parameter
  160.     inc    bx        ; now point to first char
  161.     mov    di,offset line  ; point to convert line buffer
  162.     mov    si,offset argv - 4    ; point to *argv[0] - 4
  163.  
  164.     mov    argc,0        ; normally start at 1; but for ask.com 0 is ok
  165.  
  166. ; now split command line into arguements in argv[]
  167. Loopit:
  168.     cmp    argc,MAXARGC    ; can we handle more arguements?
  169.     jae    Done        ; if not; get out
  170.  
  171.     call    GetC        ; convert one character
  172.     or    ax,ax        ; check for done
  173.     jz    Done        ; end of command line
  174.  
  175.     cmp    al,' '        ; a blank space?
  176.     jz    Loopit        ; skip it
  177.  
  178. ; now we must be seeing the beginning of an arguement
  179.     inc    argc        ; count it
  180.     add    si,4        ; point to next *argv[]
  181.     mov    [si+2],di    ; where string start
  182.     mov    word ptr [si],0 ; set length to 0
  183.  
  184.     mov    dx,' '        ; assume this is the separator
  185.     cmp    ax,'"'          ; start of quoted string?
  186.     jne    NoQuote        ;
  187.     mov    dx,'"'          ; make this the separator
  188.     jmp    short Next    ; don't store the first "
  189.  
  190. NoQuote:
  191.     mov    [di],al        ; store the character
  192.     inc    di
  193.     inc    word ptr [si]    ; increment argv's length
  194. Next:    call    GetC
  195.     or    ax,ax
  196.     jz    Done        ; end of arguement
  197.  
  198.     cmp    ax,dx        ; is this the separator?
  199.     jz    Loopit        ; find next arguement
  200.  
  201.     jmp    NoQuote        ; keep storing
  202.  
  203. ; now done with splitting argv[]'s
  204. Done:
  205. ; now let's check for options
  206.     mov    ah,argc
  207.     mov    mc,ah        ; for mc = argc downto 1 do
  208.     mov    si,offset argv - 4
  209.     or    ah,ah        ; do we any argv at all?
  210.     jz    EndOpt
  211. More:    add    si,4        ; point to *argv[0,1,2,...]
  212.     mov    bx,[si+2]    ; address of string
  213.     cmp    byte ptr [bx],SWITCH    ; is this string an option?
  214.     jnz    EndOpt        ; no more options
  215.  
  216. ; process this option (option can be /abc or /a /b /c or /a/b/c)
  217.     mov    cx,[si]        ; length of option string
  218. Mopts:    inc    bx        ; point to char after the switch
  219.     dec    cx        ; decrement length of option string
  220.     jz    NextOp        ; done with this option string. Next.
  221.  
  222. ; now scrutinize the option letter
  223.     mov    al,[bx]        ; the option letter
  224.     cmp    al,SWITCH    ; is the switch embedded in here?
  225.     je    Mopts        ; ignore it
  226.  
  227.     cmp    al,'A'        ; check for legal option letters
  228.     jb    BadOpt
  229.     cmp    al,'Z'
  230.     jbe    GoodOpt        ; a valid uppercase option letter
  231.  
  232.     cmp    al,'a'
  233.     jb    BadOpt
  234.     cmp    al,'z'
  235.     ja    BadOpt
  236.  
  237. GoodOpt:
  238.     mov    dl,al        ; save option letter in case of error
  239.     and    al,31        ; convert to 1-26
  240.     dec    al        ; convert to 0-25
  241.     xor    ah,ah
  242.     mov    di,ax        ; use as an index
  243.     mov    al,dl        ; in case we need this to print error
  244.     cmp    option[di],1    ; check if this is a known option
  245.     je    BadOpt        ; if not, yell at user
  246.      mov    option[di],2    ; set the option
  247.      jmp    short Mopts    ; go look at next option char.
  248.  
  249. BadOpt:                ; yell at user for bad option character
  250.     mov    unkopt,al
  251.     mov    dx,offset cry
  252.     mov    ah,9        ; print the error message
  253.     int    21h
  254.     jmp    short Mopts    ; look at next option char.
  255.  
  256. NextOp:    dec    mc        ; count down argc
  257.     jnz    More
  258.  
  259. ; now process the parameters
  260. EndOpt:    cmp    mc,0        ; see if there's any arguements at all
  261.     ja    NoHelp
  262.     mov    dx,offset helpms    ; if not, print a summary
  263.     mov    ah,9        ; print string
  264.     int    21h
  265.     xor    al,al        ; return code 0
  266.     jmp    Die
  267.  
  268. NoHelp:                ; si is pointing to a parameter *argv[]
  269.     mov    di,si
  270.     add    di,4        ; if mc = 2 then di is pointing to the
  271.                 ;  expected response string's argv[]
  272.  
  273. ; now see if we should convert the "expected response" to upper case
  274.     cmp    mc,2        ; is there an "expected response" at all?
  275.     jb    Ask        ; if not, then forget about converting
  276.     cmp    option + 'c' - 'a',2    ; should we be case sensitive?
  277.     je    Ask        ; if so, then forget about converting
  278.  
  279. ; convert "expected response" to upper case
  280.     mov    cx,[di]        ; length of "expected response"
  281.     mov    bx,[di+2]    ; point to the actual string
  282.  
  283. Convert:
  284.     mov    al,[bx]        ; get a character from "expected response"
  285.     cmp    al,'a'        ; see if it's a lower case letter
  286.     jb    NotLow
  287.     cmp    al,'z'
  288.     ja    NotLow
  289.  
  290. ; alright, we have a lower case letter here, make it upper and store it back
  291.     sub    al,32
  292.     mov    [bx],al
  293.  
  294. NotLow:    inc    bx        ; point to next char
  295.     dec    cx        ; decrement length
  296.     jnz    Convert        ; until all characters are converted
  297.  
  298. Ask:    call    PrtS        ; print first parameter (the prompt)
  299.     mov    ah,1        ; keyboard input function code
  300.     int    21h        ; get a char
  301.     mov    char,al        ; save it
  302.  
  303.     mov    dx,offset crlf  ; print a carriage return
  304.     mov    ah,9
  305.     int    21h
  306.  
  307. ; now see if the /c option is on or off
  308.     mov    al,char        ; get it back
  309.     cmp    byte ptr [option+'c'-'a'],2
  310.     je    NoCase        ; no case translation if on
  311.  
  312. ; translate to upper case
  313.     cmp    al,'a'
  314.     jb    NoCase
  315.     cmp    al,'z'
  316.     ja    NoCase
  317.     sub    al,32        ; convert lower case to upper case
  318.  
  319. NoCase:    cmp    mc,2        ; test if expected response is present
  320.     jb    Die        ; if not present, just return the ASCII
  321.  
  322. ; now we should try to search the key pressed with expected response
  323.     mov    cx,[di]        ; length of string
  324.     mov    bx,[di+2]    ; start of string
  325.     mov    ah,al        ; mov char into ah
  326.     xor    al,al        ; use this to keep track of the index
  327.  
  328. Search:    inc    al        ; adjust index
  329.     cmp    [bx],ah        ; match ?
  330.     je    Die        ; if so, exit with index as errorlevel
  331.     inc    bx        ; point to next char
  332.     dec    cx        ; more to check?
  333.     jnz    Search
  334.  
  335. ; ok, no match, what should we do?
  336.     xor    al,al        ; return this if quiet option is set
  337.     cmp    option + 'q' - 'a',2    ; quiet option set?
  338.     je    Die        ; return with errorlevel = 0
  339.  
  340.     mov    dx,offset nom    ; quiet option not set, so yell at user!
  341.     mov    ah,9
  342.     int    21h
  343.     jmp    Ask        ; prompt user again until he gets it right
  344.  
  345. Die:    mov    ah,4ch        ; terminate; errorlevel in al
  346.     int    21h
  347.  
  348. Start    endp
  349. All    ends
  350.     end    Entry
  351.