1
0

moved mescc to subdirectory

This commit is contained in:
acn
2020-03-10 16:11:38 +01:00
parent 564425aa64
commit 0021b0387a
10 changed files with 3 additions and 1 deletions

BIN
Blocks/mescc/CC.COM Normal file

Binary file not shown.

BIN
Blocks/mescc/CCOPT.COM Normal file

Binary file not shown.

BIN
Blocks/mescc/HEXTOCOM.COM Normal file

Binary file not shown.

BIN
Blocks/mescc/ZSM.COM Normal file

Binary file not shown.

203
Blocks/mescc/ctype.h Normal file
View File

@@ -0,0 +1,203 @@
/**
* @file ctype.h
* @brief Character tests and conversion functions.
* @author Miguel I. Garcia Lopez / FloppySoftware
*
* Character tests and conversion functions, for MESCC (Mike's Enhanced
* Small C Compiler for Z80 & CP/M).
*
* Revisions:
* - 19 Dec 2000 : Last revision.
* - 16 Apr 2007 : GPL'd.
* - 15 Aug 2016 : Documented. GPL v3.
*
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
*
* Licensed under the GNU General Public License v3.
*
* http://www.floppysoftware.es
* floppysoftware@gmail.com
*/
#ifndef CTYPE_H
#define CTYPE_H
/**
* @fn int isalpha(char ch)
* @brief Test if ch is a letter.
* @param ch - character to test
* @return true or false
*/
#asm
isalpha
ld a,l
ld hl,0
cp 'A'
ret c
cp 'Z'+1
jr c,isalpha1
cp 'a'
ret c
cp 'z'+1
ret nc
isalpha1
inc l
ret
#endasm
/**
* @fn int isdigit(char ch)
* @brief Test if ch is a decimal digit.
* @param ch - character to test
* @return true or false
*/
#asm
isdigit
ld a,l
ld hl,0
cp '0'
ret c
cp '9'+1
ret nc
inc l
ret
#endasm
/**
* @fn int isxdigit(char ch)
* @brief Test if ch is an hexadecimal digit.
* @param ch - character to test
* @return true or false
*/
#asm
isxdigit
LD C,L
CALL isdigit
RET C
LD HL,0
LD A,C
CP 'A'
RET C
CP 'G'
JR C,isxdigit1
CP 'a'
RET C
CP 'g'
RET NC
isxdigit1
INC L
RET
#endasm
/**
* @fn int isalnum(char ch)
* @brief Test if ch is a letter or a decimal digit.
* @param ch - character to test
* @return true or false
*/
#asm
isalnum
LD C,L
CALL isdigit
RET C
LD L,C
JP isalpha
#endasm
/**
* @fn int isupper(char ch)
* @brief Test if ch is a letter in uppercase.
* @param ch - character to test
* @return true or false
*/
#asm
isupper
ld a,l
ld hl,0
cp 'A'
ret c
cp 'Z'+1
ret nc
inc l
ret
#endasm
/**
* @fn int islower(char ch)
* @brief Test if ch is a letter in lowercase.
* @param ch - character to test
* @return true or false
*/
#asm
islower
ld a,l
ld hl,0
cp 'a'
ret c
cp 'z'+1
ret nc
inc l
ret
#endasm
/**
* @fn int toupper(char ch)
* @brief Convert letter to uppercase.
*
* If ch is not a letter in lowercase, returns ch unchanged.
*
* @param ch - character to convert
* @return ch in uppercase
*/
#asm
toupper
ld a,l
cp 'a'
ret c
cp 'z'+1
ret nc
sub 20h
ld l,a
ret
#endasm
/**
* @fn int tolower(char ch)
* @brief Convert letter to lowercase.
*
* If ch is not a letter in uppercase, returns ch unchanged.
*
* @param ch - character to convert
* @return ch in lowercase
*/
#asm
tolower
ld a,l
cp 'A'
ret c
cp 'Z'+1
ret nc
add 20h
ld l,a
ret
#endasm
#endif


945
Blocks/mescc/mescc.h Normal file
View File

