]     ] ]]]]]]]  ]]]]]   ]]]]]   ]]]]]
]]   ]] ]       ]     ] ]     ] ]     ]
] ] ] ] ]       ]       ]       ]
]  ]  ] ]]]]]    ]]]]]  ]       ]
]     ] ]             ] ]       ]
]     ] ]       ]     ] ]     ] ]     ]
]     ] ]]]]]]]  ]]]]]   ]]]]]   ]]]]]

MESCC v1.23 - 13 Jan 2021

Mike's Enhanced Small C Compiler for Z80 and CP/M

Copyright (c) 1999-2021 Miguel I. Garcia Lopez / FloppySoftware, Spain

www.floppysoftware.es
cpm-connections.blogspot.com
floppysoftware@gmail.com

This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

See the copying file for more details.

Last update: 13 Jan 2021.


OVERVIEW
========

MESCC is a subset of the standard C language.

It was based on the version 1.7 (Oct. 1985) of Small C by Ron Cain, Mike Bernson's
and John Hill, but now only a little (if any) of the original source code is present.

This compiler can be compiled by itself.

This is not a C language manual, only a brief description of MESCC.

The present document assume that you have some knowledge about C programming language.


OPTIONS
=======

Usage: cc [name[.typ] [options]]

If no options are entered, a help summary will be displayed on screen.

Options:

-PRG          Out normal file ---- Type=ZSM
-LIB          Out library file --- Type=LIB
-ASM          Out assembler file - Type=ZSM
-O:name[.typ] File name for output
-Cflag        C source as comments?
-Eflag        Pause on errors?
-E:number     Max. number of errors to abort
-L:letnum     Letter and start number for labels
-S:size       Minimum stack size

Default options are: (flag is + for YES, - for NO)

        -PRG -C- -E+ -E:50 -L:A0 -S:512
        Input file type is .c
        Output file name is the same as input

NOTE: All programs must include the runtime file mescc.h first.

Examples:	cc hello
		cc myprog.c -s:2048 -lz1000

Then, if you want to generate a COM file, the compiler output (Z80 assembler)
must be assembled with ZSM.COM to generate a HEX file.

The HEX file output must be converted to a COM file with HEXTOCOM.COM
or HEXTOBIN.COM (or, if you prefer, with LOAD.COM or HEXCOM.COM, both supplied
with CP/M).

Example:	cc hello.c
		zsm hello.ccz
		hextocom hello.zsm hello.com

See ZSM.DOC for details about the assembler.

In theory, you can use any Z80 assembler (and linker) if the assembler output of the
compiler is compatible.

Note that some MESCC libraries can change their behaviour, by #defining some
macros like CC_NO_ARGS, CC_STDIO, etc., as described below.

There is a new optimizer that analizes the assembler output of the compiler: ccopt.

Usage: ccopt file [-r]

Options:

-r	Generate new rules for the optimizer. After this command,
	you must re-compile ccopt.

Examples:	ccopt myprog
		ccopt ccopt -r


SUPPORTED TYPES
===============

char		1 byte.
		Can be signed (-128 to 127) or unsigned (0 to 255).
		By default is signed.

int		2 bytes.
		Can be signed (-32768 to 32767) or unsigned (0 to 65535).
		By default is signed.

Pointers	2 bytes.

Arrays		Size of type * number of items.
		Arrays of pointers are not supported.

Examples:

char ch, *ptr;		A char and a pointer to char.
unsigned char c;	An unsigned char.
int i, *ptr_i;		An int and a pointer to int.
unsigned int ui;	An unsigned int.
signed int i;		A signed int.
char str[10];		An array of 10 char, 10 bytes.
unsigned int ui[5];	An array of 5 int, 10 bytes.

You can declare and assign one or more global variables in the same sentence:

Characters:

	char space = 32, tab = '\t';
	char lf = '\n';
	unsigned char cpm_eof = 0x1A, cpm_eos = '$';

Integers:

	int number = -32;
	unsigned int common = 0xC000;

Pointers:

	char *text = "a text";
	unsigned char *bytes = "a string";
	unsigned int *bdos_entry = 0x0005;

