.module Char ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.ToLower === ; ; Converts a character to its lowercase representation. ; ; INPUTS: ; REGISTERS ; * A - The character to convert. ; ; OUTPUTS: ; REGISTERS ; * A - The lowercase character. ; ; DESTROYED: ; REGISTERS: ; * F ; ;@doc:end ;------------------------------------------------------------------------------- ToLower cp 'A' ret c cp 'Z'*1+1 ret nc add a,'a'-'A' ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.ToUpper === ; ; Converts a character to its uppercase representation. ; ; INPUTS: ; REGISTERS ; * A - The character to convert. ; ; OUTPUTS: ; REGISTERS ; * A - The uppercase character. ; ; DESTROYED: ; REGISTERS: ; * F ; ;@doc:end ;------------------------------------------------------------------------------- ToUpper cp 'a' ret c cp 'z'*1+1 ret nc add a,'A'-'a' ret ------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.ParseHexNybble === ; ; Parses a hex nybble character. ; ; INPUTS: ; REGISTERS ; * A - The character to convert. ; ; OUTPUTS: ; REGISTERS ; * F - Carry flag set on error (out of range value). ; * A - The converted hex value (from $00..$0F). ; ; DESTROYED: ; REGISTERS: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- ParseHexNybble cp '0' ret c cp '9'*1+1 jr nc,+ sub '0' or a ret + call ToUpper cp 'A' ret c cp 'F'*1+1 jr nc,+ sub 'A'*1-10 or a ret + scf ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.IsWhitespace === ; ; Checks if a character is whitespace or not. ; ; INPUTS: ; REGISTERS ; * A - Character to check. ; ; OUTPUTS: ; REGISTERS ; * F - Z set if character is whitespace, NZ otherwise. ; ; DESTROYED: ; REGISTERS ; * F ; ;@doc:end ;------------------------------------------------------------------------------- IsWhitespace cp ' ' ret z cp '\t' ret z cp '\n' ret z cp '\r' ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.IsNumeric === ; ; Checks if a character is numeric or not. ; ; INPUTS: ; REGISTERS ; * A - Character to check. ; ; OUTPUTS: ; REGISTERS ; * F - Z set if character is numeric (0-9), NZ otherwise. ; ; DESTROYED: ; REGISTERS ; * F ; ;@doc:end ;------------------------------------------------------------------------------- IsNumeric cp '0' jr c,IsNumberNo cp '9'*1+1 jr nc,IsNumberNo IsNumberYes cp a ret IsNumberNo cp '0' ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.IsLegalInVariableName === ; ; Checks if a character is legal in a variable name or not. ; ; INPUTS: ; REGISTERS ; * A - Character to check. ; ; OUTPUTS: ; REGISTERS ; * F - Z set if character is legal numeric (A-Z, a-z, 0-9, _), NZ otherwise. ; ; DESTROYED: ; REGISTERS ; * F ; ;@doc:end ;------------------------------------------------------------------------------- IsLegalInVariableName cp '_' ret z call IsNumeric ret z ; Deliberate run-on. ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.IsLetter === ; ; Checks if a character is a letter or not. ; ; INPUTS: ; REGISTERS ; * A - Character to check. ; ; OUTPUTS: ; REGISTERS ; * F - Z set if character is numeric (A-Z or a-z), NZ otherwise. ; ; DESTROYED: ; REGISTERS ; * F ; ;@doc:end ;------------------------------------------------------------------------------- IsLetter cp 'A' jr c,IsLetterNo cp 'z'*1+1 jr nc,IsLetterNo cp 'Z'*1+1 jr c,IsLetterYes cp 'a' jr c,IsLetterNo IsLetterYes cp a ret IsLetterNo cp 'a' ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.ParseDecimal === ; ; Parses a decimal digit. ; ; INPUTS: ; REGISTERS ; * A - The character to convert. ; ; OUTPUTS: ; REGISTERS ; * F - Carry flag set on error (out of range value). ; * A - The parsed value (from 0-9). ; ; DESTROYED: ; REGISTERS: ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- ParseDecimal call IsNumeric jr z,+ scf ret + sub '0' or a ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.IsTerminator === ; ; Checks if a character is a NUL or CR terminator or not. ; ; INPUTS: ; REGISTERS ; * A - Character to check. ; ; OUTPUTS: ; REGISTERS ; * F - Z set if character is a terminator, NZ otherwise. ; ; DESTROYED: ; REGISTERS ; * F ; ;@doc:end ;------------------------------------------------------------------------------- IsTerminator or a ret z cp '\r' ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === Char.CaseInsensitiveCompare === ; ; Checks if two characters are equivalent, ignoring case differences. ; ; INPUTS: ; REGISTERS ; * B - One of the characters. ; * C - The other character. ; ; OUTPUTS: ; REGISTERS ; * F - Z set if characters are equivalent, NZ otherwise. ; ; DESTROYED: ; REGISTERS ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- CaseInsensitiveCompare ld a,b cp c ret z cp 'a' jr c,+ cp 'z'*1+1 jr nc,+ add a,'A'-'a' + cp c ret z ld b,a ld a,c cp 'a' jr c,+ cp 'z'*1+1 jr nc,+ add a,'A'-'a' + cp b ret .endmodule .module String ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.ToLower === ; ; Converts a string to its lowercase representation. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to the NUL-terminated string to convert. ; ;@doc:end ;------------------------------------------------------------------------------- ToLower push hl push af - ld a,(hl) or a jr z,DoneToLower call Char.ToLower ld (hl),a inc hl jr - DoneToLower pop af pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.ToUpper === ; ; Converts a string to its uppercase representation. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to the NUL-terminated string to convert. ; ;@doc:end ;------------------------------------------------------------------------------- ToUpper push hl push af - ld a,(hl) or a jr z,DoneToUpper call Char.ToUpper ld (hl),a inc hl jr - DoneToUpper pop af pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.Compare === ; ; Compares two NUL/CR-terminated strings. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to one NUL/CR-terminated string. ; * DE - Pointer to the other NUL/CR-terminated string. ; ; OUTPUTS: ; REGISTERS ; * F - Z is set if the strings are the same. ; ; DESTROYED: ; REGISTERS ; * AF ; ;@doc:end ;------------------------------------------------------------------------------- Compare push hl push de - ld a,(de) cp (hl) jr nz,+ or a jr z,+ cp '\r' jr z,+ inc hl inc de jr - + pop de pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.Length === ; ; Measures the length of a NUL-terminated string. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to the NUL-terminated string to measure. ; ; OUTPUTS: ; REGISTERS ; * A - Length of the string (in bytes). ; ; DESTROYED: ; REGISTERS ; * F ; ;@doc:end ;------------------------------------------------------------------------------ Length push bc push hl ld b,0 - ld a,(hl) or a jr z,+ inc b inc hl jr - + ld a,b or a pop hl pop bc ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.Copy === ; ; Copies a string from one location to another. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to the source NUL-terminated string to copy. ; * DE - Pointer to the destination memory address. ; * B - Maximum length of the copied string (1..256). ; ; OUTPUTS: ; REGISTERS ; * F - Z is set if the entire string was copied. ; ; DESTROYED: ; REGISTERS ; * AF ; ;@doc:end ;------------------------------------------------------------------------------ Copy push hl push de - ld a,(hl) ld (de),a inc hl inc de or a jr z,+ djnz - or a + pop de pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.ParseHexByte === ; ; Parses a hex byte and returns the value. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to the source string to parse. ; ; OUTPUTS: ; REGISTERS ; * F - Carry is set on error. ; * A - If successful, contains the parsed value. ; ; DESTROYED: ; REGISTERS ; * AF ; ;@doc:end ;------------------------------------------------------------------------------ ParseHexByte push hl push de ld d,0 ; Running total. ld a,(hl) - call Char.ParseHexNybble jr c,DoneParseHexByte ld e,a ld a,d and $F0 jr nz,DoneParseHexByteError ld a,d add a,a add a,a add a,a add a,a add a,e ld d,a inc hl ld a,(hl) or a jr nz,- ld a,d jr DoneParseHexByte DoneParseHexByteError scf DoneParseHexByte pop de pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.ParseHexByte === ; ; Parses a hex byte and returns the value. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to the source string to parse. ; ; OUTPUTS: ; REGISTERS ; * F - Carry is set on error. ; * DE - If successful, contains the parsed value. ; ; DESTROYED: ; REGISTERS ; * AF, DE ; ;@doc:end ;------------------------------------------------------------------------------ ParseHexWord push hl push bc ld d,h ld e,l ld hl,0 ; Running total. ld a,(de) - call Char.ParseHexNybble jr c,DoneParseHexWord ld b,0 ld c,a ld a,h and $F0 jr nz,DoneParseHexWordError sla l \ rl h sla l \ rl h sla l \ rl h sla l \ rl h add hl,bc inc de ld a,(de) or a jr nz,- ld d,h ld e,l jr DoneParseHexWord DoneParseHexWordError scf DoneParseHexWord pop bc pop hl ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.CompareWildcards === ; ; Compares two NUL-terminated strings using wildcards. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to NUL-terminated string to test. ; * DE - Pointer to the NUL-terminated string with wildcards. ; ; OUTPUTS: ; REGISTERS ; * F - Z is set if the strings match. ; ; DESTROYED: ; REGISTERS ; * AF, HL, DE ; ;@doc:end ;------------------------------------------------------------------------------- CompareWildcards ld a,(de) cp (hl) jr nz,+ or a ret z - inc hl inc de jr CompareWildcards + ld a,(hl) or a jr nz,+ inc a ret + ld a,(de) cp '?' jr z,- cp '*' ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.FindNext === ; ; Finds the string after the current one. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to current NUL-terminated string. ; ; OUTPUTS: ; REGISTERS ; * HL - Pointer to next string. ; ; ;@doc:end ;------------------------------------------------------------------------------- FindNext push af - ld a,(hl) inc hl or a jr nz,- pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.FindPrevious === ; ; Finds the string before the current one. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to current NUL-terminated string. ; ; OUTPUTS: ; REGISTERS ; * HL - Pointer to previous string. ; ; ;@doc:end ;------------------------------------------------------------------------------- FindPrevious push af - dec hl dec hl ld a,(hl) inc hl or a jr nz,- pop af ret ;------------------------------------------------------------------------------- ;@doc:routine ; ; === String.Match === ; ; Compares a pattern against a string to see if it matches. ; ; INPUTS: ; REGISTERS ; * HL - Pointer to NUL or CR terminated input string to check. ; * DE - Pointer to NUL or CR terminated pattern string. ; ; OUTPUTS: ; REGISTERS ; * F - Z is set if the pattern matches the input string, reset if it does ; not. ; ; DESTROYED: ; REGISTERS ; * AF, BC, DE, HL. ; ;@doc:end ;------------------------------------------------------------------------------- Match Match.NextInputChar ; Check that we haven't reached the end of the input. ld a,(hl) call Char.IsTerminator jr z,Match.EndOfInput ld c,a Match.NextPatternChar ld a,(de) inc de cp '?' jr nz,+ inc hl jr Match.NextInputChar ; Single character wildcard. + cp '*' jr z,Match.HandleWildcard ; Regular character search. inc hl cp c jr z,Match.NextInputChar ; Try it uppercased? cp 'a' jr c,+ cp 'z'*1+1 jr nc,+ add a,'A'-'a' + cp c jr z,Match.NextInputChar ; Try uppercasing both? ld b,a ld a,c cp 'a' jr c,+ cp 'z'*1+1 jr nc,+ add a,'A'-'a' + cp b jr z,Match.NextInputChar ; Failed. ret Match.HandleWildcard ; hl -> input. ; de -> pattern. ; If a * wildcard is the last thing in a pattern then we've definitely matched the input. ld a,(de) call Char.IsTerminator ret z ; In case we have two ** for some weird reason. ;cp '*' ;jr z,Match.NextPatternChar Match.HandleWildcard.NextInputChar ld a,(hl) call Char.IsTerminator jr nz,+ ; We have something meaningful after the * but we're at the end of the input. ; Bail out! cp '#' ; nz ret + ; Match HL against DE. push hl push de call Match.CheckEndOfWildcard jr z,Match.FoundEndOfWildcard pop de pop hl inc hl jr Match.HandleWildcard.NextInputChar Match.FoundEndOfWildcard pop af pop af jr Match.NextInputChar Match.CheckEndOfWildcard ld a,(de) cp '*' ret z call Char.IsTerminator ret z inc de ld b,a ld c,(hl) inc hl call Char.CaseInsensitiveCompare ret nz jr Match.CheckEndOfWildcard Match.EndOfInput ld a,(de) call Char.IsTerminator ret z cp '*' ret .endmodule