@@ -0,0 +1,945 @@
/**
* @file mescc.h
* @brief Runtime library.
* @author Miguel I. Garcia Lopez / FloppySoftware
*
* Runtime library for MESCC (Mike's Enhanced
* Small C Compiler for Z80 & CP/M).
*
* This library file must be included first!
*
* Need following EQU's (generated by the compiler):
* - ccSTACKSIZE : Stack size in bytes.
*
* Supports following #defs:
* - #define CC_STDIO Support for stdin, stdout & stderr.
* - #define CC_REDIR Support for stdin & stdout redirection
* in command line (needs CC_STDIO).
* - #define CC_NO_MUL To exclude MULTIPLICATION code.
* - #define CC_NO_DIV To exclude DIVISION & MODULUS code.
* - #define CC_NO_SWITCH To exclude SWITCH code.
* - #define CC_NO_ARGS To exclude ARGC & ARGV code.
* - #define CC_NO_ORG To exclude ORG 0100H code.
*
* Sets the following #defines:
*
* - BYTE
* - WORD
* - BOOL
* - NULL
* - TRUE
* - FALSE
* - SIZEOF_CHAR
* - SIZEOF_INT
* - SIZEOF_PTR
*
* Revisions:
* - 16 Jan 2001 : Last revision.
* - 23 Mar 2007 : Expand ccladr1 and ccladr2 for more speed.
* - 16 Apr 2007 : GPL'd.
* - 26 Aug 2012 : Added standard defs.
* - 08 Dec 2014 : Minor changes.
* - 09 Dec 2014 : Added support for stdin, stdout & stderr with CC_STDIO.
* - 12 Dec 2014 : Added support for stdin & stdout redirection in command line with CC_REDIR.
* - 16 Jan 2015 : Added SIZEOF_??? definitions.
* - 16 Feb 2015 : Modified / added code in cctmpw, ccxpb2, ccxpb, ccxpb3, ccxpw2
* ccxpw, ccxpw3, ccladr2sv, ccladr2, ccladr1sv, ccladr1,
* to avoid use of IX register.
* - 20 Mar 2015 : Added support for CC_NO_MUL, CC_NO_DIV, CC_NO_SWITCH, CC_NO_ARGS.
* - 12 Apr 2015 : Removed ccDEFARGS code.
* - 14 Jul 2015 : Modified code for << and >>, because a shift of 0 positions,
* resulted in a wrong value (they assumed a shift > 0) - ie: 128 >> 0 resulted in 0.
* - 19 Oct 2015 : Improved multiplication algorithm (ccmul & ccumul).
* - 05 Nov 2015 : Modified ccsxt.
* - 30 Nov 2015 : Added support for atexit().
* - 24 Jan 2016 : Added support for CC_NO_ORG.
* - 10 Dec 2016 : Documented. GPL v3.
*
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
*
* Licensed under the GNU General Public License v3.
*
* http://www.floppysoftware.es
* floppysoftware@gmail.com
*/
/* STANDARD DEFs
-------------
*/
#define BYTE unsigned char
#define WORD unsigned int
#define BOOL char
#define NULL 0
#define TRUE 1
#define FALSE 0
#define SIZEOF_CHAR 1 /* [unsigned] char */
#define SIZEOF_INT 2 /* [unsigned] int */
#define SIZEOF_PTR 2 /* pointer */
/* RUNTIME CODE
------------
*/
#ifndef CC_NO_ORG
#asm
; Start at TPA
ORG 0100H
#endasm
#endif
#asm
; Runtime address
ccrtadr:
; Set stack under BDOS (xx00h)
LD HL,(6)
LD L,0
LD SP,HL
; Leave space for stack and init. variables
LD DE,ccSTACKSIZE
OR A
SBC HL,DE
DEC HL
LD (ccfreelast),HL
LD DE,ccfreemem
LD (ccfreefirst),DE
OR A
SBC HL,DE
INC HL
LD (ccfreebytes),HL
JR NC,ccargs
; Error, no memory for stack
LD C,9
LD DE,ccerrstack
CALL 5
JP 0
ccerrstack
DEFB 'Runtime Error - No stack$'
; Setup command line arguments
ccargs
#endasm
#ifndef CC_NO_ARGS
#asm
; Copy command line
LD HL,81H
LD DE,ccmdbuf
LD BC,127
LDIR
LD A,(80H)
LD B,0
LD C,A
LD HL,ccmdbuf
ADD HL,BC
LD (HL),0
; Init. argc & argv
LD DE,cchptr
LD HL,ccmdbuf - 1
LD BC,1
ccspc
INC HL
LD A,(HL)
OR A
JR Z,ccarg
CP ' '
JR Z,ccspc
LD A,L
LD (DE),A
LD A,H
INC DE
LD (DE),A
INC DE
INC C
ccpar
INC HL
LD A,(HL)
OR A
JR Z,ccarg
CP ' '
JR NZ,ccpar
LD (HL),0
JR ccspc
ccarg
LD HL,cchptr - 2
PUSH BC ;argc
PUSH HL ;argv
#endasm
#endif
#ifdef CC_REDIR
#asm
CALL redir ;FIXME - Check errors
POP DE
POP BC
PUSH HL ;argc
PUSH DE ;argv
#endasm
#endif
#asm
; Execute program
CALL main
#endasm
/**
* @fn void exit(int code)
* @brief Exit to CP/M.
*
* FixMe: Return code is lost!
*/
#asm
; Exit to CP/M
exit
NOP ; Patch for atexit() -- 3 bytes.
NOP
NOP
#endasm
#ifdef CC_STDIO
BYTE *stdin, *stdout, *stderr; /* Sorry, no available FILE here */
#asm
LD HL,(stdin)
CALL ccflush
LD HL,(stdout)
CALL ccflush
JP 0
ccflush
LD A,H
OR L
RET Z
PUSH HL
CALL fclose
POP BC
RET
#endasm
#else
#asm
JP 0
#endasm
#endif
#asm
; Variables for memory functions
ccfreefirst
DEFW 0 ;Adr. first free byte
ccfreelast
DEFW 0 ;Adr. last free byte
ccfreebytes
DEFW 0 ;Number of free bytes
#endasm
#ifndef CC_NO_ARGS
#asm
; Variables for command line arguments
ccmdbuf
DEFS 128 ;Command line buffer
DEFW ccNULL ;Pointers table for argv
cchptr
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
DEFW ccNULL,ccNULL,ccNULL,ccNULL,ccNULL
ccNULL
DEFB 0 ;Null pointer
#endasm
#endif
#asm
; Basic routines
; Call formats to access locals:
;
; Format 1: CALL routine
; DEFB SpOffset
;
; Format 2: CALL routine
; DEFW SpOffset
; HL = unsigned char from local (format 2)
ccxgb2
CALL ccladr2
JR ccxgb3
; HL = unsigned char from local (format 1)
ccxgb
CALL ccladr1
ccxgb3
LD L,(HL)
LD H,0
RET
; HL = signed char from local (format 2)
ccxgc2
CALL ccladr2
JR ccgc
; HL = signed char from local (format 1)
ccxgc
CALL ccladr1
; HL = signed char from (HL)
ccgc
LD A,(HL)
; HL = signed char from A
ccsxt
LD L,A
RLCA
SBC A
LD H,A
RET
; LD H,0
; LD L,A
; AND 128
; RET Z
; DEC H
; RET
; HL = word from local (format 2)
ccxgw2
CALL ccladr2
JR ccgw
; HL = word from local (format 1)
ccxgw
CALL ccladr1
; HL = word from (HL)
ccgw
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
RET
; char local = HL (format 2)
ccxpb2
CALL ccladr2sv
JR ccxpb3
; char local = HL (format 1)
ccxpb
CALL ccladr1sv
ccxpb3
LD DE,(cctmpw)
LD (HL),E
EX DE,HL
RET
; int/ptr local = HL (format 2)
ccxpw2
CALL ccladr2sv
JR ccxpw3
; int/ptr local = HL (format 1)
ccxpw
CALL ccladr1sv
ccxpw3
LD DE,(cctmpw)
LD (HL),E
INC HL
LD (HL),D
EX DE,HL
RET
; Copy 1 word from HL to (DE)
ccpw
LD A,L
LD (DE),A
INC DE
LD A,H
LD (DE),A
RET
; Calc. local adress
cctmpw DEFW 0
ccladr2sv
LD (cctmpw),HL
ccladr2
POP DE
POP HL
LD C,(HL)
INC HL
LD B,(HL)
INC HL
PUSH HL
PUSH DE
LD HL,4
ADD HL,BC
ADD HL,SP
RET
ccladr1sv
LD (cctmpw),HL
ccladr1
POP DE
POP HL
LD B,0
LD C,(HL)
INC HL
PUSH HL
PUSH DE
LD HL,4
ADD HL,BC
ADD HL,SP
RET
; OR HL = HL | DE
ccor
LD A,L
OR E
LD L,A
LD A,H
OR D
LD H,A
RET
; XOR HL = HL ^ DE
ccxor
LD A,L
XOR E
LD L,A
LD A,H
XOR D
LD H,A
RET
; AND HL = HL & DE
ccand
LD A,L
AND E
LD L,A
LD A,H
AND D
LD H,A
RET
; LOGIC OR HL = DE || HL
cclgor
LD A,H
OR L
OR D
OR E
LD L,A
RET
;LD A,H
;OR L
;RET NZ
;LD A,D
;OR E
;RET Z
;INC L
;RET
; LOGIC AND HL = DE && HL
cclgand
LD A,H
OR L
RET Z
LD A,D
OR E
RET NZ
JP ccfalse
; HL = HL == DE
cceq
OR A
SBC HL,DE
; LOGIC NOT HL = !HL
cclgnot
LD A,H
OR L
JP NZ,ccfalse
INC L
RET
; HL = HL != DE
ccne
OR A
SBC HL,DE
RET
; HL = DE > HL (SIGNED)
ccgt
EX DE,HL
; HL = DE < HL (SIGNED)
cclt
CALL cccmp
RET C
DEC L
RET
; HL = DE <= HL (SIGNED)
ccle
CALL cccmp
RET Z
RET C
DEC L
RET
; HL = DE >= HL (SIGNED)
ccge
CALL cccmp
RET NC
DEC L
RET
; Compare DE with HL, and return: (SIGNED)
;
; CARRY if DE < HL
; ZERO if DE == HL
; HL = 1
cccmp
LD A,E
SUB L
LD E,A
LD A,D
SBC H
LD HL,1
JP M,cccmp1
OR E
RET
cccmp1
OR E
SCF
RET
; HL = DE <= HL (UNSIGNED)
ccule
CALL ccucmp
RET Z
RET C
DEC L
RET
; HL = DE >= HL (UNSIGNED)
ccuge
CALL ccucmp
RET NC
DEC L
RET
; HL = DE > HL (UNSIGNED)
ccugt
EX DE,HL
; HL = DE < HL (UNSIGNED)
ccult
CALL ccucmp
RET C
DEC L
RET
; Compare DE with HL, and return: (UNSIGNED)
;
; CARRY if DE < HL
; ZERO if DE == HL
; HL = 1
ccucmp
LD A,D
CP H
JR NZ,ccucmp1
LD A,E
CP L
ccucmp1
LD HL,1
RET
; HL = DE >> HL (UNSIGNED)
ccuasr
EX DE,HL
LD A,E
ccuasr1
OR A
RET Z
DEC A
SRL H
RR L
JR ccuasr1
; HL = DE >> HL (ARITMETIC)
ccasr
EX DE,HL
LD A,E
ccasr1
OR A
RET Z
DEC A
SRA H
RR L
JR ccasr1
; HL = DE << HL (UNSIGNED)
ccuasl
; HL = DE << HL (ARITMETIC)
ccasl
EX DE,HL
LD A,E
ccasl1
OR A
RET Z
DEC A
ADD HL,HL
JR ccasl1
; HL = DE - HL
ccsub
EX DE,HL
OR A
SBC HL,DE
RET
; HL = ~HL (1 COMPLEMENT)
cccom
LD A,H
CPL
LD H,A
LD A,L
CPL
LD L,A
RET
; HL = -HL (2 COMPLEMENT)
ccneg
LD A,H
CPL
LD H,A
LD A,L
CPL
LD L,A
INC HL
RET
#endasm
#ifndef CC_NO_MUL
#asm
; HL = DE * HL (UNSIGNED)
ccumul
; HL = DE * HL (SIGNED)
ccmul
LD A,H
LD C,L
LD HL,0
LD B,16
ccmul0
ADD HL,HL
SLA C
RL A
JR NC,ccmul1
ADD HL,DE
ccmul1
DJNZ ccmul0
RET
#endasm
#endif
#ifndef CC_NO_DIV
#asm
; HL = DE % HL (SIGNED)
ccmod
CALL ccdiv
EX DE,HL
RET
; HL = DE / HL (SIGNED)
; DE = DE % HL (SIGNED)
ccdiv
LD B,H
LD C,L
LD A,D
XOR B
PUSH AF
LD A,D
OR A
CALL M,ccdivdeneg
LD A,B
OR A
JP P,ccdiv0
LD A,B
CPL
LD B,A
LD A,C
CPL
LD C,A
INC BC
ccdiv0
EX DE,HL
LD DE,0
LD A,16
ccdiv1
PUSH AF
ADD HL,HL
RL E
RL D
LD A,D
OR E
JR Z,ccdiv2
LD A,E
SUB C
LD A,D
SBC B
JP M,ccdiv2
LD A,L
OR 1
LD L,A
LD A,E
SUB C
LD E,A
LD A,D
SBC B
LD D,A
ccdiv2
POP AF
DEC A
JR NZ,ccdiv1
POP AF
RET P
CALL ccneg
ccdivdeneg
LD A,D
CPL
LD D,A
LD A,E
CPL
LD E,A
INC DE
RET
; HL = DE % HL (UNSIGNED)
ccumod
CALL ccudiv
EX DE,HL
RET
; HL = DE / HL (UNSIGNED)
; DE = DE % HL (UNSIGNED)
ccudiv
LD (ccudiv_tmp),HL
LD HL,ccudiv_cnt
LD (HL),17
LD BC,0
PUSH BC
XOR A
ccudiv0
RL E
RL D
DEC (HL)
POP HL
JR Z,ccudiv2
LD A,0
ADC 0
ADD HL,HL
LD B,H
ADD L
LD HL,(ccudiv_tmp)
SUB L
LD C,A
LD A,B
SBC H
LD B,A
PUSH BC
JR NC,ccudiv1
ADD HL,BC
EX (SP),HL
ccudiv1
LD HL,ccudiv_cnt
CCF
JR ccudiv0
ccudiv2
EX DE,HL
RET
ccudiv_tmp
DEFW 0
ccudiv_cnt
DEFB 0
#endasm
#endif
#ifndef CC_NO_SWITCH
#asm
; Switch, on entry:
;
; DE = Table address
; HL = Where to go if value was not found in table
; B = Number of entries in table
ccswtch
EX (SP),HL
EX DE,HL
ccswch1
LD A,E
CP (HL)
INC HL
JR NZ,ccswch2
LD A,D
CP (HL)
JR NZ,ccswch2
INC HL
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL
POP BC
JP (HL)
ccswch2
INC HL
INC HL
INC HL
DJNZ ccswch1
EX (SP),HL
POP BC
JP (HL)
#endasm
#endif
#asm
; HL = TRUE
cctrue
LD L,1
RET
; HL = FALSE
ccfalse
LD HL,0
RET
#endasm