Arrays:

	char abc[3] = {'a', 'b', 'c'};
	char blanks[] = {32, '\t', 13, 10};
	char text[] = "a text";
	unsigned char bytes = "a string";
	int values[] = {12, -45, 68};
	int prices[2] = {2400, 1250};

As the compiler doesn't support arrays of pointers, the arguments of the
function main can be as follows:

main(argc, argv)
int argc, argv[];
{
	char *ptr;

	ptr=argv[1]; /* This is the first parameter */

	...
}

You can manage 'arrays of pointers' in a similar manner:

unsigned array[3];

array[0]="First";
array[1]="Second";
array[2]="Third";

int i;

for(i=0; i<3; ++i)
	puts(array[i]);


CONSTANTS
=========

Decimal integer		Examples: 32, -1, 456.
Hexadecimal integer	Examples: 0x12, 0xF3, 0xAA34
Character		Examples: 'A', '12', '\t', '\0', '\x1A'


STRINGS
=======

Examples:	"This is a text"
		"Text with a newline\n"


NAMES
=====

Variables and function names should consist of not more than
11 alpha-numeric characters.
The '_' character is considered an alphabetic character,
and the first character can't be numeric.


ESCAPE SEQUENCES
================

Can be included in character constants or strings:

\n	Newline, 10 decimal.
\t	Tab, 9 decimal.
\r	Carriage line, 13 decimal.
\b	Backspace, 8 decimal.
\a	Alarm, 7 decimal.
\f	Formfeed, 12 decimal.
\e	Escape, 27 decimal.
\xNN	Hexadecimal.
\NNN	Octal.

The characters ', " and \ can be included in character constants or strings as:

\'	'
\"	"
\\	\

Escape sequences in hexadecimal notation can be 1 or 2 digits, case insensitive:

		'\xF'
		'\x1a'

Escape sequences in octal notation can be 1, 2 or 3 digits:

		'\0'
		'\12'
		'\123'

Examples:	'\0'
		'\n'
		'\''
		"\aError: Can't open"
		"Filename: \"%s\".\n"
		"\xA<-Form feed!"
		"\12<-Form feed!"


COMMENTS
========

Comments can be written as follows:

	/* Comment in old style */
	// Comment in new style


SUPPORTED STATEMENTS
====================

for(init, cond, incr) statement;     -- init, cond and incr are optional, see forever loops below
while(cond) statement;
do statement; while(cond);
switch(cond) case statements;
if(cond) statement; else statement;
continue;
break;
return;
return expr;

A statement can be only one statement or two or more
statements enclosed in brackets.

Examples:

for(i=0; i<10; ++i)
	printf("Line number %d.\n", i);

while(i!=100)
{
	if(read()==0)
		continue;
	i=useroption();
}

do
{
	read();
	i=useroption();
} while(i!=100);

swith(i)
{
	case 10 : option10(); break;
	case 11 : option11(); break;
	default : optionerr(); break;
}

if(i)
	nonzero();
else
	zero();

return 32;

The statement for, accepts forever loop types - ie:

for(;;) {
	if(getch() == EOF)
		break;
	/* etc */
}


SIZEOF
======

You can use it only as follows:

sizeof(char)
sizeof(char *)
sizeof(int)
sizeof(int *)


OPERATORS AND PRECEDENCE
========================

! ~ ++ -- - * &   right to left
* / %             left to right
+ -               left to right
<< >>             left to right
< <= > >=         left to right
== !=             left to rigth
&                 left to rigth
^                 left to right
|                 left to right
&&                left to right
||                left to right
?:                right to left
=  -= += *= %=    right to left
   /= &= ^= |=


PREPROCESSOR
============

Preprocessor commands can be indented.

#define name string

	Examples: #define BYTE unsigned char
		  #define TITLE "My program"

#undef name

	Examples: #undef BYTE

#include filename

	Examples: #define "stdio.lib"
		  #define <2nd_mod.c>

#if value
#ifdef name
#ifndef name
#else
#endif

	Examples: #ifndef WORD
		  #define unsigned int
		  #endif

		  #if PCW
			machine = "Amstrad PCW";
		  #endif

#asm
#endasm

	Example: #asm
		 quit:
			JP 0
		 #endasm

