home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug141.arc / IF.LBR / IF.AQM / IF.ASM
Assembly Source File  |  1979-12-31  |  11KB  |  347 lines

  1. ;
  2. ;   IF   --  conditionally execute or skip commands witthin a submit file
  3. ;
  4. ;         Written by Marc C. Brooks 1/4/83
  5. ;
  6. ;         based on David Kirkland's version of SKIPIF as of 6/12/83
  7. ;
  8. ;         Usage:
  9. ;
  10. ;         IF A[mbig] fn      true if fn is ambigous
  11. ;         IF E[xists] fn     true if file fn exists
  12. ;         IF M[issing] fn    true if file fn does not exist
  13. ;         IF N[ull] (fn)     true if the fn is missing
  14. ;         IF Z[ero] fn       true if file fn is zero length or does not exist
  15. ;
  16. ;         If the condition is true, all commands up to the next ELSE or 
  17. ;         ENDIF statement are executed.  If an ELSE is encountered before
  18. ;         the ENDIF statement is reached, commands are skipped until the 
  19. ;         ENDIF is found.  If the condition is false, commands are skipped
  20. ;         until the matching ELSE or ENDIF is found.  Command execution then
  21. ;         resumes.  IF-ELSE-ENDIF groups may be nested to any depth.
  22. ;
  23. ;         Only the first character of the first keyword (the A of Ambig or
  24. ;         whatever) is checked.  If an invalid keyword is entered, all 
  25. ;         commands between the IF and its matching ENDIF will be skipped
  26. ;         (after a suitable error message.)
  27. ;
  28. cpm    equ    0000h
  29. tpa    equ    0100h
  30. ccpoff    equ    0806h        ; offset from (bdos+1) to bottom of ccp
  31. bdos    equ    0005h
  32. fcb1    equ    005ch        ;the first fcb prepared by the CCP
  33. name1    equ    fcb1+1        ; start of the filename of fcb1 (AEMN or Z)
  34. fcb2    equ    006ch
  35. name2    equ    fcb2+1
  36. fcb2CUR    equ    fcb2+32        ; current record for fcb2
  37. ;
  38. drive    equ    'A'        ; the drive with the $$$.SUB file
  39. bell    equ    07h        ; an ASCII bell character
  40. ;   BDOS codes used
  41. ;
  42. PrtStr    equ    9        ; Print a string to console (terminated by $)
  43. Open    equ    15        ; Open a file
  44. Close    equ    16        ; Close a file
  45. Srch1st    equ    17        ; Search for the first occurence of a file
  46. Erase    equ    19        ; Erase a file
  47. Read    equ    20        ; Read a sequential record from a file
  48. SetDma    equ    26        ; Set the dma buffer address
  49. ;
  50.     org    tpa
  51. ;
  52. ;  First set the Stack, Dma address and check for a $$$.SUB file
  53. ;
  54.     lhld    bdos+1        ; get the address of the BDOS 
  55.     lxi    d,-ccpoff    ;  and add the CCP offset
  56.     dad    d        ; set the stack below the CCP
  57.     sphl
  58.     
  59.     mvi    c,SetDma    ; set the dma address to the buffer following
  60.     lxi    d,dmabuf    ;  the variables.
  61.     call    bdos
  62.  
  63.     mvi    c,Open        ; open $$$.SUB
  64.     lxi    d,subfile
  65.     call    bdos
  66.     inr    a        ; check to see if the $$$.SUB exists
  67.     jz    explain        ;  if not, explain the syntax and return
  68. ;
  69. ;  Everything is fine so execute the command the caller actually asked for
  70. ;
  71.     lda    name1        ; first character of the AMBIG or EXISTS or ..
  72.  
  73.     cpi    'N'        ; Null?
  74.     jz    null
  75.  
  76.         lda    name2        ; check the to see if the user gave
  77.         cpi    020h        ;  a filespec as the second argument
  78.     jnz    process
  79.  
  80.     mvi    c,PrtStr    ; fn is null, bitch to user and skip both the 
  81.     lxi    d,FnNulMsg    ;  IF and ELSE clauses
  82.     call    bdos
  83.     jmp    skipboth
  84.  
  85. process    lda    name1        ; okay, we have a filespec, branch to command
  86.     cpi    'A'        ; Ambig?
  87.     jz    ambig
  88.     cpi    'E'        ; Exists?
  89.     jz    exists
  90.     cpi    'M'        ; Missing?
  91.     jz    missing
  92.     cpi    'Z'        ; Zero?
  93.     jz    zero
  94.  
  95.     mvi    c,PrtStr    ; no match so print error message
  96.     lxi    d,BadOptMsg
  97.     call    bdos
  98.  
  99.     jmp    skipboth    ; skip both IF anf ELSE clauses
  100.  
  101. ;  ambig - do the IF clause if the 2nd argument is ambiguous
  102. ambig    mvi    b,11        ; 11 characters in filename & filetype
  103.     lxi    h,name2        ; bypass the drive code
  104.  
  105. scanlp    mov    a,m        ; scan for '?' in parsed fcb
  106.     cpi    '?'
  107.     jz    cpm        ; fn is ambiguous, return to CP/M
  108.     inx    h
  109.     dcr    b        ; done ?
  110.     jnz    scanlp        ;  no, loop back for next char
  111.  
  112.     jmp     false        ; no '?', so false
  113.  
  114. ;  exists - do the IF clause if the file exists
  115. exists    call    search
  116.     jnz    cpm        ; file found, return to CP/M
  117.     jmp     false
  118.  
  119. ;  missing - do the IF clause if the file does not exist
  120. missing    call    search
  121.     jnz    false
  122.     jmp    cpm        ; file not found, return to CP/M
  123.  
  124. ;  null - do the IF clause if the second parameter is missing
  125. null    lda    name2        ; Check the second FCB to see if the user 
  126.     cpi    020h        ;  gave a filespec as the second arg
  127.     jnz    false
  128.     jmp    cpm        ; fn is not present, return to CP/M
  129.  
  130. ;  zero - do the IF clause if the 2nd argument is a zero length file
  131. zero    call    search        ; does the file exist?
  132.     jz    cpm        ;  nope, zero long then so return to CP/M
  133.  
  134.     mvi    c,Open        ;  yes, lets open it
  135.     lxi    d,fcb2
  136.     call    bdos
  137.  
  138.         xra    a        ; zero the current record byte
  139.     sta    fcb2CUR
  140.     mvi    c,Read        ; now try to read one record (will fail if
  141.     lxi    d,fcb2        ;  the file is zero length)
  142.     call    bdos
  143.     ora    a
  144.     jz    false        ; read was OK, so not zero length
  145.     jmp    cpm        ; read failed, return to CP/M
  146.  
  147. ;  search - search for the first (possibly) ambiguous file to match fcb
  148. search    mvi    c,Srch1st
  149.     lxi    d,fcb2
  150.     call    bdos
  151.     inr    a        ; adjust the flags
  152.     ret
  153.  
  154. ;  skipboth - tell the user and skip both clauses of the IF
  155. skipboth mvi    c,PrtStr    ; tell the user that both the IF and the
  156.     lxi    d,SkipMsg    ;  ELSE clauses are being skipped
  157.     call    bdos
  158.  
  159.     mvi    c,Open        ; open $$$.SUB
  160.     lxi    d,subfile
  161.     call    bdos
  162.  
  163.     call    skipend        ; skip line till the ENDIF is encountered
  164.     
  165.     mvi    c,Close        ; close the $$$.SUB to rewrite the modified fcb
  166.     lxi    d,subfile
  167.     call    bdos
  168.  
  169.     jmp    cpm        ; return to CPM
  170.  
  171. ;  false - skip all command up to and including the ELSE, then return
  172. false    mvi    c,Open        ; open $$$.SUB
  173.     lxi    d,subfile
  174.     call    bdos
  175.  
  176.     call    skipelse    ; skip lines till ELSE or ENDIF
  177.  
  178.     mvi    c,Close        ; close the $$$.SUB to rewrite the modified fcb
  179.     lxi    d,subfile
  180.     call    bdos
  181.  
  182.     jmp    cpm        ; return to CP/M to execute else clause
  183.  
  184. ;  skipend - skip lines in the $$$.SUB file till an ENDIF is found
  185. skipend    call    nxtline        ; get the next line from the $$$.SUB file
  186.  
  187.     lxi    d,EndLit    ; point to the ENDIF literal
  188.     call    compstr        ; and compare
  189.     jnz    skipend        ;  not equal, loop till it is
  190.     ret            ;  equal, return to caller
  191.  
  192. ;  skipelse - skip lines in the $$$.SUB file till an ELSE or ENDIF is found
  193. skipelse call    nxtline        ; get the next line from the $$$.SUB file
  194.  
  195.         lxi    d,ElseLit    ; point to the ELSE literal
  196.     call    compstr        ; now compare the record just read to if equal
  197.     rz            ;  yes, return to caller
  198.  
  199.     lxi    d,EndLit    ; point to the ENDIF literal
  200.     call    compstr        ; and compare
  201.     jnz    skipelse    ;  not equal, loop till found
  202.     ret            ;  equal, return to caller
  203.  
  204. ;  nxtline - get the next line from the $$$.SUB file (with recursion stuff)
  205. nxtline    call    nxtcmd        ; get the next command line from the $$$.SUB
  206.  
  207.     lxi    d,IfLit        ; is it an IF statement?
  208.     call    compstr
  209.     rnz            ;  nope, okay, return the line to caller
  210.  
  211.     call    skipend        ;  yes, skip both clauses of this nested IF
  212.     jmp    nxtline        ; and now get the next command line
  213.  
  214. ;  nxtcmd - get the command line from the $$$.SUB file and chop it off the file
  215. nxtcmd    lda    subCNT        ; get the current record count for $$$.SUB
  216.     dcr    a        ;  decrement by one
  217.     sta    subREC        ;  and set the current record
  218.         mvi    c,Read        ; read the next command
  219.         lxi    d,subfile
  220.         call    bdos
  221.     inr    a
  222.     jz    killsub        ;  if error, kill $$$.SUB and exit
  223.  
  224.     lxi    h,dmabuf    ; load the address of the command buffer
  225.     mov    e,m        ;  get the byte count
  226.     mvi    d,0
  227.     dad    d
  228.     inx    h
  229.     mvi    m,0        ; and terminate the command with a zero
  230.  
  231.     lxi    h,subs2        ; zero the S2 byte of the fcb to force the
  232.     mvi    m,0        ;  BDOS to rewrite it
  233.     inx    h        ; now point to the record count byte
  234.     mov    a,m        ;  and see if it is a zero
  235.     ora    a
  236.     jz    erasub        ;  yes, erase the $$$.SUB and return to CP/M
  237.     dcr    m        ;  no, decrement the record count and return
  238.     ret
  239.     
  240. ;  compstr - compare the command just read to the literal point to by DE
  241. compstr lxi    h,dmabuf+1    ; get the address of the command and
  242.                 ;  skip the leading whitespace
  243.  
  244. skipblk    mov    a,m        ; end of command string ?
  245.     ora    a
  246.     jz    nomatch        ;  yes, signal no match
  247.  
  248.     cpi    021h        ; is it whitespace ?
  249.     jnc    complp        ;  no, start comparing
  250.     inx    h        ;  yes, next character
  251.     jmp    skipblk
  252.  
  253. nomatch    ori    0ffh        ; clear the zero flag to signal no match
  254.     ret            ;  and return to caller
  255.  
  256. complp    ldax    d
  257.     ora    a        ; end of the comparison string ?
  258.     rz            ;  yes, they must match
  259.         mov    c,a
  260.     mov    a,m        ;  not eos, get next byte
  261.     cpi    061h        ;   is 'a' <= a <= 'z' ?
  262.     jc    compit        
  263.     cpi    07ah
  264.     jnc    compit
  265.     ani    05fh        ;   yes, fold to upper case
  266. compit    cmp    c        ;  match ?
  267.     rnz            ;   no , return non zero
  268.     inx    h
  269.     inx    d
  270.     jmp    complp
  271.  
  272. ;  killsub - kill the submit file and return to CP/M
  273. killsub    mvi    c,PrtStr
  274.     lxi    d,TermMsg    ; tell the user
  275.     call    bdos
  276.  
  277. erasub    mvi    c,Erase        ; now kill the $$$.SUB file
  278.     lxi    d,subfile
  279.     call    bdos
  280.  
  281.     jmp    cpm        ; return to CP/M
  282.  
  283. ;  explain - give the syntax and an operational synopsis since the user
  284. ;            involked IF with no $$$.SUB file present (i.e. from console)
  285. explain mvi    c,PrtStr
  286.     lxi    d,HelpMsg
  287.     call    bdos
  288.  
  289.     jmp    cpm        ; return to CP/M
  290. ;
  291. ;
  292. IfLit    db    'IF',0
  293. ;
  294. ElseLit    db    'ELSE',0
  295. ;
  296. EndLit    db    'ENDIF',0
  297. ;
  298. ;
  299. ;
  300. TermMsg    db    bell,bell,bell,'ERROR - Submit procedure terminated'
  301.     db    13,10,'$'
  302. ;
  303. FnNulMsg db    bell,bell,bell,'A filespec must be given with this command'
  304.     db    13,10,'$'
  305. ;
  306. BadOptMsg db    bell,bell,bell,'That is not a legal option (A,E,M,N or Z)'
  307.     db    13,10,'$'
  308. ;
  309. SkipMsg    db    bell,bell,bell,'ERROR - Skipping both IF and ELSE clauses'
  310.         db    13,10,'$'
  311. ;
  312. HelpMsg    db    bell,13,10,'IF and its companion programs (ELSE, ENDIF and GOTO) are',13,10
  313.     db    'used within submit files to allow conditional execution of',13,10
  314.     db    'commands.  See IF.DOC for examples.',13,10
  315.     db    13,10
  316.     db    'Usage:        IF A[mbig] fn      true if fn is ambigous',13,10
  317.     db    '        IF E[xists] fn     true if file fn exists',13,10
  318.     db    '        IF M[issing] fn    true if file fn does not exist',13,10
  319.     db    '        IF N[ull] (fn)     true if the fn is missing',13,10
  320.     db    '        IF Z[ero] fn       true if file fn is zero length or',13,10
  321.     db    '                   does not exist',13,10
  322.     db    13,10
  323.     db    'If the condition is true, all commands up to the next ELSE or',13,10
  324.     db    'ENDIF statement are executed.  If an ELSE is encountered before',13,10
  325.     db    'the ENDIF statement is reached, commands are skipped until the',13,10
  326.     db    'ENDIF is found.  If the condition is false, commands are skipped',13,10
  327.     db    'until the matching ELSE or ENDIF is found.  Command execution',13,10
  328.     db    'then resumes.  IF-ELSE-ENDIF groups may be nested to any depth.',13,10
  329.     db    13,10
  330.     db    'Only the first character of the first keyword (the A of Ambig or',13,10
  331.     db    'whatever) is checked.',13,10
  332.     db    '$'
  333. ;
  334. ;
  335. subfile    db    drive+1-'A'    ; drive for the $$$.SUB file
  336.     db    '$$$     SUB'    ;  and the parsed name
  337.     db    0,0        ;  and extent and S1 bytes
  338. subs2    ds    1        ;  and the S2 byte (0'ed to cause BDOS rewrite)
  339. subCNT    ds    1        ;  and the record count
  340.         ds    16        ;  room for the allocation map
  341. subREC    ds    1        ;  room for the current record number
  342.     ds    3        ;  and finally, room for the random rec num
  343. ;
  344. dmabuf    ds    128        ; the dma buffer for all operations
  345. ;
  346.     end
  347.