home *** CD-ROM | disk | FTP | other *** search
- ; ***************************************************************************
- ; CSpread StringToNumeric Routine
- ;
- ; Version 1.2
- ;
- ; Written By David Hart (davey3000) 1998-1999
- ; ***************************************************************************
- ;
- ; Notes: Remember to include the standard TI include files in your main
- ; program before including this file.
- ;
- ; How To Use: Just call CheckStrNumeric to check that a string is a valid
- ; number, and then call StringToNumeric if it is to convert
- ; the string to a real number in OP1. Note that this
- ; DESTROYS THE ORIGINAL STRING.
- ;
- ; LEGAL DISCLAIMER
- ;
- ; This SOFTWARE (that is, all software programs included with this text file)
- ; is free-ware, and therefore is provided "as-is" without any kind of warranty.
- ; I provide no guarantee as to the functionality, usefulness, fitness for a
- ; particular purpose or merchantability of the SOFTWARE. I may not be held
- ; liable for any damages whatsoever arising from the use of or inability to
- ; use the SOFTWARE.
- ;
- ;
- ; Please feel free to use this code however you see fit. I would appreciate
- ; a small credit in the documentation of any program that you produce
- ; which uses this code.
- ;
-
-
- ; ***** Required variables - these can point to any spare place in memory
- ;
- decimal_point_pos equ _textShadow+0 ; Position of decimal point
- ; in a number (2 BYTES)
- exponent_len equ _textShadow+2 ; Length of the exponent
- ; string, or zero if none -
- ; valid when converting a str
- ; to a number (1 BYTE)
-
-
- ; ***** Check the string pointed to by HL, of length B, to see if it is
- ; numeric. CF set if non-numeric, otherwise cleared - Destroys A
- CheckStrNumeric:
- push bc
- push de
- push hl
-
- ld c,0 ; C is the status register, and its
- ; bits mean as follows:
- ; 0 - Set when decimal point found
- ; 1 - Set when first non-space char
- ; found
- ; 2 - Set when exponent char found
- ; 3 - Set when first numeric digit
- ; found
- ; 4 - Set when exponent char first
- ; found, reset when next char is
- ; checked - used to allow a neg
- ; sign after exponent char
-
- ld d,0 ; D holds the index of the current
- ; digit, relative to the start of the
- ; number
-
- check_byte_numeric:
- ld a,(hl) ; Get current char
-
- cp Lspace ; Spaces are not counted as digits, but
- jr nz,no_more_spaces ; are accepted if before any other
- bit 1,c ; chars
- jr z,is_numeric_byte_no_count
- jr not_numeric
-
- no_more_spaces:
- set 1,c ; Non-space char found, so no more
- ; spaces allowed
-
- check_exponent:
- cp Lexponent ; Check for exponent (only one allowed)
- jr nz,check_dec_point
- bit 2,c
- jr nz,not_numeric
- set 2,c ; Set exponent just found
- set 4,c
- res 3,c ; Must be at least one numeric digit
- jr is_numeric_byte_no_res_exp
-
- check_dec_point:
- cp Lperiod ; Check for decimal point
- jr nz,check_neg
- bit 0,c ; Check there is only one decimal
- jr nz,not_numeric ; point - exit with error if not
- bit 2,c ; Check no dec. point after exponent
- jr nz,not_numeric
- set 0,c
- jr is_numeric_byte
-
- check_neg:
- cp Lneg ; Check for negative (-) sign
- jr nz,check_numbers
- xor a ; Check - sign is at start of number
- cp d
- jr z,is_numeric_byte
- bit 4,c
- jr nz,is_numeric_byte
- jr not_numeric
-
- check_numbers:
- cp L0 ; Check for numbers (final filter)
- jr c,not_numeric
- cp L9+1
- jr nc,not_numeric
- set 3,c ; Numeric char (digit) found, so record
- jr is_numeric_byte ; in C that it has been
-
- not_numeric:
- scf ; Non-numeric, so set CF
- jr check_str_numeric_exit
-
- is_numeric_byte:
- res 4,c ; Clear negative allowance after
- ; exponent
- is_numeric_byte_no_res_exp:
- inc d ; Count digit
- is_numeric_byte_no_count:
- inc hl ; Point HL to next char, and loop
- djnz check_byte_numeric
-
- bit 3,c ; Signal non-numeric string if no
- jr z,not_numeric ; numbers found
-
- or a ; Clear CF to signal numeric
-
- check_str_numeric_exit:
- pop hl
- pop de
- pop bc
- ret
-
-
- ; ***** Converts string in HL, length B, to number in OP1 (MUST be checked
- ; to be numeric with CheckStrNumeric first) - Destroys A AND THE STRING
- ; IT CHECKS
- StringToNumeric:
- push bc
- push de
- push hl
-
- push hl
- call _ZEROOP1 ; Clear OP1
- pop hl
-
- remove_initial_spaces:
- ld a,(hl) ; Remove all spaces at start of number
- cp Lspace
- jr nz,stop_spaces
- inc hl
- dec b
- jr remove_initial_spaces
- stop_spaces:
-
- ld de,_OP1 ; Store pointer to OP1 in DE
-
- ld a,(hl) ; Check whether first char of string
- cp Lneg ; is the -ve sign (-), and set A
- ld a,0 ; accordingly
- jr nz,not_negative_number
- ld a,$80
- inc hl
- dec b
- not_negative_number:
- ld (de),a ; Store type of OP1 (real) and sign
- inc de
-
- inc de ; Add 2 to DE to point to mantissa
- inc de
-
-
- ; ** Remove the exponent and everything after it
-
- xor a ; No exponent by default
- ld (exponent_len),a
-
- ld a,Lexponent ; Handle exponent (by altering string
- call FindByte ; length to remove it, and by setting
- jr c,no_exponent ; the num_has_exponent variable)
-
- ld c,a ; Store exponent value length
- ld a,b
- sub c
- ld (exponent_len),a
-
- ld b,c ; Set new string length
-
- ld a,c ; If exponent is before any numbers,
- or a ; then take it as being before 1
- jr nz,no_exponent
- push hl
- call _op1set1
- pop hl
- jp check_conv_exponent
- no_exponent:
-
-
- push hl ; Set default decimal point pos
- ld h,0
- ld l,b
- ld (decimal_point_pos),hl
- pop hl
-
-
- ; ** Remove the decimal point - makes all future tasks easier
-
- ld a,Lperiod ; Find decimal point pos, and store
- call FindByte
- jr c,no_dec_point
-
- dec b ; Reduce string length to allow for
- push hl ; removal of the dec. point, and store
- ld h,0 ; the position of the dec. point
- ld l,a
- ld (decimal_point_pos),hl
- pop hl
-
- cp b ; If decimal point is at end of string,
- jr z,no_dec_point ; it has already been removed fully
-
- push bc
- push de
- push hl
-
- ld h,0 ; Find length of string to move, and
- ld l,b ; store in BC
- ld a,(exponent_len)
- ld e,a
- ld d,h
- add hl,de
- ld de,(decimal_point_pos)
- or a
- sbc hl,de
- ld b,h
- ld c,l
-
- ld de,(decimal_point_pos)
- pop hl ; Store pointer to dec. point in HL
- push hl
- add hl,de
-
- ld d,h ; Get rid of decimal point (by setting
- ld e,l ; HL to point to byte after dec. point,
- inc hl ; and DE to point to dec. point)
- ldir
-
- pop hl
- pop de
- pop bc
- no_dec_point:
-
-
- find_first_non_zero_digit:
- ld a,(hl) ; Skip past any superfluous zeros
- cp L0
- jr nz,non_zero_digit_found
-
- inc hl ; Check next character is a number -
- ld a,(hl) ; don't remove zero if not
- dec hl
- cp L0
- jr nc,another_digit_after
- cp L9+1
- jr c,another_digit_after
-
- set_zero_number:
- call _OP1SET0 ; Main part of number is zero, so just
- jr no_get_exponent ; set entire number to zero, and exit
-
- another_digit_after:
- ld a,b ; Remove zero digit. Make sure there
- cp 1 ; is always at least one digit
- jr z,set_zero_number
- dec b
- inc hl
-
- push hl ; Correct decimal point pos
- ld hl,(decimal_point_pos)
- dec hl
- ld (decimal_point_pos),hl
- pop hl
- jr find_first_non_zero_digit
- non_zero_digit_found:
-
-
- add_digit_to_op1:
- ld a,(hl) ; Get first digit as ASCII char
- inc hl
-
- sub L0 ; Convert first char to BCD digit,
- rlca ; and shift to upper nibble of C
- rlca
- rlca
- rlca
- ld c,a
-
- dec b ; If last digit, then write straight
- jr nz,is_second_digit ; out to OP1 without a second digit
- ld (de),a
- jr fin_conv_number
-
- is_second_digit:
- ld a,(hl)
- inc hl
-
- sub L0 ; Store BCD digit in OP1
- or c
- ld (de),a
- inc de
-
- digit_conv_loop_end:
- djnz add_digit_to_op1 ; Check all digits
-
-
- fin_conv_number:
- push hl
- ld de,(decimal_point_pos) ; Calculate exponent based on decimal
- ld hl,$FBFF ; point pos
- add hl,de
- ld (_OP1EXPM),hl
- pop hl
-
- check_conv_exponent:
- ld a,(exponent_len) ; Check whether exponent must be
- or a ; processed
- jr z,no_get_exponent
-
- inc hl ; Adjust HL to point to value after
- ; exponent
-
- dec a ; Decrement exponent length to allow
- ld b,a ; for removed E sign, and limit
- ld a,(hl) ; exponent length to 3 digits - allows
- cp Lneg ; an extra char for the negation (-)
- ld a,3 ; sign if needed
- jr nz,no_neg_sign
- ld a,4
- no_neg_sign:
- call LimitBToA
-
- push bc
- push hl
- rst 08h ; Store main number in OP2
- pop hl
- pop bc
-
- call StringToNumeric ; Convert exponent from string to
- ; value in OP1
-
- call _CONVOP1 ; Convert exponent from float to binary
- ; word in DE
-
- ld a,(_OP1)
- or a
- jr z,normal_adjust_exp
- ld hl,(_OP2EXPM) ; Adjust exponent of main number
- or a ; (negative exponent)
- sbc hl,de
- ld (_OP2EXPM),hl
- jr restore_main_number
-
- normal_adjust_exp:
- ld hl,(_OP2EXPM) ; Adjust exponent of main number
- add hl,de ; (positive exponent)
- ld (_OP2EXPM),hl
-
- restore_main_number:
- call _OP2TOOP1 ; Restore main number
-
- no_get_exponent:
- pop hl
- pop de
- pop bc
- ret
-
-
- ; ***** Limits the value in B to the value in A (B will be less than or equal
- ; to A afterwards)
- LimitBToA:
- cp b
- ret nc
- ld b,a
- ret
-
-
- ; ***** Finds the first byte of value A in the block of memory pointed to
- ; by HL of length B - Returns position of value in A, or index of char
- ; after last char if not found - CF also set if byte not found
- FindByte:
- push bc
- push de
- push hl
-
- ld c,a ; C holds target value
- ld d,0 ; D holds current byte index
-
- check_for_byte:
- ld a,(hl) ; Search for byte value
- cp c
- jr z,byte_found
- inc d
- inc hl
- djnz check_for_byte
-
- ld a,d ; Indicate byte not found
- scf
- jr exit_find_byte
-
- byte_found:
- ld a,d ; Indicate byte found, and store index
- or a ; in A
-
- exit_find_byte:
- pop hl
- pop de
- pop bc
- ret
-
-