Predefined macros:

__FILE__  Name of the file currently in process.
__LINE__  Line number currently in process.


ABOUT THE SOURCE CODE OF MESCC
==============================

The source code of MESCC is written in MESCC code. That's is: A subset of C language
in Kernighan & Ritchie style, not ANSI.

Then, it can be compiled by itself.

To compile by itself, you must compile the file make_cc.c with MESCC.

See make_cc.c for more details.

The source code uses some extern library functions as fopen, fgetchar, etc.,
that are available as part of standard library of MESCC.

See main.h for more information.


LINKING MESCC OUTPUT TO MACHINE CODE
====================================

If a function is called: fn(arg1, arg2, arg3), the compiler pushes the
values of arg1, arg2  and arg3 on the stack in the order that they are listed
and then generates a call to a label "fn".

Values should be returned in HL, and 8 bit signed values should be sign
extended to 16 bits, and the simplest way to do this is to put the value
into A and call the routine 'ccsxt' in the library mescc.h which will do
this for you.

The stack must be restored to its previous state before returning.

The last argument will still be in HL when a function is entered,
so if a function has only one argument there is no need to get it off
the stack.

The functions printf, fprintf, sprintf, scanf, fscanf and sscanf, have
an additional value pushed on the stack, to tell the function how many
parameteres are.

Machine code functions can be put between #asm and #endasm directives.


LIBRARIES
=========

mescc.h		Runtime. All programs must include this file first.
alloc.h		Memory allocation functions.
atexit.h	Code for atexit() function.
bsearch.h	Binary search function.
clock.h		Date & time functions for CP/M Plus.
conio.h		Console I/O functions.
cpm.h		CP/M specific functions.
ctype.h		Test and character conversion functions.
fileio.h	Stream file I/O functions.
fprintf.h	Formatted output to file.
mem.h		Memory functions.
printf.h	Formatted output to console.
qsort.h		Sort function.
rand.h		Pseudo-random number generation.
setjmp.h	Non-local jumps.
sprintf.h	Formatted output to memory.
stdbool.h	Boolean type and values.
string.h	String functions.
xprintf.h	Support library for printf, fprintf and sprintf.
z80.h		Z80 specific functions.

The ANSI style of C functions declaration is not supported, and the type of
parameters are indicated only for information.

Also, the type 'void' is not supported, only is specified for information.

[S] means that function is C standard (or near).


alloc.h
-------

Dinamic memory management functions.

void *malloc(unsigned int size) [S]

	Allocate 'size' bytes of memory. Return pointer to memory,
	or 0 if not enough memory.

void free(void *ptr) [S]

	Free memory pointed by 'ptr'. If 'ptr' is NULL, nothing happens.


atexit.h
--------

Code for atexit() function.

int atexit(void (*func)(void)) [S]

	Adds a function to be called when the program terminates normally,
	with exit() or a return in main() function. Returns 0 on success.


bsearch.h
---------

Binary search function.

void *bsearch(void *key, void *base, int items, int size, int (*comp)(void *, void *)) [S]

	Binary search. Returns item found, else NULL.


clock.h
-------

Date & time functions for CP/M Plus.

unsigned char *getclock(unsigned char *clk)

	Get CP/M clock.

void setclock(unsigned char *clk)

	Set CP/M clock.

int *getdate(unsigned char *clk, int *dt)

	Get date from clock (convert clock to date).

unsigned char *setdate(unsigned char *clk, int *dt)

	Set clock from date (convert date to clock).


conio.h
-------

Console I/O functions.

All functions send a LF as CR/LF, except getch() and putch().

#define CC_STDIO      to support stdin, stdout & stderr (needs fileio.h).
#define CC_CONIO_BIOS to support direct console I/O using BIOS, instead of BDOS.

If CC_STDIO is not defined, stdin & stdout are always the console.

int putch(int ch)

	Send character to the console.

int getch(void)

	Get character from the console without echo.

int kbhit(void)

	Return NON ZERO if a character is available from the console,
	else 0.

int getchar(void) [S]

	Get character from stdin with echo to stdout.

int putchar(int ch) [S]

	Send character to stdout.

