;
; SYSLIB Module Name:  SEVAL
; Author:  Richard Conn
; SYSLIB Version Number:  2.0
; Module Version Number:  1.0
; Module Entry Points:
;       EVAL
; Module External References:
;       CAPS            EVAL10          EVAL16          EVAL2
;       EVAL8
;

;
;  EVAL --
;       On input, HL points to a string of ASCII binary, octal, decimal,
; or hexadecimal characters to convert to binary; this string may take
; any of the following forms --
;
;       bbbbbbbbbbbbbbbbB -- b=0 or b=1; binary string
;       ttttt or tttttD -- 0<= t <= 9; decimal string
;       hhhhH or hhhhX -- 0<= h <= F; hexadecimal string
;       oooooooO or oooooooQ -- 0<= o <=7; octal string
;
;       On return, DE = value, HL points to next byte after
; string, A=E; BC is not affected.
;       On return, CARRY Set means error, and HL pts to byte after error
;

       EXT     CAPS    ; CAPITALIZATION ROUTINE
       EXT     EVAL16  ; CONVERT HEX STRING
       EXT     EVAL10  ; CONVERT DEC STRING
       EXT     EVAL8   ; CONVERT OCT STRING
       EXT     EVAL2   ; CONVERT BIN STRING

EVAL::
       PUSH    B       ; SAVE BC
       PUSH    H       ; SAVE PTR TO 1ST CHAR
       XRA     A       ; A=0
       STA     CFLAG   ; SET CHARACTER FOUND FLAG TO NULL

;  Find end of string
FEND:
       MOV     A,M     ; GET BYTE
       CALL    CAPS    ; CAPITALIZE
       SUI     '0'     ; ASSUME HEX
       JC      FEDONE  ; DONE
       CPI     10      ; 0-9?
       JC      FECONT  ; CONTINUE
       SUI     7
       CPI     16      ; A-F?
       JNC     FEDONE

;  Digit found -- set flag and point to next
FECONT:
       MVI     A,1     ; GET A 1
       STA     CFLAG   ; SET FLAG
       INX     H       ; PT TO NEXT
       JMP     FEND

;  Found end of string
FEDONE:
       MOV     A,M     ; GET OFFENDING CHAR
       CALL    CAPS    ; CAPITALIZE
       MOV     C,A
       DCX     H       ; GET PREVIOUS CHAR (POSSIBLY BINARY OR DEC)
       MOV     A,M     ; GET IT
       CALL    CAPS    ; CAPITALIZE
       MOV     B,A
       POP     H       ; RESTORE POINTER TO 1ST CHAR IN STRING
       LXI     D,0     ; SET ZERO VALUE (ERROR EXIT)
       LDA     CFLAG   ; ANY CHARS?
       JZ      DONE    ; DONE IF NONE

;  Determine type of string (H,X=hex; O,Q=oct; B=bin; D,other=dec)
       MOV     A,C     ; GET TERMINATING CHAR
       CPI     'H'     ; HEX
       JZ      EHEX
       CPI     'X'
       JZ      EHEX
       CPI     'O'     ; OCTAL
       JZ      EOCT
       CPI     'Q'
       JZ      EOCT
       MOV     A,B     ; GET PREVIOUS CHAR FOR BINARY CHECK
       CPI     'B'     ; BINARY?
       JZ      EBIN

;  Evaluate string as decimal
       CALL    EVAL10  ; EVALUATE AS DECIMAL
       MOV     A,M     ; MAY PT TO D
       CALL    CAPS
       CPI     'D'     ; INCR HL IF SO
       JNZ     DONE
       INX     H       ; PT TO NEXT
       JMP     DONE

;  Evaluate string as hexadecimal
EHEX:
       CALL    EVAL16  ; EVAUATE AS HEXADECIMAL
       MOV     A,M     ; MUST PT TO H OR X
       CALL    CAPS
       INX     H       ; PT TO NEXT
       CPI     'H'
       JZ      DONE
       CPI     'X'
       JZ      DONE

;  String Error -- set flag
ERROR:
       MOV     A,E     ; LOW-ORDER IN A
       STC             ; SET CARRY FLAG FOR ERROR
       POP     B       ; RESTORE BC
       RET

;  Evaluate string as octal
EOCT:
       CALL    EVAL8   ; EVALUATE AS OCTAL
       MOV     A,M     ; MUST PT TO O OR Q
       CALL    CAPS
       INX     H       ; PT TO NEXT
       CPI     'O'
       JZ      DONE
       CPI     'Q'
       JZ      DONE
       JMP     ERROR   ; ERROR OTHERWISE

;  Flag buffer
CFLAG:  DS      1       ; 0 IF NO CHARS IN STRING, 1 OTHERWISE

;  Evaluate string as binary
EBIN:
       CALL    EVAL2   ; EVALUATE AS BINARY
       MOV     A,M     ; MUST PT TO B
       CALL    CAPS
       INX     H       ; PT TO NEXT
       CPI     'B'
       JNZ     ERROR

;  Done with evaluation -- no error
DONE:
       MOV     A,E     ; LOW-ORDER IN A
       ORA     A       ; CLEAR CARRY FLAG
       POP     B       ; RESTORE BC
       RET

       END