?login_element?

Subversion Repositories NedoOS

Rev

Rev 1865 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.         DEVICE ZXSPECTRUM128
  2.         include "../_sdk/sys_h.asm"
  3.  
  4. STACK=0x4000
  5.  
  6. LISTBUF         equ     0x4400
  7. LISTBUFsz       equ     0x200
  8.  
  9. DISKBUF=0xc000
  10. DISKBUFsz=0x4000
  11.  
  12.  
  13.         org PROGSTART
  14. cmd_begin
  15.         ld sp,STACK
  16.         call initstdio
  17.  
  18.                 call    CS_PREPARE
  19.  
  20.  
  21.                 ;get name of the prog as it was called from shell
  22.                 ld      hl,COMMANDLINE
  23.        
  24.                 call    skipspaces
  25.                 or      a
  26.                 jp      z,fatal_err     ;can't find first non-' ' char -- fatal error
  27.  
  28.                 ld      [name_ptr],hl   ;program name
  29.  
  30.                 call    skipword
  31.                 or      a
  32.                 jp      z,got_no_args
  33.                 ld      [hl],0          ;zero-terminate program name
  34.                 inc     hl
  35.                 call    skipspaces
  36.                 or      a
  37.                 jp      z,got_no_args
  38.  
  39.                 ;now HL points to first real arg, start arg parsing loop
  40. parse_args:
  41.                 ld      [curr_arg],hl
  42.                 ;find end of arg and zero-terminate
  43.                 call    skipword
  44.                 or      a
  45.                 push    af
  46.                 push    hl
  47.                 ld      [hl],0
  48.  
  49.                 call    process_arg
  50.  
  51.                 pop     hl
  52.                 pop     af
  53.                 jr      z,successful_exit
  54.                 inc     hl
  55.                 call    skipspaces
  56.                 or      a
  57.                 jr      nz,parse_args
  58. successful_exit:
  59.                 ld      hl,0
  60.                 QUIT
  61.  
  62.  
  63. AST_DFLT        equ     0
  64. AST_FILES       equ     1
  65. AST_CHK         equ     2
  66.  
  67. process_arg:    ;args parsing routine, has state
  68.                 ;in: HL=asciiz of current argument
  69.  
  70.                 ld      a,[argp_state]
  71.                 or      a
  72.                 jr      nz,.no_dflt
  73.  
  74. ;DFLT - wait for switches
  75.  
  76.                 ; check for -h or --help
  77.                 ld      hl,[curr_arg]
  78.                 push    hl
  79.                 ld      de,help_arg
  80.                 call    strcmp
  81.                 jr      z,.arg_help
  82.  
  83.                 pop     hl
  84.                 ld      de,chk_arg
  85.                 call    strcmp
  86.                 jr      z,.arg_chk
  87.  
  88.                 ; set FILES mode
  89.                 ld      a,AST_FILES
  90.                 ld      [argp_state],a
  91. .chksum_arg
  92.                 ld      hl,[curr_arg]
  93.                 xor     a
  94.                 jp      process_file
  95. .no_dflt
  96.                 dec     a
  97.                 jr      z,.chksum_arg
  98.                 ; FILES mode -- go to .chksum_arg
  99. .no_files
  100.                 dec     a
  101.                 jr      nz,.no_check
  102.                 ;CHECK mode
  103.                 call    process_list
  104.                 ret
  105. .no_check
  106.                 jp      error_exit
  107.  
  108.  
  109.  
  110. .arg_help       ;print help, exit
  111.                 ld      hl,help_msg1
  112.                 call    prtext
  113.                 ld      hl,[name_ptr]
  114.                 call    prtext
  115.                 ld      hl,help_msg2
  116.                 call    prtext
  117.                 ld      hl,CS_NAME
  118.                 call    prtext
  119.                 ld      hl,help_msg3
  120.                 call    prtext
  121.                 jr      successful_exit
  122.  
  123.  
  124. .arg_chk        ;check mode
  125.  
  126.                 ld      a,AST_CHK
  127.                 ld      [argp_state],a
  128.                 ret
  129.  
  130.  
  131.  
  132.  
  133. process_list:   ;argument = filename, open it, read crcs and filenames, check
  134.  
  135.                 ;open file by name
  136.                 ;
  137.                 ld      de,[curr_arg]
  138.                 OS_OPENHANDLE
  139.                 ;b - handle, a!=0 - error
  140.                 or      a
  141.                 jp      nz,.error_open
  142.                 ld      a,b
  143.                 ld      [list_hndl],a
  144.  
  145.                 ;initialize getc/ungetc state
  146.                 xor     a
  147.                 ld      [lpush],a       ;nothing ungetc'ed
  148.                 ld      h,a
  149.                 ld      l,a
  150.                 ld      [lsz],hl        ;nothing in buffer
  151.  
  152.  
  153.  
  154.                 ;main loop: FSM to parse the file with checksums and filenames.
  155.                 ;format:
  156.                 ;
  157.                 ;<BOL>XXXXXXXX<space><space><filename><EOL>
  158.                 ;
  159.                 ;<BOL> -- not a real symbol, just an indication that this is the beginning of line
  160.                 ;XXXXXXXX -- checksum in hex, must be of predefined length (8 for CRC32)
  161.                 ;<space> -- 0x20
  162.                 ;<filename> -- file that will be attempted to open.
  163.                 ;<EOL> -- <crlf> or <cr> or <lf>, last line from file is not obliged to end with these
  164.  
  165. .new_line
  166.                 ;check for EOF
  167.                 call    my_getc
  168.                 jr      nc,.have_bytes
  169.  
  170. .full_end       ;correct end of the file
  171.                 ld      a,[list_hndl]
  172.                 ld      b,a
  173.                 OS_CLOSEHANDLE
  174.                 ret
  175.  
  176. .have_bytes     call    my_ungetc
  177.  
  178.                 ;parse checksum
  179.                 ld      b,CS_SYMLEN
  180.                 ld      hl,CHKSUM
  181. .chksum_loop
  182.                 call    my_getc
  183.                 jp      c,.line_unexp_end
  184.                 call    is_hex
  185.                 jp      c,.line_format_error
  186.  
  187.                 ld      [hl],a
  188.                 inc     hl
  189.                 djnz    .chksum_loop
  190.                 ld      [hl],0
  191.  
  192.                 ;parse >=1 spaces
  193.                 call    my_getc
  194.                 jr      c,.line_unexp_end2
  195.                 cp      ' '
  196.                 jr      nz,.line_format_error
  197. .chkspc_loop
  198.                 call    my_getc
  199. .line_unexp_end2
  200.                 jr      c,.line_unexp_end
  201.                 cp      ' '
  202.                 jr      z,.chkspc_loop
  203.                 call    my_ungetc
  204.  
  205.  
  206.  
  207.                 ;parse filepath/name
  208.                 ld      b,MAXPATH_sz&255 ;now it is 256
  209.                 ld      hl,FNAME
  210. .chkfname_loop
  211.                 call    my_getc
  212.                 jr      c,.line_last_end
  213.                 cp      ' '     ;space -- end of path/fname
  214.                 jr      z,.end_fname
  215.                 cp      13      ;13 or 10 -- end of path/fname
  216.                 jr      z,.end_fname
  217.                 cp      10
  218.                 jr      z,.end_fname
  219.                
  220.                 ld      [hl],a
  221.                 inc     hl
  222.                 djnz    .chkfname_loop
  223.                 ld      [hl],0
  224.  
  225.                 ;check whether there's more in input stream
  226.                 call    my_getc
  227.                 jr      c,.line_last_end
  228.                 cp      ' '
  229.                 jr      z,.end_fname
  230.                 cp      13
  231.                 jr      z,.end_fname
  232.                 cp      10
  233.                 jr      z,.end_fname
  234.  
  235. .fname_error    ;if path/filename seems to be greater than MAXPATH_sz or zero-sized
  236.                 jr      $       ;STUB
  237.  
  238. .line_last_end  ;here if EOF condition while parsing '-c filename'
  239.                 ld      [hl],0
  240.  
  241.                 ;check for zero-length path/filename
  242.                 exd    
  243.                 ld      hl,FNAME
  244.                 or      a
  245.                 sbc     hl,de
  246.                 exd
  247.                 jr      z,.fname_error
  248.                 jr      .no_errs
  249.  
  250. .end_fname
  251.                 call    my_ungetc       ;return space/13/10 to the input stream;
  252.                                         ;will be used later as to look for a new line
  253.                
  254.                 ;check for zero-length path/filename
  255.                 exd
  256.                 ld      hl,FNAME
  257.                 or      a
  258.                 sbc     hl,de
  259.                 exd
  260.                 jr      z,.fname_error
  261.  
  262.                 ;no errors here
  263. .no_errs        ;hl=FNAME
  264.                 ld      [hl],0
  265.                 ld      hl,FNAME
  266.                 ld      a,1
  267.                 call    process_file
  268.  
  269. .skip_line      ;scan till end of filename/whatever, skip extra spaces/etc., skip line end
  270.                 call    my_getc
  271.                 jp      c,.full_end
  272.                 cp      13
  273.                 jr      z,.eol_13
  274.                 cp      10
  275.                 jr      nz,.skip_line
  276. .eol_10
  277.                 jr      .new_line2
  278. .eol_13
  279.                 call    my_getc
  280.                 cp      10
  281.                 jr      z,.new_line2
  282.                 call    my_ungetc
  283. .new_line2
  284.                 jp      .new_line
  285.  
  286.  
  287.  
  288. .line_format_error
  289. .line_unexp_end
  290.                 ld      hl,[name_ptr]
  291.                 call    prtext
  292.                 ld      hl,name_to_file
  293.                 call    prtext
  294.                 ld      hl,[curr_arg]
  295.                 call    prtext
  296.                 ld      hl,format_error
  297.                 jr      .prtext2
  298.  
  299.  
  300.  
  301. .error_open
  302.                 ld      hl,[name_ptr]
  303.                 call    prtext
  304.                 ld      hl,name_to_file
  305.                 call    prtext
  306.                 ld      hl,[curr_arg]
  307.                 call    prtext
  308.                 ld      hl,file_error
  309. .prtext2
  310.                 jp      prtext
  311.  
  312.  
  313.  
  314.  
  315.  
  316. my_getc:        ;get a symbol from list_hdnl:lptr:lsz:etc. construction
  317.                 ;
  318.                 ;out: A - symbol
  319.                 ;     cy=1 - no more symbols or error
  320.  
  321.                 ld      a,[lpush]       ;was smth ungetc'ed?
  322.                 or      a
  323.                 jr      z,.no_ununget
  324.                 ;
  325.                 xor     a
  326.                 ld      [lpush],a
  327.                 ld      a,[lpbyte]      ;if was, getc it back
  328.                 ret
  329. .no_ununget
  330.                 push    hl
  331.                 ld      hl,[lsz]
  332.                 ld      a,h
  333.                 or      l
  334.                 jr      z,.buf_empty    ;smth in the buffer?
  335. .no_ununget2
  336.                 dec     hl              ;get from buffer
  337.                 ld      [lsz],hl
  338.                 ld      hl,[lptr]
  339.                 ld      a,[hl]
  340.                 inc     hl
  341.                 ld      [lptr],hl
  342.                 pop     hl
  343.                 ret
  344. .buf_empty
  345.                 push    ix              ;was nothing in buffer, read from file
  346.                 push    iy
  347.                 push    bc
  348.                 push    de
  349.                
  350.                 ld      a,[list_hndl]
  351.                 ld      b,a
  352.                 ld      de,LISTBUF
  353.                 ld      [lptr],de
  354.                 ld      hl,LISTBUFsz
  355.                 OS_READHANDLE
  356.                 ;currently there's only single indication of both error and EOF:
  357.                 ; HL=0, A!=0
  358. .noerr
  359.                 ld      a,h
  360.                 or      l
  361.                 ld      [lsz],hl
  362.                
  363.                 pop     de
  364.                 pop     bc
  365.                 pop     iy
  366.                 pop     ix
  367.                
  368.                 jr      nz,.no_ununget2
  369. .nothing_more
  370.                 pop     hl
  371.                 scf
  372.                 ret
  373.  
  374.  
  375.  
  376. my_ungetc:      ;'ungetc' a symbol (there can be only a single ungot symbol!)
  377.                 ;in: A - symbol
  378.  
  379.                 push    af
  380.                 ld      a,[lpush]
  381.                 or      a
  382.                 jr      nz,$
  383.                 inc     a
  384.                 ld      [lpush],a
  385.                 pop     af
  386.                 ld      [lpbyte],a
  387.                 ret
  388.  
  389.  
  390.  
  391. is_hex:         ;check that A is hex, i.e. [0-9][A-F][a-f]
  392.                 ;in: A
  393.                 ;out: cy=1: *NOT* hex. A is saved
  394.  
  395.                 cp      '0'
  396.                 ret     c
  397.                 cp      '9'+1
  398.                 ccf
  399.                 ret     nc
  400.  
  401.                 cp      'A'
  402.                 ret     c
  403.                 cp      'F'+1
  404.                 ccf
  405.                 ret     nc
  406.                
  407.                 cp      'a'
  408.                 ret     c
  409.                 cp      'f'+1
  410.                 ccf
  411.                 ret
  412.  
  413.  
  414. process_file:   ;hl - asciiz filename
  415.                 ;a  - mode, 0 print, 1 check
  416.  
  417.                 ld      [.mode+1],a
  418.                 ld      [file_name],hl
  419.  
  420.                 ;in mode 0 (print CRCs), the name '-'
  421.                 ; is treated as stdin
  422.                 or      a
  423.                 jr      nz,.dofile
  424.  
  425.                 ld      de,stdin_arg
  426.                 call    strcmp
  427.                 jr      nz,.dofile
  428.  
  429.                 ;get STDIN
  430.                 OS_GETSTDINOUT
  431.                 ld      a,e
  432.                 ld      [file_hndl],a
  433.                 jr      .dohandle
  434. .dofile
  435.                 ld      de,[file_name]
  436.                 OS_OPENHANDLE
  437.                 or      a
  438.                 jp      nz,.file_error
  439.                 ld      a,b
  440.                 ld      [file_hndl],a
  441. .dohandle
  442.                 call    CS_START
  443.  
  444. .readloop0
  445.         ld de,DISKBUF
  446.         ld hl,DISKBUFsz
  447. ;de=buf
  448. ;hl=size
  449.         ld      a,[file_hndl]
  450.         ld      b,a
  451.         OS_READHANDLE
  452.         ;no difference between EOF and error in nedoos, so always treat as an EOF
  453.         ld a,h
  454.         or l
  455.         jr z,.closequit
  456.         ld b,h
  457.         ld c,l
  458.        
  459.         ;BC -- size
  460.         ld      hl,DISKBUF
  461.         call    CS_APPEND
  462.  
  463.         jr      .readloop0
  464. .closequit
  465.                 ld      a,[file_hndl]
  466.                 ld      b,a
  467.                 OS_CLOSEHANDLE
  468.  
  469.  
  470.                 ld      hl,CALCSUM
  471.                 push    hl
  472.                 call    CS_FINALIZE
  473.  
  474.  
  475. .mode           ld      a,#2E
  476.                 or      a
  477.  
  478.                 jr      z,.print
  479.  
  480.                 ;compare: first print filename
  481.                 ld      hl,[file_name]
  482.                 call    prtext
  483.                 ld      hl,txtcds
  484.                 call    prtext
  485.  
  486.                 pop     hl
  487.                 ld      de,CHKSUM
  488.                 call    strcasecmp
  489.  
  490.                 ld      hl,txtOK
  491.                 jr      z,.nofail
  492.                 ld      hl,txtFAIL
  493. .nofail
  494.                 jr      .prtext
  495. .print
  496.                 pop     hl
  497.                 call    prtext
  498.  
  499.                 ld      hl,txtdblspc
  500.                 call    prtext
  501.  
  502.                 ld      hl,[curr_arg]
  503.                 call    prtext
  504.  
  505.                 ld      hl,txtcrlf
  506.                 jr      .prtext
  507.  
  508. .file_error
  509.                 ld      hl,[file_name]
  510.                 call    prtext
  511.                 ld      hl,file_error
  512. .prtext
  513.                 jp      prtext
  514.  
  515.  
  516.  
  517. fatal_err:              ; fatal error so that we can't print even error message
  518.                 ld      hl,2
  519.                 QUIT
  520.  
  521.  
  522.  
  523. got_no_args:    ; no args given, print short help
  524.        
  525.                 ld      hl,[name_ptr]
  526.                 push    hl
  527.                 call    prtext
  528.                 ld      hl,noargs_msg1
  529.                 call    prtext
  530.                 pop     hl
  531.                 call    prtext
  532.                 ld      hl,noargs_msg2
  533.                 call    prtext
  534. error_exit:
  535.                 ld      hl,1
  536.                 QUIT
  537.  
  538.  
  539. noargs_msg1:    db      ": no args given",13,10
  540.                 db      "Try '",0
  541. noargs_msg2:    db      " -h' for more information",13,10,0
  542.  
  543. help_msg1:      db      "CRC rev."
  544.  
  545. SV=SVNREVISION+1
  546. BEG=$
  547.         WHILE   SV>0
  548.                 db      '0'+(SV%10)
  549. SV=SV/10
  550.         ENDW
  551. CONTINUE=$
  552. END=$-1
  553.         WHILE   BEG<END
  554. V1={b BEG}
  555. V2={b END}
  556.         org     BEG
  557.         db      V2
  558.         org     END
  559.         db      V1
  560. BEG=BEG+1
  561. END=END-1
  562.         ENDW
  563.  
  564.                 org     CONTINUE
  565.                 db      13,10
  566.  
  567.                 db      "Usage: ",0
  568. help_msg2:      db      " [OPTION] [FILE]...",13,10
  569.                 db      "Print ",0
  570. help_msg3:      db      " checksums.",13,10,13,10
  571.                 db      "When filename is -, read standard input.",13,10
  572.                 db      "Options:",13,10
  573.                 db      "  -c   read checksums from the FILE(s) (but not stdin) and check them.",13,10
  574.                 db      "       file format: ^<CHKSUM><spaces><filename><EOL>",13,10
  575.                 db      "  -h   display this help and exit",13,10
  576.                 db      13,10
  577.                 db      0
  578.  
  579. stdin_arg:      db      "-",0
  580. help_arg:       db      "-h",0
  581. chk_arg:        db      "-c",0
  582.  
  583. txtcds:         db      ":"     ;colon, double space
  584. txtdblspc:      db      "  ",0
  585. txtcrlf:        db      13,10,0
  586.  
  587. txtOK:          db      "OK!",13,10,0
  588. txtFAIL:        db      "fail!",13,10,0
  589.  
  590. file_error:     db      ": Error opening or reading file",13,10,0
  591. format_error:   db      ": File format error",13,10,0
  592.  
  593. name_to_file:   db      ": ",0
  594.  
  595.  
  596.  
  597. strcmp:         ;compare strings pointed by HL and DE, case-sensitive.
  598.                 ;in: hl, de -- ptr to asciiz,
  599.                 ;out: Z,NC if equal, NZ,NC if str(DE)>str(HL), NZ,C if str(DE)<str(HL)
  600.                 ;kills: af,de,hl
  601.                 ;
  602.                 ld      a,[hl]
  603.                 or      a
  604.                 ld      a,[de]
  605.                 jr      z,.lastcmp
  606.                 or      a
  607.                 jr      z,.lastcmp
  608.                
  609.                 cp      [hl]
  610.                 inc     hl
  611.                 inc     de
  612.                 jr      z,strcmp
  613.                 ret
  614. .lastcmp
  615.                 cp      [hl]
  616.                 ret
  617.  
  618. strcasecmp:     ;same as strcmp, but english letters are compared without case
  619.                 ;kills: af,bc,de,hl
  620.  
  621.                 ld      c,'a'
  622. .loop
  623.                 ld      a,[hl]
  624.                 or      a
  625.                 jr      z,.hl_zero
  626.  
  627.                 cp      c       ;'a'
  628.                 jr      c,.hl_nonlower
  629.                 cp      'z'+1
  630.                 jr      nc,.hl_nonlower
  631.                 sub     'a'-'A'
  632. .hl_nonlower
  633.                 ld      b,a
  634.  
  635.                 ld      a,[de]
  636.                 or      a
  637.                 jr      z,.de_zero
  638.  
  639.                 cp      c       ;'a'
  640.                 jr      c,.de_nonlower
  641.                 cp      'z'+1
  642.                 jr      nc,.de_nonlower
  643.                 sub     'a'-'A'
  644. .de_nonlower
  645.                 cp      b
  646.                 inc     hl
  647.                 inc     de
  648.                 jr      z,.loop
  649.                 ret
  650. .hl_zero
  651.                 ld      a,[de]
  652.                 cp      [hl]    ;cp 0
  653.                 ret
  654. .de_zero
  655.                 cp      b
  656.                 ret
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663. skipword
  664. ;hl=string
  665. ;out: hl=terminator/space addr
  666. getword0
  667.         ld a,(hl)
  668.         or a
  669.         ret z
  670.         cp ' '
  671.         ret z
  672.         inc hl
  673.         jr getword0
  674.  
  675. skipspaces
  676. ;hl=string
  677. ;out: hl=after last space
  678.         ld a,(hl)
  679.         cp ' '
  680.         ret nz
  681.         inc hl
  682.         jr skipspaces
  683.  
  684.  
  685. prtext
  686.         ld a,(hl)
  687.         or a
  688.         ret z
  689.         push hl
  690.         push iy
  691.         PRCHAR_
  692.         pop iy
  693.         pop hl
  694.         inc hl
  695.         jr prtext
  696.        
  697.  
  698.  
  699. name_ptr:       dw      0
  700. curr_arg:       dw      0
  701. file_name:      dw      0
  702. argp_state:     db      0
  703.  
  704. file_hndl:      db      0
  705. list_hndl:      db      0
  706.  
  707. lpush:          db      0
  708. lpbyte:         db      0
  709. lptr:           dw      0
  710. lsz:            dw      0
  711.  
  712.  
  713.  
  714.  
  715.  
  716.         include "../_sdk/file.asm"
  717.         include "../_sdk/stdio.asm"
  718.  
  719. CALCSUM ds      CS_SYMLEN+1     ;checksum calculated by algorithm
  720.  
  721. CHKSUM  ds      CS_SYMLEN+1     ;checksum to check, taken from '-c filename' file
  722. FNAME   ds      MAXPATH_sz+1    ;file/path to check, taken from '-c filename' file
  723.  
  724.         IFNDEF  MODULE
  725.         define  MODULE "crc.asm"
  726.         ENDIF
  727.         include MODULE ;"crc.asm"
  728.  
  729. cmd_end
  730.  
  731.         display "Size ",/d,cmd_end-cmd_begin," bytes"
  732.  
  733.         IFNDEF  OUTFNAME
  734.         define  OUTFNAME "crc.com"
  735.         ENDIF
  736.         savebin OUTFNAME,cmd_begin,cmd_end-cmd_begin
  737.        
  738. ;;      LABELSLIST "../../us/user.l"
  739.  
  740.