104
Blocks/mescc/sprintf.h Normal file
View File

@@ -0,0 +1,104 @@
/**
* @file sprintf.h
* @brief Library for sprintf() function.
* @author Miguel I. Garcia Lopez / FloppySoftware
*
* Implementation of sprintf() function, for MESCC (Mike's Enhanced
* Small C Compiler for Z80 & CP/M).
*
* Revisions:
* - 20 Oct 2000 : Last revision.
* - 16 Apr 2007 : GPL'd.
* - 14 Apr 2015 : Ammended a bad closed comment.
* - 25 Aug 2016 : Documented. GPL v3.
*
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
*
* Licensed under the GNU General Public License v3.
*
* http://www.floppysoftware.es
* floppysoftware@gmail.com
*/
#ifndef SPRINTF_H
#define SPRINTF_H
// Dependencies
// ------------
#ifndef XPRINTF_H
#include <xprintf.h>
#endif
/**
* @fn int sprintf(char *dst, char *fmt, arg1, arg2, ...)
* @brief Formatted output to memory.
*
* See the documentation for xprintf.h to learn about the string format.
*
* @param dst - destination
* @param fmt - string format
* @param arg1 - argument #1
* @param arg? - argument #?
* @return number or characters written, or -1 on failure (currently always #).
*/
#asm
sprintf:
ADD HL,HL
ADD HL,SP ;HL=Adr. fmt
LD DE,xspfout
PUSH DE
LD DE,xspfend
PUSH DE
PUSH HL
INC HL
INC HL ;HL=Adr. dst
LD A,(HL)
INC HL
LD H,(HL)
LD L,A
LD (xspfout+2),HL
CALL xprintf
POP BC
POP BC
POP BC
RET
#endasm
// int xspfout(char ch) : output ch to memory; return 0 on success, !=0 on failure (currently always returns 0).
#asm
xspfout:
LD A,L
LD HL,0 ;Adr.
LD (HL),A
INC HL
LD (xspfout+2),HL
LD HL,0
RET
#endasm
// void xspfend(void) : end formatted output; writes a trailing zero byte.
#asm
xspfend:
LD HL,(xspfout+2)
LD (HL),0
RET
#endasm
#endif