int putstr(char *s) [S]

	Send string to stdout.

int puts(char *str) [S]

	Send string and a new line to stdout.


cpm.h
-----

CP/M functions.

Read the CP/M manual for more information about input/output parameters.

#define CC_FCX to support FCX (user number in file names).
#define CC_FCX_DIR to support directory names -- you must supply DirToDrvUsr().

int bdos_hl(unsigned int bc, unsigned int de)

	Call to BDOS. Returns HL.

unsigned char bdos_a(unsigned int bc, unsigned int de)

	Call to BDOS. Returns A.

unsigned char bdos_fcx_a(int fun, char *fcx)

	Call to BDOS with a FCX. Returns A.

int setfcx(char *fname, char *fcx)

	Set FCX. Returns 0 on success.

int setfcb(char *fname, char *fcb)

	Set FCB. Returns 0 on success.


ctype.h
-------

Test and conversion character functions.

int isalpha(char ch) [S]

	Test for alphabetic. Return nonzero if yes, zero if not.

int isdigit(char ch) [S]

	Test for decimal digit. Return nonzero if yes, zero if not.

int isxdigit(char ch) [S]

	Test for hexadecimal digit. Return nonzero if yes, zero if not.

int isalnum(char ch) [S]

	Test for alpabetic or decimal digit. Return nonzero if yes, zero if not.

int isupper(char ch) [S]

	Test for upper case character. Return nonzero if yes, zero if not.

int islower(char ch) [S]

	Test for lower case character. Return nonzero if yes, zero if not.

int toupper(char ch) [S]

	Convert 'ch' to upper case character.

int tolower(char ch) [S]

	Convert 'ch' to lower case character.


fileio.h
--------

Stream file I/O functions.

All functions converts a CR/LF to a LF on input, and a LF to CR/LF on output,
only in text mode.

On binary mode, no conversion is done.


#define CC_STDIO     to support stdin, stdout & stderr.
#define CC_FCX       to support FCX (user number in file names, see cpm.h).
#define CC_FCX_DIR   to support named directories in file names (see cpm.h).
#define CC_FOPEN_A   to include "a" and "ab" modes for fopen().
#define CC_FREAD     to include fread().
#define CC_FWRITE    to include fwrite().
#define CC_FGETS     to include fgets().
#define CC_FPUTS     to include fputs().
#define CC_FSIZE     to include fsize().

FILE *fopen(char *fname, char *fmode) [S]

	Open file.
	Mode can be: 'r' for read in text mode, 'rb' for binary mode.
	             'w' for write in text mode, 'wb' for binary mode.
	             'a' for append in text mode, 'ab' for binary mode.
	Return a FILE pointer, or NULL if can't be opened.

int fclose(FILE *fp) [S]

	Close file. Return NULL, or EOF if can't be closed.

int fgetc(FILE *fp) [S]

	Read a character. Return character value, of EOF if end of file or errors.

int fputc(int ch, FILE *fp) [S]

	Write a character. Return character value, or EOF if errors.

int feof(FILE *fp) [S]

	Test for end of file. Return nonzero if true, zero if false.

int ferror(FILE *fp) [S]

	Test for error. Return nonzero if true, zero if false.

int fread(char *ptr, int size, int nobj, FILE *fp) [S]

	Read 'nobj' objects of 'size' bytes each. Return number of objects read.

int fwrite(char *ptr, int size, int nobj, FILE *fp) [S]

	Write 'nobj' objects of 'size' bytes each. Return number of objects writed.

char *fgets(char *str, int size, FILE *fp) [S]

	Read a string. Returns 'str' on success, else NULL.

int remove(char *fname) [S]

	Delete file. Return nonzero on errors.

int rename(char *oldname, char *newname) [S]

	Rename file. Return nonzero on errors.

int fputs(char *str, FILE *fp) [S]

	Write a string. Return a non-negative number on success (the
	number of characters written), else EOF.
	
int fsize(char *fname)

	Get the file size in units of 128 bytes. Return -1 on errors.


fprintf.h
---------

Formatted output to stream file.

int fprintf(FILE *fp, char *fmt, arg1, arg2, ...) [S]

	Return number of characters written, or -1 on errors.

	See printf.h for more information.


