home *** CD-ROM | disk | FTP | other *** search
- name scantd
- title SCANTD.ASM --- time & date input conversion
- page 55,132
- ;
- ;
- ; SCANTD.ASM --- Convert ASCII times and dates
- ; to binary in MS-DOS format.
- ;
- ; Copyright (c) 1988 Ziff Communications Co.
- ; PC Magazine * Ray Duncan
- ;
- ; This module contains two public routines:
- ;
- ;
- ; SCANTIME convert ASCII time to binary
- ;
- ; Call with: DS:SI = address of string
- ;
- ; Returns: Carry = Set if bad time
- ; or
- ; Carry = Clear if good time
- ; CH = hour
- ; CL = minute
- ; DH = second
- ; DL = hundredths
- ; DS:SI = address+1 of terminator
- ; other registers preserved
- ;
- ;
- ; SCANDATE convert ASCII date to binary
- ;
- ; Call with: DS:SI = address of string
- ;
- ; Returns: Carry = Set if bad date
- ; or
- ; Carry = Clear if good date
- ; CX = year (1980+)
- ; DH = month (1-12)
- ; DL = day (1-31)
- ; DS:SI = address+1 of terminator
- ; other registers preserved
- ;
-
- DGROUP group _DATA
-
-
- _DATA segment word public 'DATA'
-
- n1 dw 0 ; first converted field
- n2 dw 0 ; second converted field
- n3 dw 0 ; third converted field
-
- dlmtab db '/-.' ; valid date delimiters
- dlmtab_len equ $-dlmtab ; length of table
-
- tlmtab db ':.' ; valid time delimiters
- tlmtab_len equ $-tlmtab ; length of table
-
- ; date format table
- dftab dw mdy ; code 0 = mon/day/year
- dw dmy ; code 1 = day/mon/year
- dw ymd ; code 2 = year/mon/day
-
- dfptr dw 0 ; becomes address of
- ; mdy, dmy, or ymd
-
- mdy dw n2 ; day
- dw n1 ; month
- dw n3 ; year
-
- dmy dw n1 ; day
- dw n2 ; month
- dw n3 ; year
-
- ymd dw n3 ; day
- dw n2 ; month
- dw n1 ; year
-
- daytab dw 31,28,31 ; days in month
- dw 30,31,30
- dw 31,31,30
- dw 31,30,31
-
- cbuff db 34 dup (0) ; current country info
-
- _DATA ends
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP
-
- extrn atoi:near ; we need ATOI routine
-
- public scantime ; make these routines
- public scandate ; available to Linker
-
-
- scantime proc near ; convert ASCII time to binary
-
- push ax ; save registers
- push bx
- push di
- push es
-
- call getctry ; get internationalization
- ; info if first call
-
- call chknum ; convert first field
- jc scant9 ; jump, bad number
- mov n1,ax ; save result
-
- mov al,[si-1] ; check time delimiter
- call chktlm
- jc scant9 ; jump if no good
-
- call chknum ; convert second field
- jc scant9 ; jump, bad number
- mov n2,ax ; save result
-
- mov n3,0 ; force seconds = 0
-
- mov al,[si-1] ; another field present?
- call chktlm ; if no delimiter,
- jc scant1 ; assume seconds absent
-
- call chknum ; convert third field
- jc scant9 ; jump, bad number
- mov n3,ax ; save value
-
- scant1: ; validate entry
-
- cmp word ptr n1,0 ; hours must be 0-23
- jc scant9 ; jump, bad hour
- cmp word ptr n1,24
- cmc
- jc scant9 ; jump, bad hour
-
- cmp word ptr n2,0 ; minutes must be 0-59
- jc scant9 ; jump, bad minute
- cmp word ptr n2,60
- cmc
- jc scant9 ; jump, bad minute
-
- cmp word ptr n3,0 ; seconds must be 0-59
- jc scant9 ; jump, bad second
- cmp word ptr n3,60
- cmc
- jc scant9 ; jump, bad second
-
- ; load the results...
- mov ch,byte ptr n1 ; hours
- mov cl,byte ptr n2 ; minutes
- mov dh,byte ptr n3 ; seconds
- mov dl,0 ; hundredths always = 0
-
- scant9: ; common exit point
- pop es ; restore registers
- pop di
- pop bx
- pop ax
- ret ; return to caller
-
- scantime endp
-
-
- scandate proc near ; convert ASCII date to binary
-
- push ax ; save registers
- push bx
- push di
- push es
-
- call getctry ; get internationalization
- ; info if first call
-
- call chknum ; convert first field
- jc scand9 ; jump, bad number
- mov n1,ax ; save result
-
- mov al,[si-1] ; get delimiter
- call chkdlm ; and check it
- jc scand9 ; exit, bad delimiter
-
-
- call chknum ; convert second field
- jc scand9 ; jump, bad number
- mov n2,ax ; save result
-
- mov al,[si-1] ; get delimiter
- call chkdlm ; and check it
- jc scand9 ; exit, bad delimiter
-
- call chknum ; convert third field
- jc scand9 ; jump, bad number
- mov n3,ax ; and save result
-
- ; validate entry and
- ; load results...
-
- mov bx,dfptr ; point to year
- mov bx,[bx+4] ; year must be 80-99
- cmp word ptr [bx],80
- jc scand9 ; jump, bad year
- cmp word ptr [bx],100
- cmc
- jc scand9 ; jump, bad year
- mov cx,[bx] ; load year and correct
- add cx,1900 ; to range 1980-1999
-
- ; adjust days/month table
- mov daytab+2,28 ; assume not leap year
- test word ptr [bx],3 ; is it a leap year?
- jnz scand1 ; jump, not multiple of 4
- mov daytab+2,29 ; fix table for leap year
-
- scand1: mov bx,dfptr ; point to month
- mov bx,[bx+2]
- cmp word ptr [bx],1 ; month must be 1-12
- jc scand9 ; jump, bad month
- cmp word ptr [bx],13
- cmc
- jc scand9 ; jump, bad month
- mov dh,byte ptr [bx]; load month result
- mov di,[bx] ; also prepare to index
- dec di ; into days/month table
- shl di,1
-
- mov bx,dfptr ; point to day
- mov bx,[bx]
- cmp word ptr [bx],1 ; day must be >= 1
- jc scand9 ; jump, bad day
- mov ax,[di+daytab] ; get max day for this
- ; month from table
- cmp ax,[bx]
- jc scand9 ; jump, bad day
- mov dl,byte ptr [bx]; load day result
-
- scand9: ; common exit point
- pop es ; restore registers
- pop di
- pop bx
- pop ax
- ret ; return to caller
-
- scandate endp
-
-
- chkdlm proc near ; check date delimiter
- ; call with:
- ; AL = character to check
- ; returns:
- ; Carry = Clear if OK
- ; Carry = Set if not OK
-
- push ds ; make delimiter table
- pop es ; addressable
- mov di,offset DGROUP:dlmtab
- mov cx,dlmtab_len
-
- repne scasb ; compare to table
-
- je chkd9 ; jump if match found
- ; (Carry is cleared)
-
- stc ; else force Carry = set
-
- chkd9: ret ; back to caller
-
- chkdlm endp
-
-
- chktlm proc near ; check time delimiter
- ; call with:
- ; AL = character to check
- ; returns:
- ; Carry = Clear if OK
- ; Carry = Set if not OK
-
- push ds ; make delimiter table
- pop es ; addressable
- mov di,offset DGROUP:tlmtab
- mov cx,tlmtab_len
-
- repne scasb ; compare to table
-
- je chkt9 ; jump if match found
- ; (Carry is cleared)
-
- stc ; else force Carry = set
-
- chkt9: ret ; back to caller
-
- chktlm endp
-
-
- chknum proc near ; check for valid numeric
- ; field and convert it
- ; call with:
- ; DS:DI = ASCII field
- ; returns:
- ; Carry = clear if OK
- ; AX = value of field
- ; or
- ; Carry = set if not OK
-
- ; check if >= '0'
- cmp byte ptr [si],'0'
- jb chkn1 ; jump, bad digit
-
- ; check if <= '9'
- cmp byte ptr [si],'9'+1
- cmc ; invert Carry flag
- jc chkn1 ; jump, bad digit
-
- call atoi ; convert field and
- clc ; clear carry flag
-
- chkn1: ret ; back to caller
-
- chknum endp
-
-
- getctry proc near ; get country information
-
- test dfptr,-1 ; did we already get info?
- jnz getc2 ; if we did, just exit
-
- mov ax,3000h ; Fxn. 30h = get DOS vers.
- int 21h ; transfer to MS-DOS
-
- or al,al ; is it version 1.x?
- jz getc1 ; yes, jump
-
- mov ax,3800h ; get current country info
- mov dx,offset DGROUP:cbuff
- int 21h ; transfer to MS-DOS
-
- getc1: ; get date code (default=0)
- mov bx,word ptr cbuff
- shl bx,1 ; extract pointer to
- mov ax,[bx+dftab] ; date format table
- mov dfptr,ax
-
- getc2: ret ; back to caller
-
- getctry endp
-
- _TEXT ends
-
- end
-