249
Blocks/mescc/string.h Normal file
View File

@@ -0,0 +1,249 @@
/**
* @file string.h
* @brief String functions.
* @author Miguel I. Garcia Lopez / FloppySoftware
*
* String functions, for MESCC (Mike's Enhanced
* Small C Compiler for Z80 & CP/M).
*
* Revisions:
* - 19 Mar 2001 : Last revision.
* - 16 Apr 2007 : GPL'd.
* - 15 Aug 2016 : Documented. GPL v3.
*
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
*
* Licensed under the GNU General Public License v3.
*
* http://www.floppysoftware.es
* floppysoftware@gmail.com
*/
#ifndef STRING_H
#define STRING_H
/**
* @fn int strlen(char *str)
* @brief Return string length.
* @param str - string
* @return length in characters
*/
#asm
strlen:
LD D,H
LD E,L
LD BC,0FFFFH
XOR A
CPIR
OR A
SBC HL,DE
DEC HL
RET
#endasm
/**
* @fn char *strcpy(char *dst, char *src)
* @brief Copy string.
* @param dst - destination string
* @param src - source string
* @return pointer to dst
*/
#asm
strcpy:
POP BC
POP HL
POP DE
PUSH DE
PUSH HL
PUSH BC
PUSH DE
strcpy2:
LD A,(HL)
LD (DE),A
INC HL
INC DE
OR A
JR NZ,strcpy2
POP HL
RET
#endasm
/**
* @fn char *strcat(char *dst, char *src)
* @brief Copy string at the end of another string.
* @param dst - destination string
* @param src - source string
* @return pointer to dst
*/
#asm
strcat:
POP BC
POP HL
POP DE
PUSH DE
PUSH HL
PUSH BC
PUSH DE
strcat2
LD A,(DE)
OR A
JR Z,strcpy2
INC DE
JR strcat2
#endasm
/**
* @fn int strcmp(char *str1, char *str2)
* @brief Compare two strings.
* @param str1 - a string
* @param str2 - a string
* @return <0 on str1 < str2; =0 on str1 == str2; >0 on str1 > str2
*/
#asm
strcmp
POP BC
POP HL
POP DE
PUSH DE
PUSH HL
PUSH BC
strcmp1
LD A,(DE)
CP (HL)
JR NZ,strcmp2
OR A
JR Z,strcmp2
INC DE
INC HL
JR strcmp1
strcmp2
LD HL,0
RET Z
JR NC,strcmp3
DEC HL
RET
strcmp3
INC L
RET
#endasm
/**
* @fn char *strchr(char *str, char ch)
* @brief Search a character in a string.
* @param str - the string where to search
* @param ch - the character to find
* @return pointer to ch in the string, or NULL on failure
*/
#asm
strchr
POP BC
POP DE
POP HL
PUSH HL
PUSH DE
PUSH BC
strchr2
LD A,(HL)
CP E
RET Z
INC HL
OR A
JR NZ,strchr2
LD H,A
LD L,A
RET
#endasm
/**
* @fn char *strupr(char *str)
* @brief Convert a string to upper case.
* @param str - a string
* @return pointer to str
*/
#asm
strupr
POP BC
POP HL
PUSH HL
PUSH BC
PUSH HL
strupr1
LD A,(HL)
OR A
JR Z,strupr3
CP 'a'
JR C,strupr2
CP 'z'+1
JR NC,strupr2
SUB 32
LD (HL),A
strupr2
INC HL
JR strupr1
strupr3
POP HL
RET
#endasm
/**
* @fn int atoi(char *s)
* @brief Convert string to a integer.
*
* This function parses a string, interpreting its content as
* a decimal integer number, until the end of the string, or
* a non decimal digit:
*
* [+|-][[0..9]...][ZERO|NON_DECIMAL_DIGIT]
*
* Examples:
* - "-256" == -256
* - "64" == 64
* - "1024 bytes" == 1024
* - "what?" == 0
*
* @param s - a string
* @return integer value
*/
atoi(s)
char *s;
{
int sign, val;
if(*s == '+')
{
++s; sign = 1;
}
else if(*s == '-')
{
++s; sign = -1;
}
else
sign = 1;
val=0;
while(*s >= '0' && *s <= '9')
val = val * 10 + (*s++ - '0');
return val * sign;
}
#endif