mem.h
-----

Memory functions.

char *memset(char *dst, char data, int count) [S]

	Set 'count' bytes in 'dst' memory pointer to 'data'.

char *memcpy(char *dst, char *src, int count) [S]

	Copy 'count' bytes, from 'src' to 'dst' memory pointers.

int memcmp(char *mem1, char *mem2, int count) [S]

	Compare 'count' bytes in 'mem1' and 'mem2' memory pointers.

	Return < 1 if *mem1 is lower than *mem2, 0 if equal, or
	> 1 ir *mem1 is upper than *mem2.


mescc.h
-------

Runtime library.

#define CC_STDIO     To support stdin, stdout & stderr.
#define CC_REDIR     To support stdin & stdout redirection
	             in the CP/M 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.

void exit(int code)

	Return to CP/M.


printf.h
--------

Formatted output to console.

int printf(char *fmt, arg1, arg2, ...) [S]

	% character in format, acts as follows (<> means, optional):

	%<-><0><width>type

	-	Left alignment, else right alignment.
	0	Fill with zeroes in right alignment.
	width	Width for alignment. If width if less than width of
		argument, output is done without alignment.
 	type	d	Signed decimal integer.
		u	Unsigned decimal integer.
		x	Hexadecimal integer.
		s	String.
		c	Character.

	The pair %% outputs a single %.

qsort.h
-------

Sort function.

void qsort(void *base, int items, int size, int (*comp)(void *, void*)) [S]

	Sorts an array of data.


rand.h
------

Pseudo-random number generation.

int rand(void) [S]

	Returns a pseudo-random value between 0 and RAND_MAX (both included).

void srand(unsigned seed) [S]

	Seeds the pseudo-random number generatod user by rand().


redir.h
-------

Command line redirection.

int redir(int argc, char *argv[])

	Stdin & stdout redirection in the CP/M command line.
	Returns number of args after parsing redirection.


setjmp.h
--------

Non-local jumps.

int setjmp (jmp_buf env) [S]

	Save environment state information, for later use of longjmp().
	Returns ZERO from direc call, NON-ZERO from a longjmp() call.

void longjmp (jmp_buf env, int rv) [S]

	Restore environment state information, as stored in env.
	Execution resumes after setjmp(), and returns the value of rv, that must be NON-ZERO.


sprintf.h
---------

Formatted output to memory.

int sprintf(char *dst, char *fmt, arg1, arg2, ...) [S]

	See printf.h for more information.

stdbool.h
---------

Boolean type and values.

#define bool  int
#define true  1      [S]
#define false 0      [S]


string.h
--------

String functions. All strings must be zero terminated.

int strlen(char *str) [S]

	Return length of string.

char *strcpy(char *dst, char *src) [S]

	Copy string 'src' into 'dst'.

char *strcat(char *dst, char *src) [S]

	Copy string 'src' at the end of 'dst'.

char *strupr(char *str)

	Converts string into upper case characters.

int strcmp(char *str1, char *str2) [S]

	Compare two strings.
	Return <1 if *str1 is lower than *str2, 0 if equal, or
	>1 ir *str1 is upper than *str2.

char *strchr(char *str, char ch) [S]

	Search 'ch' in 'str'. Returns a pointer, or 0 if not encountered.

int atoi(char *s) [S]

	Converts a string containing a decimal number to a integer value.
	Supported + and - signs.


xprintf.h
---------

Support library for printf, fprintf and sprintf functions.

int xprintf(void *funout, void *funend, void *adrpars)

	Support for printf, fprintf and sprintf functions.


z80.h
-----

Z80 specific functions.

unsigned int Z80in(int port)

	Byte input from port.

void Z80out(int port, int value)

	Byte output to port.

void Z80di(void)

	Disable interruptions.

void Z80ei(void)

	Enable interruptions.


EXAMPLES
========

Some examples for MESCC are included:

banner.c : Print text in big characters. Supports redirection.
cal.c    : Print calendar months. Supports redirection.
dump.c   : Print contents of a file in byte and ascii format.
head.c   : Print the first lines of a file. Supports redirection.
hello.c  : The classic 'Hello world!' C program.