365
Blocks/mescc/xprintf.h Normal file
View File

@@ -0,0 +1,365 @@
/**
* @file xprintf.h
* @brief Support library for formatted output.
* @author Miguel I. Garcia Lopez / FloppySoftware
*
* Support library for formatted output,
* for MESCC (Mike's Enhanced Small C Compiler for Z80 & CP/M).
*
* All functions with formatted output like printf(), fprintf()
* and sprintf() call some private functions in this order:
* - pf_sf()
* - pf_s()
* - pf_out()
*
* Revisions:
* - 19 Mar 2001 : Last revision.
* - 16 Apr 2007 : GPL'd.
* - 09 Dec 2016 : Documented. Optimized. GPL v3.
* - 02 Aug 2017 : Output '%%' as '%'.
*
* Copyright (c) 1999-2016 Miguel I. Garcia Lopez / FloppySoftware.
*
* Licensed under the GNU General Public License v3.
*
* http://www.floppysoftware.es
* floppysoftware@gmail.com
*/
#ifndef XPRINTF_H
#define XPRINTF_H
// Dependencies
// ------------
#ifndef STRING_H
#include <string.h>
#endif
// Private globals
// ---------------
BYTE xpf_err; // True on error
extern WORD xpf_out; // Output function
extern WORD xpf_end; // End function
int xpf_fw; // Field width
BYTE xpf_fa; // Field alignment: 0=left, 1=right
BYTE xpf_fz; // True on zero filling
int xpf_cnt; // # of characters sent
/**
* @fn int xprintf(WORD funout, WORD funend, WORD adrpars)
* @brief Formatted output.
*
* This function performs formatted output. It is used
* by printf(), fprintf() and sprintf() functions.
*
* The format is indicated in the string as follows:
*
* %[-][0][w]t
*
* | - : Left align (default: right align).
* | 0 : Zero filling on right align.
* | w : Width for alignment. If the specified width
* | is lower than the argument length, output is
* | done without aligment. Care with sprinf()!
* | t : d = Signed decimal integer.
* | u = Unsigned decimal integer.
* | x = Hexadecimal integer.
* | s = String.
* | c = Character.
*
* The pair %% outputs a single %.
*
* @param funout - function to output a character
* @param funend - function to end output
* @param adrpars - arguments addresses
* @return # of characters sent on sucess, -1 on failure
*/
xprintf(funout, funend, adrpars)
WORD funout, funend;
WORD *adrpars;
{
WORD *parg; // Pointer to arguments
char *pfor; // Pointer to formatted string
int ivalue;
char ch;
// Setup
xpf_out = funout;
xpf_end = funend;
pfor = *adrpars;
parg = --adrpars;
xpf_err = xpf_cnt = 0;
// Loop
while((ch = *pfor++))
{
if(ch == '%')
{
// Character %
if(*pfor == '%')
{
pf_out(ch);
++pfor;
continue;
}
// Align
if(*pfor == '-')
{
xpf_fa = 0; // Left align
++pfor;
}
else
xpf_fa = 1; // Right align
// Zero filling
if(*pfor == '0')
{
xpf_fz = 1; // Zero filling
++pfor;
}
else
xpf_fz = 0;
// Width
xpf_fw = 0;
while(*pfor >= '0' && *pfor <= '9')
xpf_fw = xpf_fw * 10 + (*pfor++) - '0';
// Type
switch(ch = *pfor++)
{
case 'd' :
ivalue = *parg--;
pf_dec(ivalue);
break;
case 'u' :
ivalue = *parg--;
pf_udec(ivalue);
break;
case 'x' :
ivalue = *parg--;
pf_hex(ivalue);
break;
case 'c' :
pf_cf(*parg--);
break;
case 's' :
pf_sf(*parg--);
break;
case '\0' :
--pfor;
// P'abajo
default :
pf_out('!');
break;
}
}
else
pf_out(ch);
if(xpf_err)
break;
}
pf_end();
return xpf_err ? -1 : xpf_cnt;
}
// void pf_sf(char *s) : output formatted string.
pf_sf(s)
char *s;
{
int len;
char fill;
if(xpf_fw)
{
if((len = strlen(s)) < xpf_fw)
{
xpf_fw = xpf_fw-len;
if(xpf_fa)
{
// Left align
fill = (xpf_fz ? '0' : ' ');
while(xpf_fw--)
pf_out(fill);
pf_s(s);
}
else
{
// Right align
pf_s(s);
while(xpf_fw--)
pf_out(' ');
}
return;
}
}
pf_s(s);
}
// void pf_cf(char c) : output formatted character.
pf_cf(c)
char c;
{
char tmp[2];
tmp[0] = c; tmp[1] = '\0';
pf_sf(tmp);
}
unsigned char xpf_dst[7]; // Buffer for numbers
unsigned char *xpf_dpt; // Buffer pointer
// void pf_dec(int i) : output signed decimal integer.
pf_dec(i)
int i;
{
xpf_dpt = xpf_dst;
if(i < 0)
{
*xpf_dpt++ = '-'; i = -i;
}
pf_dec2(i);
*xpf_dpt = '\0';
pf_sf(xpf_dst);
}
// void pf_dec2(int i) : helper for pf_dec().
pf_dec2(i)
int i;
{
int n;
if(n = i / 10)
pf_dec2(n);
*xpf_dpt++ = i % 10 + '0';
}
// void pf_udec(unsigned int i) : output unsigned decimal integer.
pf_udec(i)
unsigned i;
{
xpf_dpt = xpf_dst;
pf_udec2(i);
*xpf_dpt = '\0';
pf_sf(xpf_dst);
}
// void pf_udec2(unsigned int i) : helper for pf_udec().
pf_udec2(i)
unsigned i;
{
unsigned n;
if(n = i / 10)
pf_udec2(n);
*xpf_dpt++ = i % 10 + '0';
}
// void pf_hex(unsigned int i) : output hexadecimal integer.
pf_hex(i)
unsigned i;
{
xpf_dpt = xpf_dst;
pf_hex2(i);
*xpf_dpt = '\0';
pf_sf(xpf_dst);
}
// void pf_hex2(unsigned int i) : helper for pf_hex().
pf_hex2(i)
unsigned i;
{
unsigned n;
if(n = i / 16)
pf_hex2(n);
i %= 16;
*xpf_dpt++ = i < 10 ? '0' + i : 'A' + i - 10;
}
// void pf_s(char *s) : output string.
pf_s(s)
char *s;
{
while(*s)
pf_out(*s++);
}
// void pf_out(char c) : output character.
#asm
pf_out:
PUSH HL
DEFB 0CDH
xpf_out:
DEFW 0
POP BC
EX DE,HL
LD HL,(xpf_cnt)
INC HL
LD (xpf_cnt),HL
LD A,D
OR E
RET Z
;; LD A,255
LD (xpf_err),A
RET
#endasm
// void pf_end(void) : end output.
#asm
pf_end:
DEFB 0C3H
xpf_end:
DEFW 0
#endasm
#endif