HI-TECH C USER'S MANUAL i CONTENTS 1. Introduction 1 1.1. Features 1 1.2. System Requirements 2 1.3. Using this Manual 2 2. Getting Started 3 3. Compiler Structure 5 4. Operating Details 7 5. Specific Features 13 5.1. ANSI C Standard Compatibility 13 5.2. Type Checking 13 5.3. Member Names 13 5.4. Unsigned Types 14 5.5. Arithmetic Operations 14 5.6. Structure Operations 15 5.7. Enumerated Types 16 5.8. Initialization Syntax 16 5.9. Function Prototypes 17 5.10. Void and Pointer to Void 18 5.11. Type qualifiers 19 5.12. 20 5.13. Pragma Directives 20 6. Machine Dependencies 21 6.1. Predefined Macros 21 7. Error Checking and Reporting 23 8. Standard Libraries 25 8.1. Standard I/O 25 8.2. Compatibility 25 8.3. Libraries for Embedded Systems 25 8.4. Binary I/O 26 8.5. Floating Point Library 27 9. Stylistic Considerations 29 9.1. Member Names 29 9.2. Use of Int 30 9.3. Extern Declarations 30 10. Memory Models 31 11. What Went Wrong 33 12. Z80 Assembler Reference Manual 35 12.1. Introduction 35 12.2. Usage 35 12.3. The Assembly Language 36 12.3.1. Symbols 36 12.3.1.1. Temporary Labels 37 12.3.2. Constants 37 12.3.2.1. Character Constants 38 ii HI-TECH C USER'S MANUAL 12.3.2.2. Floating Constants 38 12.3.2.3. Opcode Constants 38 12.3.3. Expressions 38 12.3.3.1. Operators 38 12.3.3.2. Relocatability 39 12.3.4. Pseudo-ops 40 12.3.4.1. DEFB, DB 40 12.3.4.2. DEFF 41 12.3.4.3. DEFW 41 12.3.4.4. DEFS 41 12.3.4.5. EQU 41 12.3.4.6. DEFL 41 12.3.4.7. DEFM 42 12.3.4.8. END 42 12.3.4.9. COND, IF, ELSE, ENDC 42 12.3.4.10. ELSE 42 12.3.4.11. ENDC 42 12.3.4.12. ENDM 43 12.3.4.13. PSECT 43 12.3.4.14. GLOBAL 43 12.3.4.15. ORG 44 12.3.4.16. MACRO 44 12.3.4.17. LOCAL 45 12.3.4.18. REPT 46 12.3.5. IRP and IRPC 47 12.3.6. Extended Condition Codes 48 12.4. Assembler Directives 48 12.5. Diagnostics 49 12.6. Z80/Z180/64180 Instruction Set 50 13. Linker Reference Manual 69 13.1. Relocation and Psects 69 13.1.1. Program Sections 69 13.1.2. Local Psects and the Large Model 70 13.2. Global Symbols 70 13.3. Operation 71 13.4. Examples 74 13.5. Invoking the Linker 74 14. Librarian 75 14.1. The Library Format 75 14.2. Using 75 14.3. Examples 76 14.4. Supplying Arguments 77 14.5. Listing Format 77 14.6. Ordering of Libraries 77 14.7. Error Messages 78 15. Objtohex 79 16. Cref 83 APPENDIX 1 Error Messages 85 APPENDIX 2 Standard Library Functions 99 INDEX 165 HI-TECH C COMPILER User's Manual March 1989 1. Introduction The HI-TECH C Compiler is a set of software which translates programs written in the C language to executable machine code programs. Versions are available which compile programs for operation under the host operating system, or which produce programs for execution in embedded systems without an operating system. 1.1. Features Some of HI-TECH C's features are: A single command will compile, assemble and link entire programs. The compiler performs strong type checking and issues warnings about various constructs which may represent programming errors. The generated code is extremely small and fast in exe- cution. A full run-time library is provided implementing all standard C input/output and other functions. The source code for all run-time routines is provided. A powerful general purpose macro assembler is included. Programs may be generated to execute under the host operating system, or customized for installation in ROM. PC-DOS/MS-DOS CP/M-86 Concurrent DOS Atari ST Xenix Unix CP/M-80 Table 1. Supported Hosts Page 2 HI-TECH C USER'S MANUAL 1.2. System Requirements The HI-TECH C Compilers operate under the operating sytems listed in table 1. Ensure that the version of the compiler you have matches the system you have. Note that in general you must have a hard disk or two floppy disks on your system (it is possible to use one floppy disk of 800K or more). A hard disk is strongly recommended. Note that the CP/M-80 native compiler does not have all the features described in this manual, as it has not been upgraded past V3.09 due to memory limitations. The Z80 cross compiler does support all of the features described here and can be used to generate programs to execute under CP/M-80. 1.3. Using this Manual The documentation supplied with the HI-TECH C compiler comprises two separate manuals within the one binder. The manual you are reading now covers all versions of the com- piler (reflecting the portable nature of the compiler). A separate manual covers machine dependent aspects of your compiler, e.g. installation. This manual assumes you are familiar with the C language already. If you are not, you should have at least one reference book covering C, of which a large number are available from most computer bookstores, e.g. "A Book on C" by Kelley and Pohl. Other suitable texts are "Programming in ANSI C" by S. Kochan and "The C Programming Language", by Kernighan and Ritchie. You should read the "Getting Started" chapter in this manual, and the "Installation" chapter in the machine-specific manual. This will provide you with sufficient information to work through the introductory examples in the C reference you are using. Once you have a basic grasp of the C language, the remainder of this manual will provide you with information to enable you to explore the more advanced aspects of C. Most of the manual covers all implementations of the HI-TECH C compiler. A separate manual is provided for the macro assembler for your particular machine, and other machine-dependent information. HI-TECH C USER'S MANUAL Page 3 2. Getting Started If using the compiler on a hard disk system you will need to install the compiler before using it. See the "Installation" chapter for more details. If using a floppy disk based system, in general you should have a copy of the distribution disk #1 in drive A: and maintain your files on a disk in the B: drive. Again see the "Installation" chapter for more information. main() { printf("Hello, world\n"); } Fig. 1. Sample C Program Before compiling your program it must be contained in a file with an extension (or file type, i.e. that part of the name after the '.') of .C. For example you may type the program shown in fig. 1 into a file called HELLO.C. You will need a text editor to do this. Generally any text editor that can create a straight ASCII file (i.e. not a "word pro- cessor" type file) will be suitable. If using editors such as Wordstar, you should use the "non-document mode". Once you have the program in such a file all that is required to compile it is to issue the C command, e.g. to compile HELLO.C simply type the command C -V HELLO.C Cross compilers (i.e. compilers that operate on one system but produce code for a separate target system) will have a compiler driver named slightly differently, e.g. the 68HC11 cross compiler driver is called C68. If you are using a floppy disk based system (or a CP/M system) it may be necessary to specify where to find the C command, e.g. if the C command is on a disk in drive A: and you are working on B:, type the command A:C -V HELLO.C The compiler will issue a sign on message, then proceed to execute the various passes of the compiler in sequence to compile the program. If you are using a floppy disk based system where the compiler will not fit on a single disk you will be prompted to change disks whenever the compiler can- not find a pass. In this case you should insert a copy of the next distribution disk in drive A: and press RETURN. As each pass of the compiler is about to be executed, a command line to that pass will be displayed on the screen. Page 4 HI-TECH C USER'S MANUAL This is because the -V option has been used. This stands for Verbose, and had it not been given the compilation would have been silent except for the sign on message. Error mes- sages can be redirected to a file by using the standard out- put redirection notation, e.g. > _s_o_m_e_f_i_l_e. After completion of compilation, the compiler will exit to command level. You will notice that several temporary files created during compilation will have been deleted, and all that will be left on the disk (apart from the original source file HELLO.C) will be an executable file. The name of this executable file will be HELLO.EXE for MS-DOS, HELLO.PRG for the Atari ST, HELLO.COM for CP/M-80 and HELLO.CMD for CP/M-86. For cross compilers it will be called HELLO.HEX or HELLO.BIN depending on the default output format for the particular compiler. To execute this program, simply type HELLO and you should be rewarded with the message "Hello, world!" on your screen. If you are using a cross compiler you will need to put the program into EPROM or download to the target system to execute it. Cross compilers do not produce pro- grams executable on the host system. There are other options that may be used with the C command, but you will not need to use them unless you wish to do so. If you are new to the C language it will be advis- able to enter and compile a few simple programs (e.g. drawn from one of the C reference texts mentioned above) before exploring other capabilities of the HI-TECH C compiler. There is one exception to the above; if you compile a program which uses floating point arithmetic (i.e. real numbers) you MUST specify to the compiler that the floating point library should be searched. This is done with a -LF option at the END of the command line, e.g. C -V FLOAT.C -LF HI-TECH C USER'S MANUAL Page 5 3. Compiler Structure The compiler is made up of several passes; each pass is implemented as a separate program. Note that it is not necessary for the user to invoke each pass individually, as the C command runs each pass automatically. Note that the machine dependent passes are named differently for each pro- cessor, for example those with 86 in their name are for the 8086 and those with 68K in their name are for the 68000. The passes are: CPP The pre-processor - handles macros and conditional com- pilation P1 The syntax and semantic analysis pass. This writes intermediate code for the code generator to read. CGEN, CG86 etc. The code generator - produces assembler code. OPTIM, OPT86 etc. The code improver - may optionally be omitted, reducing compilation time at a cost of larger, slower code pro- duced. ZAS, AS86 etc. The assembler - in fact a general purpose macro assem- bler. LINK The link editor - links object files with libraries. OBJTOHEX This utility converts the output of LINK into the appropriate executable file format (e.g. .EXE or .PRG or .HEX). The passes are invoked in the order given. Each pass reads a file and writes a file for its successor to read. Each intermediate file has a particular format; CPP produces C code without the macro definitions and with uses of macros expanded; P1 writes a file containing a program in an inter- mediate code; CGEN translates this to assembly code; AS pro- duces object code, a binary format containing code bytes along with relocation and symbol information. LINK accepts object files and libraries of object files and writes another object file; this may be in absolute form or it may preserve relocation information and be input to another LINK command. There are also other utility programs: LIBR Creates and maintains libraries of object modules Page 6 HI-TECH C USER'S MANUAL CREF Produces cross-reference listings of C or assembler programs. HI-TECH C USER'S MANUAL Page 7 4. Operating Details HI-TECH C was designed for ease of use; a single com- mand will compile, assemble and link a C program. The syntax of the C command is as follows: C [ options ] files [ libraries ] The options are zero or more options, each consisting of a dash ('-'), a single key letter, and possibly an argu- ment following the key letter with no intervening space. The files are one or more C source files, assembler source files, or object files. Libraries may be zero or more library names, or the abbreviated form -lname which will be expanded to the library name libname.lib. The C command will, as determined by the specified options, compile any C source files given, assemble them into object code unless requested otherwise, assemble any assembler source files specified, then link the results of the assemblies with any object or library files specified. If the C command is invoked without arguments, then it will prompt for a command line to be entered. This command line may be extended by typing a backslash ('\') on the end of the line. Another line will then be requested. If the standard input of the command is from a file (e.g. by typing C < afile) then the command lines will be read from that file. Within the file more than one line may be given if each line but the last ends with a backslash. Note that this mechanism does not work in MS-DOS batch file, i.e. the com- mand file for the C command must be a separate file. MS-DOS has no mechanism for providing long command lines or stan- dard input from inside a batch file. The options recognized by the C command are as follows: -S Leave the results of compilation of any C files as assembler output. C source code will be interspersed as comments in the assembler code. -C Leave the results of all compiles and assemblies as object files; do not invoke the linker. This allows the linker to be invoked separately, or via the C command at a later stage. -CR Produce a cross reference listing. -CR on its own will leave the raw cross-reference information in a tem- porary file, allowing the user to run CREF explicitly, while supplying a file name, e.g. -CR_F_R_E_D._C_R_F will cause CREF to be invoked to process the raw information into the specified file, in this case _F_R_E_D._C_R_F. -CPM For the Z80 cross compiler only, produce CP/M-80 COM files. Unless the -CPM option is given, the Z80 cross Page 8 HI-TECH C USER'S MANUAL compiler uses the ROM runtime startoff module and pro- duces hex or binary images. If the -CPM option is given, CP/M-80 runtime startoff code is linked used and a CP/M-80 COM file is produced. -O Invoke the optimizer on all compiled code; also requests the assembler to perform jump optimization. -O_O_U_T_F_I_L_E Specify a name for the executable file to be created. By default the name for the executable file is derived from the name of the first source or object file speci- fied to the compiler. This option allows the default to be overridden. If no dot ('.') appears in the given file name, an extension appropriate for the particular operating system will be added, e.g. -O_F_R_E_D will gen- erate a file _F_R_E_D._E_X_E on MS-DOS or _F_R_E_D._C_M_D on CP/M-86. For cross compilers this also provides a means for specifying the output format, e.g. specifying an output file _P_R_O_G._B_I_N will make the compiler generate a binary file, while specifying _P_R_O_G._H_E_X will make it generate a hexadecimal file. -V Verbose: each step of the compilation will be echoed as it is executed. -I Specify an additional filename prefix to use in search- ing for #include files. For CP/M the default prefix is 0:A: (user number 0, disk drive A). For MS-DOS the default prefix is A:\HITECH\. Under Unix and Xenix the default prefix is /usr/hitech/include/. Note that on MS-DOS a trailing backslash must be appended to any directory name given as an argument to -I; e.g. -I\FRED\ not -I\FRED. Under Unix a trailing slash should be added. -D Define a symbol to the preprocessor: e.g. -DCPM will define the symbol CPM as though via #define CPM 1. -U Undefine a pre-defined symbol. The complement of -D. -F Request the linker to produce a symbol file, for use with the debugger. -R For the Z80 CP/M compiler only this option will link in code to perform command line I/O redirection and wild card expansion in file names. See the description of _getargs() in appendix 5 for details of the syntax of the redirections. -X Strip local symbols from any files compiled, assembled or linked. Only global symbols will remain. -M Request the linker to produce a link map. -A This option, for the Z80 only, will cause the compiler to produce an executable program that will, on execu- tion, self-relocate itself to the top of the TPA HI-TECH C USER'S MANUAL Page 9 (Transient Program Area). This allows the writing of programs which may execute other programs under them- selves. Note that a program compiled in such a manner will not automatically reset the bdos address at loca- tion 6 in order to protect itself. This must be done by the program itself. For cross compilers this provides a way of specifying to the linker the addresses that the compiled program is to be linked at. The format of the option is -A_R_O_M_A_D_R,_R_A_M_A_D_R,_R_A_M_S_I_Z_E. _R_O_M_A_D_R is the address of the ROM in the system, and is where the executable code and initialized data will be placed. _R_A_M_A_D_R is the start address of RAM, and is where the bss psect will be placed, i.e. uninitialized data. _R_A_M_S_I_Z_E is the size of RAM available to the program, and is used to set the top of the stack. For the 6801/6301/68HC11 compiler, the -A option takes a fourth value which is the address of a four byte direct page area called ctemp which the compiled code uses as a scratch pad. If the ctemp address is omitted from the -A option, it defaults to address 0. Normally this will be acceptable, however some 6801 variants (like the 6303) have memory mapped I/O ports at address 0 and start their direct page RAM at address $80. For the large memory model of the 8051 compiler, the -A option takes the form -A_R_O_M_A_D_R,_I_N_T_R_A_M,_E_X_T_R_A_M,_E_X_T_S_I_Z_E. _R_O_M_A_D_R is the address of ROM in the system. _I_N_T_R_A_M is the start address of internal RAM, and is where the rbss psect will be placed. The 8051 internal stack will start after the end of the rbss psect. _E_X_T_R_A_M is the start address of external RAM, and is where the bss psect will be placed. _E_X_T_S_I_Z_E is the size of external RAM available to the program, and is used to set the top of the external stack. -B For compilers which support more than one "memory model", this option is used to select which memory model code is to be generated for. The format of this option is -Bx where x is one or more letters specifying which memory model to use. For the 8086, this option is used to select which one of five memory models (Tiny, Small, Medium, Compact or Large) is to be used. For the 8051 compiler this this option is used to select which one of the three memory models (Small, Medium or Large) is to be used. For the 8051 compiler only, this option can also be used to select static allocation of _a_u_t_o variables by appending an A to the end of the -B option. For example, -Bsa would select small model with static allocation of all variables, while -Bm would select medium model with _a_u_t_o variables dynamically allocated on the stack. Page 10 HI-TECH C USER'S MANUAL -E By default the 8086 compiler will initialize the exe- cutable file header to request a 64K data segment at run time. This may be overridden by the -E option. It takes an argument (usually in hexadecimal representa- tion) which is the number of BYTES (not paragraphs) to be allocated to the program at run time. For example -E0ffff0h will request a megabyte. Since this much will not be available, the operating system will allocate as much as it can. -W This options sets the warning level, i.e. it determines how picky the compiler is about legal but dubious type conversions etc. -W0 will allow all warning messages (default), -W1 will suppress the message "Func() declared implicit int". -W3 is recommended for compil- ing code originally written with other, less strict, compilers. -W9 will suppress all warning messages. -H This option generates a symbol file for use with debuggers. The format of the symbol file is described elsewhere. The default name of the symbol file is _l._s_y_m. An alternate name may be specfied with the option, e.g. -H_s_y_m_f_i_l_e._a_b_c. -G Like -H, -G also generates a symbol file, but one that contains line and file number information for a source level debugger. Like -H a file name may be specified. When used in conjunction with -O, only partial optimi- zation will be performed to avoid confusing the debugger. -P Execution profiling is available on native compilers running under DOS, CP/M-86 and on the Atari ST. This option generates code to turn on execution profiling when the program is run. A -H option should also be specified to provide a symbol table for the profiler EPROF. -Z For version 5.xx compilers only, the -Z option is used to select global optimization of the code generated. For the 8086 and 6801/6301/68HC11 compilers the only valid -Z option is -Zg. For the 8051 compiler, the valid -Z options are -Zg which invokes global optimiza- tion, -Zs which optimizes for space, and -Zf which optimizes for speed. The s and f options may be used with the g option, thus the options -Zgf and -Zgs are valid. Speed and space optimization are mutually exclusive, i.e. the s and f options cannot be used together. -1 For the 8086 compiler only, request the generation of code which takes advantage of the extra instructions of the 80186 processor. A program compiled with -1 will not execute on an 8086 or 8088 processor. For the 68000 compiler, generate instructions for the 68010 proces- sor. HI-TECH C USER'S MANUAL Page 11 -2 Like -1 but for the 80286 and 68020. -11 For the 6801/HC11 compiler, this option will request generation of instructions specific to the 68HC11 pro- cessor. -6301 For the 6801/HC11 compiler, this option will request generation of instructions specific to the 6301/6303 processors. Some examples of the use of the C command are: c prog.c c -mlink.map prog.c x.obj -lx c -S prog.c c -O -C -CRprog.crf prog.c prog2.c c -v -Oxfile.exe afile.obj anfile.c -lf Upper and lower case has been used in the above exam- ples for emphasis: the compiler does not distinguish between cases, although arguments specifying names, e.g. -D, are inherently case sensitive. Taking the above examples in order; the first compiles and links the C source file prog.c with the standard C library. The second example will compile the file prog.c and link it with the object file x.obj and the library libx.lib; a link map will be written to the file link.map. The third example compiles the file prog.c, leaving the assembler output in a file prog.as. It does not assemble this file or invoke the linker. The next example compiles both prog.c and prog2.c, invoking the optimizer on both files, but does not perform any linking. A cross reference listing will be left in the file _p_r_o_g._c_r_f. The last example pertains to the 8086 version of the compiler, It runs the compiler with the verbose option, and will cause anfile.c to be compiled without optimization to object code, yielding anfile.obj, then afile.obj and anfile.obj will be linked together with the floating point library (from the -LF option) and the standard library to yield the executable program xfile.exe (assuming this is performed on an MS-DOS system). One would expect this pro- gram to use floating point, if it did not then the -LF option would have been required. If more than one C or assembler source file is given to the C command, the name of each file will be printed on the console as it is processed. If any fatal errors occur dur- ing the compilation or assembly of source files, further source files will be processed, but the linker will not be Page 12 HI-TECH C USER'S MANUAL invoked. Other commands which may be issued by the user, rather than automatically by the C command, are: ZAS The Z80 assembler. AS86 The 8086 assembler. LINK The linker LIBR The library maintainer OBJTOHEX Object to hex converter CREF Cross reference generator. In general, these commands accept the same type of com- mand line as the C command, i.e. zero or more options (indi- cated by a leading '-') followed by one or more file argu- ments. If the linker or the librarian is invoked with no arguments, it wll prompt for a command line. This allows command lines of more than 128 bytes to be entered. Input may also be taken from a file by using the redirection capa- blities (see _getargs() in the library function listing). See the discussion above of the C command. These commands are described in further detail in their respective manuals. HI-TECH C USER'S MANUAL Page 13 5. Specific Features The HI-TECH C compiler has a number of features, which while largely compatible with other C compilers, contribute to more reliable programming methods. 5.1. ANSI C Standard Compatibility At the time of writing the Draft ANSI Standard for the C Language was at an advanced stage, though not yet an offi- cial standard. Accordingly it is not possible to claim com- pliance with that standard, however HI-TECH C includes the majority of the new and altered features in the draft ANSI standard. Thus it is in the sense that most people under- stand it "ANSI compatible". 5.2. Type Checking Previous C compilers have adopted a lax approach to type checking. This is typified by the Unix C compiler, which allows almost arbritary mixing of types in expres- sions. The HI-TECH C compiler performs much more strict type checking, although in most cases only warning messages are issued, allowing compilation to proceed if the user knows that the errors are harmless. This would occur, for example, when an integer value was assigned to a pointer variable. The generated code would almost certainly be what the user intended, however if in fact it represented an error in the source code, the user is prompted to check and correct it where necessary. 5.3. Member Names In early C compilers member names in different struc- tures were required to be distinct except under certain cir- cumstances. HI-TECH C, like most recent implementations of C, allows member names in different structures and unions to overlap. A member name is recognized only in the context of an expression whose type is that of the structure in which the member is defined. In practice this means that a member name will be recognized only to the right of a '.' or '->' operator, where the expression to the left of the operator is of type structure or pointer to structure the same as that in which the member name was declared. This not only allows structure names to be re-used without conflict in more than one structure, it permits strict checking of the usage of members; a common error with other C compilers is the use of a member name with a structure pointer of the wrong type, or worse with a variable which is a pointer to a simple type. There is however an escape from this, where the user desires to use as a structure pointer something which is not declared as such. This is via the use of a typecast. For example, suppose it is desired to access a memory-mapped i/o device, consisting of several registers. The declarations Page 14 HI-TECH C USER'S MANUAL and use may look something like the code fragment in fig. 2. struct io_dev { short io_status; /* status */ char io_rxdata; /* rx data */ char io_txdata; /* tx data */ }; #define RXRDY 01 /* rx ready */ #define TXRDY 02 /* tx ready */ /* define the (absolute) device address */ #define DEVICE ((struct io_dev *)0xFF00) send_byte(c) char c; { /* wait till transmitter ready */ while(!(DEVICE->io_status & TXRDY)) continue; /* send the data byte */ DEVICE->io_txdata = c; } Fig. 2. Use of Typecast on an Absolute Address In this example, the device in question has a 16 bit status port, and two 8 bit data ports. The address of the device (i.e. the address of its status port) is given as (hex)0FF00. This address is typecast to the required struc- ture pointer type to enable use of the structure member names. The code generated by this will use absolute memory references to access the device, as required. Some examples of right and wrong usage of member names are shown in fig. 3. 5.4. Unsigned Types HI-TECH C implements unsigned versions of all integral types; i.e. unsigned char, short, int and long. If an unsigned quantity is shifted right, the shift will be per- formed as a logical shift, i.e. bringing zeros into the rightmost bits. Similarly right shifts of a signed quantity will sign extend the rightmost bits. 5.5. Arithmetic Operations On machines where arithmetic operations may be per- formed more efficiently in lengths shorter than int, operands shorter than int will not be extended to int length unless necessary. For example, if two characters are added and the result stored into another character, it is only necessary to HI-TECH C USER'S MANUAL Page 15 struct fred { char a; int b; } s1, * s2; struct bill { float c; long b; } x1, * x2; main() { /* wrong - c is not a member of fred */ s1.c = 2; /* correct */ s1.a = 2; /* wrong - s2 is a pointer */ s2.a = 2; /* correct */ x2->b = 24L; /* right, but note type conversion from long to int */ s2->b = x2->b; } Fig. 3. Examples of Member Usage perform arithmetic in 8 bits, since any overflow into the top 8 bits will be lost. However, if the sum of two charac- ters is stored into an int, the addition should be done in 16 bits to ensure the correct result. In accordance with the draft ANSI standard, operations on float rather than double quantities will be performed in the shorter precision rather than being converted to double precision then back again. 5.6. Structure Operations HI-TECH C implements structure assignments, structure arguments and structure-valued functions in their full gen- erality. The example in fig. 4 is a function returning a structure. Some legal (and illegal) uses of the function are also shown. Page 16 HI-TECH C USER'S MANUAL struct bill { char a; int b; } afunc() { struct bill x; return x; } main() { struct bill a; a = afunc(); /* ok */ pf("%d", afunc().a); /* ok */ /* illegal, afunc() cannot be assigned to, therefore neither can afunc().a */ afunc().a = 1; /* illegal, same reason */ afunc().a++; } Fig. 4. Example of a Function Returning a Structure 5.7. Enumerated Types HI-TECH C supports enumerated types; these provide a structured way of defining named constants. The uses of enumerated types are more restricted than that allowed by the Unix C compiler, yet more flexible than permitted by LINT. In particular, an expression of enumerated type may be used to dimension arrays, as an array index or as the operand of a switch statement. Arithmetic may be performed on enumerated types, and enumerated type expressions may be compared, both for equality and with the relation operators. An example of the use of an enumerated type is given in fig. 5. 5.8. Initialization Syntax Kernighan and Ritchie in "The C Programming Language" state that pairs of braces may be omitted from an initial- izer in certain contexts; the draft ANSI standard provides that a conforming C program must either include all braces in an initializer, or leave them all out. HI-TECH C allows any pairs of braces to be omitted providing that the front end of the compiler can determine the size of any arrays being initialized, and providing that there is no ambiguity as to which braces have been omitted. To avoid ambiguity if any pairs of braces are present then any braces which would HI-TECH C USER'S MANUAL Page 17 /* a represents 0, b -> 1 */ enum fred { a, b, c = 4 }; main() { enum fred x, y, z; x = z; if(x < z) func(); x = (enum fred)3; switch(z) { case a: case b: default: } } Fig. 5. Use of an Enumerated Type enclose those braces must also be present. The compiler will complain ("initialization syntax") if any ambiguity is present. 5.9. Function Prototypes A new feature of C included in the proposed ANSI for C, known as "function prototypes", provides C with an argument checking facility, i.e. it allows the compiler to check at compile time that actual arguments supplied to a function invocation are consistent with the formal parameters expected by the function. The feature allows the programmer to include in a function declaration (either an external declaration or an actual definition) the types of the param- eters to that function. For example, the code fragment shown in fig. 6 shows two function prototypes. void fred(int, long, char *); char * bill(int a, short b, ...) { return a; } Fig. 6. Function Prototypes The first prototype is an external declaration of the function _f_r_e_d(), which accepts one integer argument, one long argument, and one argument which is a pointer to char. Any usage of _f_r_e_d() while the prototype declaration is in scope will cause the actual parameters to be checked for number and type against the prototype, e.g. if only two arguments were supplied or an integral value was supplied for the third argument the compiler would report an error. Page 18 HI-TECH C USER'S MANUAL In the second example, the function _b_i_l_l() expects two or more arguments. The first and second will be converted to int and short respectively, while the remainder (if present) may be of any type. The ellipsis symbol (...) indicates to the compiler that zero or more arguments of any type may follow the other arguments. The ellipsis symbol must be last in the argument list, and may not appear as the only argu- ment in a prototype. All prototypes for a function must agree exactly, how- ever it is legal for a definition of a function in the old style, i.e. with just the parameter names inside the parentheses, to follow a prototype declaration provided the number and type of the arguments agree. In this case it is essential that the function definition is in scope of the prototype declaration. Access to unspecified arguments (i.e. arguments sup- plied where an ellipsis appeared in a prototype) must be via the macros defined in the header file . This defines the macros _v_a__s_t_a_r_t, _v_a__a_r_g and _v_a__e_n_d. See _v_a__s_t_a_r_t in the library function listing for more information. NOTE that is is a grave error to use a function which has an associated prototype unless that prototype is in scope, i.e. the prototype MUST be declared (possibly in a header file) before the function is invoked. Failure to comply with this rule may result in strange behaviour of the program. HI-TECH C will issue a warning message ("func() declared implicit int") whenever a function is called without an explicit declaration. It is good practice to declare all functions and global variables in one or more header files which are included wherever the functions are defined or referenced. 5.10. Void and Pointer to Void The _v_o_i_d type may be used to indicate to the compiler that a function does not return a value. Any usage of the return value from a void function will be flagged as an error. The type _v_o_i_d *, i.e. pointer to void, may be used as a "universal" pointer type. This is intended to assist in the writing of general purpose storage allocators and the like, where a pointer is returned which may be assigned to another variable of some other pointer type. The compiler permits without typecasting and without reporting an error the conversion of _v_o_i_d * to any other pointer type and vice versa. The programmer is advised to use this facility care- fully and ensure that any _v_o_i_d * value is usable as a pointer to any other type, e.g. the alignment of any such pointer should be suitable for storage of any object. HI-TECH C USER'S MANUAL Page 19 5.11. Type qualifiers The ANSI C standard introduced the concept of _t_y_p_e _q_u_a_l_i_f_i_e_r_s to C; these are keywords that qualify the type to which they are applied. The type qualifiers defined by ANSI C are const and volatile. HI-TECH C also implements several other type qualifiers. The extra qualifiers include: far near interrupt fast interrupt port Not all versions of the compilers implement all of the extra qualifiers. See the machine dependent section for further information. When constructing declarations using type qualifiers, it is very easy to be confused as to the exact semantics of the declaration. A couple of rules-of-thumb will make this easier. Firstly, where a type qualifier appears at the left of a declaration it may appear with any storage class specifier and the basic type in any order, e.g. static void interrupt func(); is semantically the same as interrupt static void func(); Where a qualifier appears in this context, it applies to the basic type of the declaration. Where a qualifier appears to the right of one or more '*' (_s_t_a_r) pointer modifiers, then you should read the declaration from right to left, e.g. char * far fred; should be read as "fred is a far pointer to char". This means that fred is qualified by _f_a_r, not the char to which it points. On the other hand, char far * bill; should be read as "bill is a pointer to a far char", i.e. the char to which bill points is located in the far address space. In the context of the 8086 compiler this will mean that bill is a 32 bit pointer while fred is a 16 bit pointer. You will hear bill referred to as a "far pointer", however the terminology "pointer to far" is preferred. Page 20 HI-TECH C USER'S MANUAL 5.12. There are two methods provided for in-line assembler code in C programs. The first allows several lines of assembler anywhere in a program. This is via the #asm and #endasm preprocessor directives. Any lines between these two directives will be copied straight through to the assem- bler file produced by the compiler. Alternatively you can use the asm("_s_t_r_i_n_g"); construct anywhere a C statement is expected. The _s_t_r_i_n_g will be copied through to the assembler file. Care should be taken with using in-line assembler since it may interact with compiler generated code. 5.13. Pragma Directives The draft ANSI C standard provides for a #pragma preprocessor directive that allows compiler implementations to control various aspects of the compilation process. Currently HI-TECH C only supports one pragma, the _p_a_c_k directive. This allows control over the manner in which members are allocated inside a structure. By default, some of the compilers (especially the 8086 and 68000 compilers) will align structure members onto even boundaries to optim- ize machine accesses. It is sometimes desired to override this to achieve a particular layout inside a structure. The _p_a_c_k pragma allows specification of a maximum packing fac- tor. For example, #pragma pack1(1) will instruct the com- piler that no additional padding be inserted between struc- ture members, i.e. that all members should be aligned on boundaries divisible by 1. Similarly #pragma pack(2) will allow alignment on boundaries divisible by 2. In no case will use of the _p_a_c_k pragma force a greater alignment than would have been used for that data type anyway. More that one _p_a_c_k pragma may be used in a program. Any use will remain in force until changed by another _p_a_c_k or until the end of the file. Do not use a _p_a_c_k pragma before include files such as <_s_t_d_i_o._h> as this will cause incorrect declarations of run-time library data structures. HI-TECH C USER'S MANUAL Page 21 6. Machine Dependencies HI-TECH C eliminates many of the machine dependent aspects of C, since it uniformly implements such features as unsigned char. There are however certain areas where machine dependencies are inherent in the C language; programmers should be aware of these and take them into account when writing portable code. The most obvious of these machine dependencies is the varying size of C types; on some machines an int will be 16 bits, on others it may be 32 bits. HI-TECH C conforms to the following rules, which represent common practice in most C compilers. char is at least 8 bits short is at least 16 bits long is at least 32 bits int is the same as either short or long float is at least 32 bits double is at least as wide as float Because of the variable width of an int, it is recom- mended that short or long be used wherever possible in preference to int. The exception to this is where a quantity is required to correspond to the natural word size of the machine. Another area of machine differences is that of byte ordering; the ordering of bytes in a short or long can vary significantly between machines. There is no easy approach to this problem other than to avoid code which depends on a particular ordering. In particular you should avoid writing out whole structures to a file (via _f_w_r_i_t_e()) unless the file is only to be read by the same program then deleted. Different compilers use different amounts of padding between structure members, though this can be modified via the #pragma pack(n) construct. 6.1. Predefined Macros One technique through which machine unavoidable machine dependencies may be managed is the predefined macros pro- vided by each compiler to identify the target processor and operating system (if any). These are defined by the compiler driver and may be tested with conditional compilation preprocessor directives. The macros defined by various compilers are listed in table 2. These can be used as shown in the example in fig . Page 22 HI-TECH C USER'S MANUAL ___________________________________________ |_M_a_c_r_o_______________D_e_f_i_n_e_d__f_o_r_____________| | i8051 8051 processor family | | i8086 8086 processor family | | i8096 8096 processor family | | z80 Z80 processor and derivatives | | m68000 68000 processor family | | m6800 6801, 68HC11 and 6301 processors| | m6809 6809 processor | | DOS MS-DOS and PC-DOS | | CPM CP/M-80 and CP/M-86 | | TOS Atari ST | |___________________________________________| Table 2. Predefined Macros #if DOS char * filename = "c:file"; #endif /* DOS */ #if CPM char * filename = "0:B:afile"; #endif /* CPM */ Use this page for notes HI-TECH C USER'S MANUAL Page 23 7. Error Checking and Reporting Errors may be reported by any pass of the compiler, however in practice the assembler and optimizer will not encounter any errors in the generated code. The types of errors produced by each pass are summarized below. In gen- eral any error will be indentified by the name of the source file in which it was encountered, and the line number at which it was detected. P1 will also nominate the name of the function inside which the error was detected. Errors may be redirected to a file with the usual syn- tax, i.e. a 'greater than' symbol ('>') followed by the name of a file into which the errors should be written. The file name may of course be a device name, e.g. LST: for CP/M or PRN for MS-DOS. CPP will report errors relating to macro definitions and expansions, as well as conditional compilation. P1 is the pass which reports most errors; it performs syntax and semantic checking of the input, and will report both fatal and warning errors when encountered. Syntax errors will normally be expressed as "symbol expected" or "symbol unexpected". Semantic errors may relate to unde- clared, redeclared or misdeclared variables. P1 will also report variable definitons which are unused or unreferenced. These errors are warnings, as are most type checking errors. When P1 encounters errors it will list the source line containing the error on the screen, and underneath display the error message and an up arrow pointing to the point at which the compiler detected the error. In some cases the actual cause of the error may be earlier in the line or even on previous line. CGEN may occasionally report errors, usually warnings, and mostly related to unusual combinations of types with constants, for example testing if an unsigned quantity is less than zero. One fatal error produced by CGEN is "can't generate code for this expression" and means that the expression currently being compiled is in some way too com- plicated to produce code for. This can usually be overcome by rewriting the source code. Such errors are rare and will occur only for unusual constructs. The linker will report undefined or multiply defined symbols. Note that variable declarations inside a header file which is included in more than one source file must be declared as extern, to avoid multiply defined symbol errors. These symbols must then be defined in one and one only source file. A comprehensive list of error messages is included in an appendix. Page 24 HI-TECH C USER'S MANUAL Use this page for notes HI-TECH C USER'S MANUAL Page 25 8. Standard Libraries 8.1. Standard I/O C is a language which does not specify the I/O facil- ites in the language itself; rather all I/O is performed via library routines. In practice this results in I/O handling which is no less convenient than any other language, with the added possibility of customising the I/O for a specific application. For example it is possible to provide a routine to replace the standard getchar() (which gets one character from the standard input) with a special getchar(). This is particulary useful when writing code which is to run on a special hardware configuration, while maintaining a high level of compatibility with "standard" C I/O. There is in fact a Standard I/O library (STDIO) which defines a portable set of I/O routines. These are the rou- tines which are normally used by any C application program. These routines, along with other non-I/O library routines, are listed in detail in a subsequent section of the manual. 8.2. Compatibility The libraries supplied with HI-TECH C are highly compa- tible with the ANSI libraries, as well as the V7 UNIX libraries, both at the Standard I/O level and the UNIX sys- tem call level. The Standard I/O library is complete, and conforms in all respects with the UNIX Standard I/O library. The library routines implementing UNIX system call like functions are as close as possible to those system calls, however there are some UNIX system calls that cannot be simulated on other systems, e.g. the link() operation. How- ever the basic low level I/O routines, i.e. open, close, read, write and lseek are identical to the UNIX equivalents. This means that many programs written to run on UNIX, even if they do not use Standard I/O, will run with little modif- ication when compiled with HI-TECH C. 8.3. Libraries for Embedded Systems The cross compilers, designed to produce code for tar- get systems without operating systems, are supplied with libraries implementing a subset of the STDIO functions. Not provided are those functions dealing with files. Included are _p_r_i_n_t_f(), _s_c_a_n_f() etc. These operate by calling two low level functions _p_u_t_c_h and _g_e_t_c_h() which typically send and receive characters via a serial port. Where the compiler is aimed at a single-chip micro with on-board UART this is used. The source code for all these functions is supplied enabling the user to modify it to address a different serial port. Page 26 HI-TECH C USER'S MANUAL 8.4. Binary I/O On some operating systems, notably CP/M, files are treated differently according to whether they contain ASCII (i.e. printable) or binary data. MD-DOS also suffers from this problem, not due to any lack in the operating system itself, but rather because of the hangover from CP/M which results in many programs putting a redundant ctrl-Z at the end of files. Unfortunately there is no way to determine which type of data a file contains (except perhaps by the name or type of the file, and this is not reliable). To overcome this difficulty, there is an extra character which may be included in the MODE string to a fopen() call. To open a file for ASCII I/O, the form of the fopen() call is: fopen("filename.ext", "r") /* for reading */ fopen("filename.ext", "w") /* for writing */ To open a file for binary I/O, the character 'b' may be appended to the fopen("filename.ext", "rb") fopen("filename.ext", "wb") The additional character instructs the STDIO library that this file is to be handled in a strict binary fashion. On CP/M or MS-DOS, a file opened in ASCII mode will have the following special character handling performed by the STDIO routines: newline ('\n') converted to carriage return/newline on output. return ('\r') ignored on input Ctrl-Z interpreted as End-Of-File on input and, for CP/M only, appended when closing the file. The special actions performed on ASCII files ensure that the file is written in a format compatible with other programs handling text files, while eliminating the require- ment for any special handling by the user program - the file appears to the user program as though it were a UNIX-like text file. None of these special actions are performed on a file opened in binary mode. This is required when handling any kind of binary data, to ensure that spurious bytes are not inserted, and premature EOF's are not seen. Since the binary mode character is additional to the normal mode character, this usage is quite compatible with UNIX C. When compiled on UNIX, the additional character will be ignored. HI-TECH C USER'S MANUAL Page 27 A mention here of the term `stream' is appropriate; stream is used in relation to the STDIO library routines to mean the source or sink of bytes (characters) manipulated by those routines. Thus the FILE pointer supplied as an argu- ment to the STDIO routines may be regarded as a handle on the corresponding stream. A stream may be viewed as a featureless sequence of bytes, originating from or being sent to a device or file or even some other indeterminate source. A FILE pointer should not be confused with the 'file descriptors' used with the low-level I/O functions _o_p_e_n(), _c_l_o_s_e(), _r_e_a_d() and _w_r_i_t_e(). These form an independent group of I/O functions which perform unbuffered reads and writes to files. 8.5. Floating Point Library HI-TECH C supports floating point as part of the language, however the Z80 implementation provides single precision only; double floats are permitted but are no dif- ferent to floats. In addition, the standard library, LIBC.LIB, does not contain any floating point routines. These have been separated out into another library, LIBF.LIB. This means that if this library is not searched no floating point support routines will be linked in, thus avoiding any size penalty for the floating point support if it is not used. This is particulary important for printf and scanf, and thus LIBF.LIB contains versions of printf and scanf that do support floating point formats. Thus, if floating point is used, a -LF option should be used AFTER the source and/or object files to the C command. E.g.: C -V -O x.c y.c z.obj -LF Page 28 HI-TECH C USER'S MANUAL Use this page for notes HI-TECH C USER'S MANUAL Page 29 9. Stylistic Considerations Although it is not the purpose of this manual to set out a coding standard for C, some comments regarding use of some of the features of HI-TECH C may be useful. 9.1. Member Names Although HI-TECH C allows the same structure or union member name to be used in more than one structure or union, this may not be allowed by another C compiler. To help ensure portability of the code, it is recommended that member names all be distinct, and a useful way of ensuring this is to prefix each member name with one or two letters derived from the name of the structure itself. An example is given in fig. 7. struct tree_node { struct tree_node * t_left; struct tree_node * t_right; short t_operator; }; Fig. 7. Member Naming Because HI-TECH C insists on use of all intermediate names when referencing a member nested inside several struc- tures, some simple macro definitions can serve as a short- hand. An example is given in fig. 8. struct tree_node { short t_operator; union { struct tree_node * t_un_sub[2]; char * t_un_name; long t_un_val; } t_un; }; #define t_left t_un.t_un_sub[0] #define t_right t_un.t_un_sub[1] #define t_name t_un.t_un_name #define t_val t_un.t_un_val Fig. 8. Member Name Shorthand This enables the variant components of the structure to be referred to by short names, while guaranteeing portabil- ity and presenting a clean definition of the structure. Page 30 HI-TECH C USER'S MANUAL 9.2. Use of Int It is recommended that the type int be avoided wherever possible, in preference to the types short or long. This is because of the variable size of int, whereas short is com- monly 16 bits and long 32 bits in most C implementations. 9.3. Extern Declarations Some compilers permit a non-initialized global variable to be declared in more than one place, with the multiple definitions being resolved by the linker as all defining the same thing. HI-TECH C specifically disallows this, since it may lead to subtle bugs. Instead, global variables may be declared extern in as many places as you wish, and must be defined in one and one only place. Typically this will mean declaring global variables in a header file as extern, and defining each variable in the file most closely associated with that variable. This usage will be portable to virually all other C implementations. HI-TECH C USER'S MANUAL Page 31 10. Memory Models With many of the processors supported by the HI-TECH C compilers there are more than one address space accessible to a program. Typically one address space is more economical to access than another, larger address space. Thus it is desirable to be able to tailor a prorgram's use of memory to achieve the greatest economy in addressing (thus minimizing program size and maximizing speed) while allowing access to as much memory as the program requires. This concept of different address spaces is not catered for by either K&R or ANSI C (except to recognize the possi- bility of separate address spaces for code and data). Without any extensions to the language itself it is possible to devise more than one memory model for a given processor, selected at compile time. This has the effect of selecting one addressing method for all data and/or code. This permits the model for a particular program to be chosen depending on that program's memory requirements. In many programs, however, only one or two data struc- tures are large enough to need to be placed in the larger address space. Selection of a "large" memory model for the whole of the program makes the whole program larger and slower just to allow a few large data structures. This can be overcome by allowing individual selection of the address space for each data structure. Unfortunately this entails extensions to the language, never a desirable approach. To minimize the effect of such extensions they should satisfy the following criteria: 1. As far as possible the extensions should be consistent with common practice. 2. The extensions should fit a machine-independent model to maximize portability across processors and operating systems. These goals have been achieved within HI-TECH C by means of the following model: Each memory model defines three address spaces each for code and data. These address spaces are known as the _n_e_a_r, _f_a_r and _d_e_f_a_u_l_t spaces. Any object qualified by the near keyword will be placed in the _n_e_a_r address space, any object qual- ified by the far keyword shall be placed in the _f_a_r address space, and all other objects shall be placed in the _d_e_f_a_u_l_t address space. The _n_e_a_r address space shall be a (possibly improper) sub- space of the _d_e_f_a_u_l_t address space, while the _d_e_f_a_u_l_t address space shall be a (possibly improper) subspace of the _f_a_r address space. There shall be up to three kinds of pointers correspond- ing to the three address spaces, each capable of Page 32 HI-TECH C USER'S MANUAL addressing an object in its own address space or a subspace of that address space. This implies that the address of an object may be con- verted to a pointer into a larger address space, e.g. a _n_e_a_r object may have its address converted to a pointer to _f_a_r, but a _f_a_r object may not be able to be addressed by a pointer to _n_e_a_r. In practice the _d_e_f_a_u_l_t address space will usually correspond exactly to either the _n_e_a_r or _f_a_r address spaces. If all three address spaces correspond to the same memory then there is only one memory model possible. This occurs with the 68000 processor. Where the _d_e_f_a_u_l_t code and data spaces may each correspond to either the _n_e_a_r or _f_a_r address spaces then there will be a total of four memory models. This is the case with the 8086 processor. The keywords far and near are supported by all the HI- TECH C compilers, but the exact correspondence of address spaces is determined by the individual characteristics of each processor and the choice of memory model (if there is a choice). However code written using these keywords will be portable providing it obeys the constraints of the model described above. This model also corresponds well with other implementa- tions using the near and far keywords, although such imple- mentations do not appear to have been designed around a for- mal, portable model. HI-TECH C USER'S MANUAL Page 33 11. What Went Wrong There are numerous error messages that the compiler may produce. Most of these relate to errors in the source code (syntax errors of various kinds and so forth) but some represent limitations, particularly of memory. The two passes most likely to be affected by memory limitations are the code generator and the optimizer. The code generator will issue the message "No room" if it runs out of dynamic memory. This can usually be eliminated by simplifying the expression at the line nominated in the error message. The more complex the expression, the more memory is required to store the tree representing it. Reducing the number of sym- bols used in the program will also help. Note that this error is different from the message "Can't generate code for this expression" which indicates that the expression is in some way too difficult for the code generator to handle. This message will be encountered very infrequently, and can be eliminated by changing the expression in some way, e.g. computing an intermediate value into a temporary variable. The optimizer reads the assembler code for a whole function into memory at one time. Very large functions will not fit, giving the error message "Optim: out of memory in _func" where func is the name of the function responsible. In this case the function should be broken up into smaller functions. This will only occur with functions with several hundred lines of C source code. Good coding practice will normally limit functions to less than 50 lines each. If a pass exits with the message "Error closing file", or "Write error on file", this usually indicates that there is insufficient room on the current disk. If you use a wordprocessing editor such as Wordstar, ensure that you use the "non-document" mode or whatever the corresponding mode is. The edited file should not contain any characters with the high bit set, and the line feed at the end of the line must be present. Lines should be not more than 255 characters long. When using floating point, ensure that you use a -LF flag at the END of the command line, to cause the floating point library to be searched. This will cause floating ver- sions of printf and scanf to be linked in, as well as specific floating point routines. If the non-floating version of printf is used with a floating format such as %f then it will simply print the letter f. If the linker gives an "Undefined symbol" message for some symbol which you know nothing about, it is possible that it is a library routine which was not found during the Page 34 HI-TECH C USER'S MANUAL library search due to incorrect library ordering. In this case you can search the library twice, e.g. for the stan- dard library add a -LC to the end of the C command line, or -LF for the floating library. If you have specified the library by name simply repeat its name. HI-TECH C USER'S MANUAL Page 35 12. Z80 Assembler Reference Manual 12.1. Introduction The assembler incorporated in the HI-TECH C compiler system is a full-featured relocating macro assembler accept- ing Zilog mnemonics. These mnemonics and the syntax of the Z80 assembly language are described in the "Z80 Assembly Language Handbook" published by Zilog and are included at the end of this manual as a reference. The assembler imple- ments certain extensions to the operands allowed, and cer- tain additional pseudo-ops, which are described here. The assembler also accepts the additional opcodes for the Hita- chi 64180 and Z180 processors. 12.2. Usage The assembler is named zas, and is invoked as follows: ZAS options files ... The files are one or more assembler source files which will be assembled, but note that all the files are assembled as one, not as separate files. To assemble separate files, the assembler must be invoked on each file separately. The options are zero or more options from the following list: -N Ignore arithmetic overflow in expressions. The -N option suppresses the normal check for arithmetic over- flow. The assembler follows the "Z80 Assembly Language Handbook" in its treatment of overflow, and in certain instances this can lead to an error where in fact the expression does evaluate to what the user intended. This option may be used to override the overflow check- ing. -J Attempt to optimize jumps to branches. The -J option will request the assembler to attempt to assemble jumps and conditional jumps as relative branches where possi- ble. Only those conditional jumps with branch equivalents will be optimized, and jumps will only be optimized to branches where the target is in branch range. Note that the use of this option slows the assembly down, due to the necessity for the assembler to make an additional pass over the input code. -U Treat undefined symbols as external. The -U option will suppress error messages relating to undefined sym- bols. Such symbols are treated as externals in any case. The use of this option will not alter the object code generated, but merely serves to suppress the error messages. Page 36 HI-TECH C USER'S MANUAL -O_f_i_l_e Place the object code in _f_i_l_e. The default object file name is constructed from the name of the first source file. Any suffix or file type (i.e. anything following the rightmost dot ('.') in the name is stripped, and the suffix .obj appended. Thus the command ZAS file1.as file2.z80 will produce an object file called file1.obj. The use of the -O option will override this default convention, allowing the object file to be arbitrarily named. For example: ZAS -ox.obj file1.obj will place the object code in x.obj. -L_l_i_s_t Place an assembly listing in the file _l_i_s_t, or on stan- dard output if _l_i_s_t is null A listfile may be produced with the -L option. If a file name is supplied to the option, the list file will be created with that name, otherwise the listing will be written to standard out- put (i.e. the console). List file names such as CON: and LST: are acceptable. -W_w_i_d_t_h The listing is to be formatted for a printer of given _w_i_d_t_h The -W option specifies the width to which the listing is to be formatted. E.g. ZAS -Llst: -W80 x.as will output a listing formatted for an 80 column printer to the list device. -C This options requests ZAS to produce cross reference information in a file. The file will be called _x_x_x.crf where _x_x_x is the base part of the first source file name. It will then be necessary to run the CREF utility to turn this information into a formatted listing. 12.3. The Assembly Language As mentioned above, the assembly language accepted by zas is based on the Zilog mnemonics. You should have some reference book such as the "Z80 Assembly Language Handbook". Described below are those areas in which zas differs, or has extensions, compared to the standard Zilog assembly language. 12.3.1. Symbols The symbols (labels) accepted by the assembler may be of any length, and all characters are significant. The char- acters used to form a symbol may be chosen from the upper and lower case alphabetics, the digits 0-9, and the special HI-TECH C USER'S MANUAL Page 37 symbols underscore ('_'), dollar ('$') and question mark ('?'). The first character may not be numeric. Upper and lower case are distinct. The following are all legal and distinct symbols. An_identifier an_identifier an_identifier1 $$$ ?$_123455 Note that the symbol $ is special (representing the current location) and may not be used as a label. Nor may any opcode or pseudo-op mnemonic, register name or condition code name. You should note the additional condition code names described later. 12.3.1.1. Temporary Labels The assembler implements a system of temporary labels, useful for use within a localized section of code. These help eliminate the need to generate names for labels which are referenced only in the immediate vicinity of their definition, for example where a loop is implemented. A temporary label takes the form of a digit string. A reference to such a label requires the same digit string, plus an appended b or f to signify a backward or forward reference respectively. Here is an example of the use of such labels. entry_point: ;This is referenced from far away ld b,10 1: dec c jr nz,2f ;if zero, branch forward to 2: ld c,8 djnz 1b ;decrement and branch back to 1: jr 1f ;this does not branch to the ;same label as the djnz 2: call fred ;get here from the jr nz,2f 1: ret ;get here from the jr 1f The digit string may be any positive decimal number 0 to 65535. A temporary label value may be re-used any number of times. Where a reference to e.g. 1b is made, this will reference the closest label 1: found by looking backwards from the current point in the file. Similarly 23f will reference the first label 23: found by looking forwards from the current point in the file. 12.3.2. Constants Constants may be entered in one of the radices 2, 8, 10 or 16. The default is 10. Constants in the other radices may be denoted by a trailing character drawn from the following set: Page 38 HI-TECH C USER'S MANUAL Character Radix Name B 2 binary O 8 octal Q 8 octal o 8 octal q 8 octal H 16 hexadecimal h 16 hexadecimal Hexadecimal constants may also be specified in C style, for example LD A,0x21. Note that a lower case b may not be used to indicate a binary number, since 1b is a backward reference to a temporary label 1:. 12.3.2.1. Character Constants A character constant is a single character enclosed in single quotes ('). Multi character constants may be used only as an operand to a DEFM pseudo-op. 12.3.2.2. Floating Constants A floating constant in the usual notation (e.g. 1.234 or 1234e-3) may be used as the operand to a DEFF pseudo-op. 12.3.2.3. Opcode Constants Any z80 opcode may be used as a constant in an expres- sion. The value of the opcode in this context will be the byte that the opcode would have assembled to if used in the normal way. If the opcode is a 2-byte opcode (CB or ED pre- fix byte) only the second byte of the opcode will be used. This is particularly useful when setting up jump vectors. For example: ld a,jp ;a jump instruction ld (0),a ;0 is jump to warm boot ld hl,boot ;done here ld (1),hl 12.3.3. Expressions Expressions are constructed largely as described in the "Z80 Assembly Language Handbook". 12.3.3.1. Operators The following operators may be used in expressions: Operator Meaning & Bitwise AND * Multiplication + Addition - Subtraction HI-TECH C USER'S MANUAL Page 39 .and. Bitwise AND .eq. Equality test .gt. Signed greater than .high. Hi byte of operand .low. Low byte of operand .lt. Signed less than .mod. Modulus .not. Bitwise complement .or. Bitwise or .shl. Shift left .shr. Shift right .ult. Unsigned less than .ugt. Unsigned greater than .xor. Exclusive or / Divison < Signed less than = Equality > Signed greater than ^ Bitwise or Operators starting with a dot "." should be delimited by spaces, thus label .and. 1 is valid but label.and.1 is not. 12.3.3.2. Relocatability Zas produces object code which is relocatable; this means that it is not necessary to specify assembly time where the code is to be located in memory. It is possible to do so, by use of the ORG pseudo-op, however the preferred approach is to use program sections or psects. A psect is a named section of the program, in which code or data may be defined at assembly time. All parts of a psect will be loaded contiguously into memory, even if they were defined in separate files, or in the same file but separated by code for another psect. For example, the following code will load some executable instructions into the psect named text, and some data bytes into the data psect. Page 40 HI-TECH C USER'S MANUAL psect text, global alabel: ld hl,astring call putit ld hl,anotherstring psect data, global astring: defm 'A string of chars' defb 0 anotherstring: defm 'Another string' defb 0 psect text putit: ld a,(hl) or a ret z call outchar inc hl jr putit Note that even though the two blocks of code in the text psect are separated by a block in the data psect, the two text psect blocks will be contiguous when loaded by the linker. The instruction "ld hl,anotherstring" will fall through to the label "putit:" during execution. The actual location in memory of the two psects will be determined by the linker. See the linker manual for information on how psect addresses are determined. A label defined in a psect is said to be relocatable, that is, its actual memory address is not determined at assembly time. Note that this does not apply if the label is in the default (unnamed) psect, or in a psect declared abso- lute (see the PSECT pseudo-op description below). Any labels declared in an absolute psect will be absolute, that is their address will be determined by the assembler. With the version of ZAS supplied with version 7 or later of HI-TECH C, relocatable expressions may be combined freely in expressions. Older versions of ZAS allowed only limited arithmetic on relocatable expressions. 12.3.4. Pseudo-ops The pseudo-ops are based on those described in the "Z80 Assembly Language Handbook", with some additions. 12.3.4.1. DEFB, DB This pseudo-op should be followed by a comma-separated list of expressions, which will be assembled into sequential HI-TECH C USER'S MANUAL Page 41 byte locations. Each expression must have a value between -128 and 255 inclusive. DB can be used as a synonym for DEFB. Example: DEFB 10, 20, 'a', 0FFH DB 'hello world',13,10,0 12.3.4.2. DEFF This pseudo-op assembles floating point constants into 32 bit HI-TECH C format floating point constants. For exam- ple: pi: DEFF 3.14159 12.3.4.3. DEFW This operates in a similar fashion to DEFB, except that it assembles expressions into words, without the value res- triction. Example: DEFW -1, 3664H, 'A', 3777Q 12.3.4.4. DEFS Defs reserves memory locations without initializing them. Its operand is an absolute expression, representing the number of bytes to be reserved. This expression is added to the current location counter. Note however that locations reserved by DEFS may be initialized to zero by the linker if the reserved locations are in the middle of the program. Example: DEFS 20h ;reserve 32 bytes of memory 12.3.4.5. EQU Equ sets the value of a symbol on the left of EQU to the expression on the right. It is illegal to set the value of a symbol which is already defined. Example: SIZE equ 46 12.3.4.6. DEFL This is identical to EQU except that it may redefine existing symbols. Example: Page 42 HI-TECH C USER'S MANUAL SIZE defl 48 12.3.4.7. DEFM Defm should be followed by a string of characters, enclosed in single quotes. The ASCII values of these char- acters are assembled into successive memory locations. Example: DEFM 'A string of funny *@$ characters' 12.3.4.8. END The end of an assembly is signified by the end of the source file, or the END pseudo-op. The END pseudo-op may optionally be followed by an expression which will define the start address of the program. This is not actually use- ful for CP/M. Only one start address may be defined per pro- gram, and the linker will complain if there are more. Exam- ple: END somelabel 12.3.4.9. COND, IF, ELSE, ENDC Conditional assembly is introduced by the COND pseudo- op. The operand to COND must be an absolute expression. If its value is false (zero) the code following the COND up to the corresponding ENDC pseudo-op will not be assembled. COND/ENDC pairs may be nested. IF may be used as a synonym for COND. The ELSE pseudo operation may be included within a COND/ENDC block, for example: IF CPM call 5 ELSE call os_func ENDC 12.3.4.10. ELSE See COND. 12.3.4.11. ENDC See COND. HI-TECH C USER'S MANUAL Page 43 12.3.4.12. ENDM See MACRO. 12.3.4.13. PSECT This pseudo-op allows specification of relocatable pro- gram sections. Its arguments are a psect name, optionally followed by a list of psect flags. The psect name is a sym- bol constructed according to the same rules as for labels, however a psect may have the same name as a label without conflict. Psect names are recognized only after a PSECT pseudo-op. The psect flags are as follows: ABS Psect is absolute GLOBAL Psect is global LOCAL Psect is not global OVRLD Psect is to be overlapped by linker PURE Psect is to be read-only If a psect is global, the linker will merge it with any other global psects of the same name from other modules. Local psects will be treated as distinct from any other psect from another module. Psects are global by default. By default the linker concatenates code within a psect from various modules. If a psect is specified as OVRLD, the linker will overlap each module's contribution to that psect. This is particularly useful when linking modules which initialize e.g. interrupt vectors. The PURE flag instructs the linker that the psect is to be made read-only at run time. The usefulness of this flag depends on the ability of the linker to enforce the require- ment. CP/M fails miserably in this regard. The ABS flag makes a psect absolute. The psect will be loaded at zero. This is useful for statically initializing interrupt vectors and jump tables. Examples: PSECT text, global, pure PSECT data, global PSECT vectors, ovrld 12.3.4.14. GLOBAL Global should be followed by one more symbols (comma separated) which will be treated by the assembler as global symbols, either internal or external depending on whether they are defined within the current module or not. Example: Page 44 HI-TECH C USER'S MANUAL GLOBAL label1, putchar, _printf 12.3.4.15. ORG An ORG pseudo-op sets the current psect to the default (absolute) psect, and the location counter to its operand, which must be an absolute expression. Example: ORG 100H 12.3.4.16. MACRO This pseudo-op defines a macro. It should be either preceded or followed by the macro name, then optionally fol- lowed by a comma-separated list of formal parameters. The lines of code following the MACRO pseudo-op up to the next ENDM pseudo-op will be stored as the body of the macro. The macro name may subsequently be used in the opcode part of an assembler statement, followed by actual parameters. The text of the body of the macro will be substituted at that point, with any use of the formal parameters substituted with the corresponding actual parameter. For example: print MACRO string psect data 999: db string,'$' psect text ld de,999b ld c,9 call 5 ENDM When used, this macro will expand to the 3 instructions in the body of the macro, with the actual parameters substi- tuted for func and arg. Thus print 'hello world' expands to psect data 999: db 'hello world','$' psect text ld de,999b ld c,9 call 5 Macro arguments can be enclosed in angle brackets ('<' HI-TECH C USER'S MANUAL Page 45 and '>') to pass arbitrary text including delimiter charac- ters like commas as a single argument. For example, suppose you wanted to use the print macro defined above to print a string which includes the carriage return and linefeed char- acters. The macro invocation: print 'hello world',13,10 would fail because 13 and 10 are treated as extra arguments and ignored. In order to pass a string which includes commas as a single argument, you could write: print <'hello world',13,10> which would cause the text 'hello world',13,10 to be passed through as a single argument. This would expand to the fol- lowing code: psect data 999: db 'hello world',13,10,'$' psect text ld de,999b ld c,9 call 5 ZAS supports two forms of macro declaration for compa- tibility with older versions of ZAS and other Z80 assem- blers. The macro name may be declared either in the label field before the MACRO pseudo-op, or in the operand field after the MACRO pseudo-op. Thus these two MACRO declara- tions are equivalent: bdos MACRO func,arg ld de,arg ld c,func call 5 ENDM and MACRO bdos,func,arg ld de,arg ld c,func call 5 ENDM 12.3.4.17. LOCAL The LOCAL pseudo-op allows unique labels to be defined for each expansion of a macro. Any symbols listed after the LOCAL directive will have a unique assembler-generated sym- bol substituted for them when the macro is expanded. For Page 46 HI-TECH C USER'S MANUAL example: copy MACRO source,dest,count LOCAL nocopy push af push bc ld bc,source ld a,b or c jr z,nocopy push de push hl ld de,dest ld hl,source ldir pop hl pop de nocopy: pop bc pop af ENDM when expanded will include a unique assembler generated label in place of nocopy. For example, copy (recptr),buf,(recsize) will expand to: push af push bc ld bc,(recsize) ld a,b or c jr z,??0001 push de push hl ld de,buf ld hl,(recptr) ldir pop hl pop de ??0001: pop bc pop af if invoked a second time, the label nocopy would expand to ??0002. 12.3.4.18. REPT The REPT pseudo-op defines a temporary macro which is then expanded a number of times, as determined by its argu- ment. For example: REPT 3 ld (hl),0 inc hl ENDM will expand to HI-TECH C USER'S MANUAL Page 47 ld (hl),0 inc hl ld (hl),0 inc hl ld (hl),0 inc hl 12.3.5. IRP and IRPC The IRP and IRPC directives are similar to REPT, how- ever instead of repeating the block a fixed number of times it is repeated once for each member of an argument list. In the case of IRP the list is a conventional macro argument list, in the case of IRPC it is successive characters from a string. For example: IRP string,<'hello world',13,10>,'arg2' LOCAL str psect data str: db string,'$' psect text ld c,9 ld de,str call 5 ENDM would expand to psect data ??0001: db 'hello world',13,10,'$' psect text ld c,9 ld de,??0001 call 5 psect data ??0002: db 'arg2','$' psect text ld c,9 ld de,??0002 call 5 Note the use of LOCAL labels and angle brackets in the same manner as with conventional macros. IRPC is best demonstrated using the following example: IRPC char,ABC ld c,2 ld e,'char' call 5 ENDM Page 48 HI-TECH C USER'S MANUAL will expand to: ld c,2 ld e,'A' call 5 ld c,2 ld e,'B' call 5 ld c,2 ld e,'C' call 5 12.3.6. Extended Condition Codes The assembler recognizes several additional condition codes. These are: _________________________________________________ | Code| Equivalent| Meaning | | alt | m | Arithmetic less than | | llt | c | Logical less than | | age | p | Arithmetic greater or equal| | lge | nc | Logical greater or equal | | di | | Use after ld a,i for test-| | ei | | ing state of interrupt| | | | enable flag - enabled or| ||______||_____________||__d_i_s_a_b_l_e_d__r_e_s_p_e_c_t_i_v_e_l_y_._______|| 12.4. Assembler Directives An assembler directive is a line in the source file which produces no code, but rather which modifies the behaviour of the assembler. Each directive is recognized by the presence of an asterisk in the first column of the line, followed immediately by a word, only the first character of which is looked at. the line containing the directive itself is never listed. The directives are: *Title Use the text following the directive as a title for the listing. *Heading Use the text following the directive as a subtitle for the listing; also causes an *Eject. *List May be followed by ON or OFF to turn listing on or off respectively. Note that this directive may be used inside a macro or include file to control listing of that macro or include file. The previous listing state will be restored on exit from the macro or include file. HI-TECH C USER'S MANUAL Page 49 *Include The file named following the directive will be included in the assembly at that point. *Eject A new page will be started in the listing at that point. A form feed character in the source will have the same effect. Some examples of the use of these directives: *Title Widget Control Program *Heading Initialization Phase *Include widget.i 12.5. Diagnostics An error message will be written on the standard error stream for each error encountered in the assembly. This mes- sage identifies the file name and line number and describes the error. In addition the line in the listing where the error occurred will be flagged with a single character to indicate the error. The characters and the corresponding messages are: Page 50 HI-TECH C USER'S MANUAL A: Absolute expression required B: Bad arg to *L Bad arg to IM Bad bit number Bad character constant Bad jump condition D: Directive not recognized Digit out of range E: EOF inside conditional Expression error G: Garbage after operands Garbage on end of line I: Index offset too large J: Jump target out of range L: Lexical error M: Multiply defined symbol O: Operand error P: Phase error Psect may not be local and global R: Relocation error S: Size error Syntax error U: Undefined symbol Undefined temporary label Unterminated string 12.6. Z80/Z180/64180 Instruction Set The remainder of this chapter is devoted to a complete instruction set listing for the Z80, Z180, 64180 and NSC800 processors. The Z180 and 64180 will execute all Z80 instructions, although the timing is different. HI-TECH C USER'S MANUAL Page 51 Page 52 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 53 Page 54 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 55 Page 56 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 57 Page 58 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 59 Page 60 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 61 Page 62 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 63 Page 64 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 65 Page 66 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 67 Page 68 HI-TECH C USER'S MANUAL HI-TECH C USER'S MANUAL Page 69 13. Linker Reference Manual HI-TECH C incorporates a relocating assembler and linker to permit separate compilation of C source files. This means that a program may be divided into several source files, each of which may be kept to a manageable size for ease of editing and compilation, then each object file com- piled separately and finally all the object files linked together into a single executable program. The assembler is described in the machine-specific manual. This appendix describes the theory behind and the usage of the linker. 13.1. Relocation and Psects The fundamental task of the linker is to combine several relocatable object files into one. The object files are said to be relocatable since the files have sufficient information in them so that any references to program or data addresses (e.g. the address of a function) within the file may be adjusted according to where the file is ulti- mately located in memory after the linkage process. Thus the file is said to be relocatable. Relocation may take two basic forms; relocation by name, i.e. relocation by the ultimate value of a global symbol, or relocation by psect, i.e. relocation by the base address of a particular section of code, for example the section of code containing the actual excutable instructions. 13.1.1. Program Sections Any object file may contain bytes to be stored in memory in one or more program sections, which will be referred to as psects. These psects represent logical group- ings of certain types of code bytes in the program. The section of the program containing executable instructions is normally referred to as the text psect. Other sections are the initialized data psect, called simply the data psect, and the uninitialized data psect, called the bss psect. In fact the linker will handle any number of psects, and in fact more may be used in special applications. How- ever the C compiler uses only the three mentioned, and the names text, data and bss are simply chosen for identifica- tion; the linker assigns no special significance to the name of a psect. The difference between the data and bss psects may be exemplified by considering two external variables; one is initialized to the value 1, and the other is not initial- ized. The first will be placed into the data psect, and the second in the bss psect. The bss psect is always cleared to zeros on startup of the program, thus the second variable will be initialized at run time to zero. The first will how- ever occupy space in the program file, and will maintain its Page 70 HI-TECH C USER'S MANUAL initialized value of 1 at startup. It is quite possible to modify the value of a variable in the data psect during exe- cution, however it is better practice not to do so, since this leads to more consistent use of variables, and allows for restartable and romable programs. The text psect is the section into which all executable instructions are placed. On CP/M-80 the text psect will nor- mally start at the base of the TPA, which is where execution commences. The data psect will normally follow the text psect, and the bss will be last. The bss does not occupy space in the program (.COM) file. This ordering of psects may be overridden by an option to the linker. This is espe- cially useful when producing code for special hardware. For MS-DOS and CP/M-86 the psects are ordered in the same way, but since the 8086 processor has segment registers providing relocation, both the text and data psects start at 0, even though they will be loaded one after the other in memory. This allows 64k code and 64k data and stack. Suffi- cient information is placed in the executable file (.EXE or .CMD) for the operating system to load the program in memory. 13.1.2. Local Psects and the Large Model Since for practical purposes the psects are limited to 64K on the 8086, to allow more than 64K code the compiler makes use of local psects. A psect is considered local if the .psect directive has a LOCAL flag. Any number of local psects may be linked from different modules without being combined even if they have the same name. Note however that no local psect may have the same name as a global psect. All references to a local psect within the same module (or within the same library) will be treated as references to the same psect. Between modules however two local psects of the same name are treated as distinct. In order to allow collective referencing of local psects via the -P option (described later) a local psect may have a class name asso- ciated with it. This is achieved witht the _C_L_A_S_S flag on the .psect directive. 13.2. Global Symbols The linker handles only symbols which have been declared as global to the assembler. From the C source level, this means all names which have storage class exter- nal and which are not declared as static. These symbols may be referred to by modules other than the one in which they are defined. It is the linker's job to match up the defini- tion of a global symbol with the references to it. HI-TECH C USER'S MANUAL Page 71 13.3. Operation A command to the linker takes the following form: LINK options files ... Options is zero or more linker options, each of which modifies the behaviour of the linker in some way. Files is one or more object files, and zero or more library names. The options recognized by the linker are as follows: they will be recognized in upper or lower case. -R Leave the output relocatable. -L Retain absolute relocation info. -LM will retain only segement relocation information. -I Ignore undefined symbols. -N Sort symbols by address. -Caddr Produce a binary output file offset by addr. -S Strip symbol information from the output file. -X Suppress local symbols in the output file. -Z Suppress trivial (compiler-generated) symbols in the output file. -Oname Call the output file name. -Pspec Spec is a psect location specification. -Mname Write a link map to the file name. -Usymbol Make symbol initially undefined. -Dfile Write a symbol file. -Wwidth Specify map width. Taking each of these in turn: The -R option will instruct the linker to leave the output file (as named by a -O option, or l.obj by default) relocatable. This is normally because there are further files to be linked in, and the output of this link will be used as input to the linker subsequently. Without this option, the linker will make the output file absolute, that Page 72 HI-TECH C USER'S MANUAL is with all relocatable addresses made into absolute refer- ences. This option may not be used with the -L or -C options. The -L option will cause the linker to output null relocation information even though the file will be abso- lute. This information allows self-relocating programs to know what addresses must be relocated at run time. This option is not usable with the -C option. In order to create an executable file (i.e. a .COM file) the program objtohex must be used. If a -LM option is used, only segment reloca- tion information will be retained. This is used in conjuc- tion with the large memory model. Objtohex will use the relocation information (when invoked with a -L flag) to insert segment relocation addresses into the executable file. The -I option is used when it is desired to link code which contains symbols which are not defined in any module. This is normally only used during top-down program develop- ment, when routines are referenced in code written before the routines themselves have been coded. When obtaining a link map via the -M option, the symbol table is by default sorted in order of symbol name. To sort in order of address, the -N option may be used. The output of the linker is by default an object file. To create an executable program, this must be converted into an executable image. For CP/M this is a .COM file, which is simply an image of the executable program as it should appear in memory, starting at location 100H. The linker will produce such a file with the -C100H option. File formats for other applications requiring an image binary file may also be produced with the -C option. The address following the -C may be given in decimal (default), octal (by using o or O suffix) or hexadecimal (by using an h or H suffix). Note that because of the complexity of the executable file formats for MS-DOS and CP/M-86, LINK will not produce these (.EXE and .CMD resp.) formats directly. The compiler automatically runs OBJTOHEX with appropriate options to gen- erate the correct file format. The -S, -X and -Z options, which are meaningless when the -C option is used, will strip respectively all symbols, all local symbols or all trivial local symbols from the out- put file. Trivial symbols are symbols produced by the com- piler, and have the form of one of a set of alphabetic char- acters followed by a digit string. The default output file name is _l._o_b_j, or _l._b_i_n when the -C option is used. This may be overridden by the -O_n_a_m_e option. The output file will be called _n_a_m_e in this instance. Note that no suffix is appended to the name; the file will be called exactly the argument to the option. For certain specialized applications, e.g. producing HI-TECH C USER'S MANUAL Page 73 code for an embedded microprocessor, it is necessary to specify to the linker at what address the various psects should be located. This is accomplished with the -P option. It is followed by a specification consisting of a comma- separated list of psect names, each with an optional address specification. In the absence of an address specification for a psect listed, it will be concatenated with the previ- ous psect. For example -Ptext=0c000h,data,bss=8000h This will cause the text psect to be located at 0C000H, the data psect to start at the end of the text psect, and the bss psect to start at 8000H. This may be for a processor with ROM at 0C000H and RAM at 8000H. Where the link address, that is the address at which the code will be addressed at execution time, and the load address, that is the address offset within the output file, are different (e.g for the 8086) it is possible to specify the load address separately from the link address. For exam- ple: -Ptext=100h/0,data=0C000h/ This specification will cause the text segment to be linked for execution at 100h, but loaded in the output file at 0, while the data segment will be linked for 0C000h, but loaded contiguously with the text psect in the file. Note that if the slash (`/') is omitted, the load address is the same as the link address, while if the slash is supplied, but not followed by an address, the psect will be loaded after the previous psect. In order to specify link and load addresses for local psects, the group name to which the psects belong may be used in place of a global psect name. The local psects will then have a link address as specified in the -P option, and load addresses incrementing upwards from the specified load address. The -Mname option requests a link map, containing sym- bol table and module load address information to be written onto the file name. If name is omitted, the map will be written to standard output. -W may be used to specify the desired width of the map. The -U option allows the specification to the linker of a symbol which is to be initially entered into the symbol table as undefined. This is useful when loading entirely from libraries. More than one -U flag may be used. If it is desired to use the debugger on the program being linked, it is useful to produce a symbol file. The -D_f_i_l_e option will write such a symbol file onto the named _f_i_l_e, or _l._s_y_m if no file is given. The symbol file consists Page 74 HI-TECH C USER'S MANUAL of a list of addresses and symbols, one per line. 13.4. Examples Here are some examples of using the linker. Note how- ever that in the normal case it is not necessary to invoke the linker explicitly, since it is invoked automatically by the C command. LINK -MMAP -C100H START.OBJ MAIN.OBJ A:LIBC.LIB This command links the files start.obj and main.obj with the library a:libc.lib. Only those modules that are required from the library will be in fact linked in. The output is to be in .COM format, placed in the default file l.bin. A map is to be written to the file of the name map. Note that the file start.obj should contain startup code, and in fact the lowest address code in that file will be executed when the program is run, since it will be at 100H. LINK -X -R -OX.OBJ FILE1.OBJ FILE2.OBJ A:LIBC.LIB The files file1.obj and file2.obj will be linked with any necessary routines from a:libc.lib and left in the file x.obj. This file will remain relocatable. Undefined symbols will not cause an error. The file x.obj will probably later be the object of another link invocation. All local symbols will be stripped from the output file, thus saving space. 13.5. Invoking the Linker The linker is called LINK, and normally resides on the A: drive, under CP/M, or in the directory A:\HITECH\ under MS-DOS. It may be invoked with no arguments, in which case it will prompt for input from standard input. If the stan- dard input is a file, no prompts will be printed. The input supplied in this manner may contain lower case, whereas CP/M converts the entire command line to upper case by default. This is useful with the -U and -P options. This manner of invocation is generally useful if the number of arguments to LINK is large. Even if the list of files is too long to fit on one line, continuation lines may be included by leaving a backslash ('\') at the end of the preceding line. In this fashion, LINK commands of almost unlimited length may be issued. HI-TECH C USER'S MANUAL Page 75 14. Librarian The librarian program, LIBR, has the function of com- bining several object files into a single file known as a library. The purposes of combining several such object modules are several. a. fewer files to link b. faster access c. uses less disk space In order to make the library concept useful, it is necessary for the linker to treat modules in a library dif- ferently from object files. If an object file is specified to the linker, it will be linked into the final linked module. A module in a library, however, will only be linked in if it defines one or more symbols previously known, but not defined, to the linker. Thus modules in a library will be linked only if required. Since the choice of modules to link is made on the first pass of the linker, and the library is searched in a linear fashion, it is possible to order the modules in a library to produce special effects when linking. More will be said about this later. 14.1. The Library Format The modules in a library are basically just con- catenated, but at the beginning of a library is maintained a directory of the modules and symbols in the library. Since this directory is smaller than the sum of the modules, the linker is speeded up when searching a library since it need read only the directory and not all the modules on the first pass. On the second pass it need read only those modules which are required, seeking over the others. This all minim- izes disk i/o when linking. It should be noted that the library format is geared exclusively toward object modules, and is not a general pur- pose archiving mechanism as is used by some other compiler systems. This has the advantage that the format may be optimized toward speeding up the linkage process. 14.2. Using The librarian program is called LIBR, and the format of commands to it is as follows: LIBR k file.lib file.obj ... Interpreting this, LIBR is the name of the program, k is a key letter denoting the function requested of the librarian (replacing, extracting or deleting modules, list- ing modules or symbols), file.lib is the name of the library file to be operated on, and file.obj is zero or more object Page 76 HI-TECH C USER'S MANUAL file names. The key letters are: r replace modules d delete modules x extract modules m list module names s list modules with symbols When replacing or extracting modules, the file.obj arguments are the names of the modules to be replaced or extracted. If no such arguments are supplied, all the modules in the library will be replaced or extracted respec- tively. Adding a file to a library is performed by request- ing the librarian to replace it in the library. Since it is not present, the module will be appended to the library. If the r key is used and the library does not exist, it will be created. Under the d keyletter, the named object files will be deleted from the library. In this instance, it is an error not to give any object file names. The m and s keyletters will list the named modules and, in the case of the s keyletter, the symbols defined or referenced within (global symbols only are handled by the librarian). As with the r and x keyletters, an empty list of modules means all the modules in the library. 14.3. Examples Here are some examples of usage of the librarian. LIBR m file.lib List all modules in the library file.lib. LIBR s file.lib a.obj b.obj c.obj List the global symbols in the modules a.obj, b.obj and c.obj LIBR r file.lib 1.obj 2.obj Replace the module 1.obj in the file file.lib with the contents of the object file 1.obj, and repeat for 2.obj. If the object module is not already present in the library, append it to the end. LIBR x file.lib Extract, without deletion, all the modules in file.lib and write them as object files on disk. LIBR d file.lib a.obj b.obj 2.obj Delete the object modules a.obj, b.obj and 2.obj from the library file.lib. HI-TECH C USER'S MANUAL Page 77 14.4. Supplying Arguments Since it is often necessary to supply many object file arguments to LIBR, and command lines are restricted to 127 characters by CP/M and MS-DOS, LIBR will accept commands from standard input if no command line arguments are given. If the standard input is attached to the console, LIBR will prompt. Multiple line input may be given by using a backslash as a continuation character on the end of a line. If standard input is redirected from a file, LIBR will take input from the file, without prompting. For example: LIBR libr> r file.lib 1.obj 2.obj 3.obj \ libr> 4.obj 5.obj 6.obj will perform much the same as if the .obj files had been typed on the command line. The libr> prompts were printed by LIBR itself, the remainder of the text was typed as input. LIBR prompt. A backslash at the end of the line will be interpreted to mean that more command lines follow. HI-TECH C USER'S MANUAL Page 85 APPENDIX 1 Error Messages Error Messages produced by the compiler are listed below. Each message is followed by the name of the program which produces it, and some further description of what causes the message or what to do about it. '.' expected after '..' P1 The ellipsis symbol must have three dots actuals too long CPP Reduce length of macro arguments argument list conflicts with prototype P1 The argument list in a function definition must agree with a prototype if one exists argument redeclared P1 This argument has been declared twice arithmetic overflow in constant expression CGEN Evaluation of this constant expression produced an arithmetic overflow. This may or may not represent a true error. array index out of bounds P1 An array index expression evaluates to a constant which is less than zero or greater than or equal to the dimension of the array Assertion CGEN Internal error - contact HI-TECH attempt to modify const object P1 An attempt has been made to assign to or otherwise modify an object designated as 'const' bad bitfield type P1 Bitfields must be of type 'int' Bad conval CGEN Internal error - contact HI-TECH Bad dimensions CGEN An array has bad dimensions - probably zero Bad element count expr CGEN Internal error - contact HI-TECH bad formal CPP Check macro defintion syntax Page 86 HI-TECH C USER'S MANUAL bad include syntax CPP Use only "" and <> for include files Bad int. code CGEN The intermediate code file has been corrupted - can be caused by running out of disk space Bad -M option CGEN A -M option passed to the code generator is unknown Bad mod '+' for how = c CGEN Internal error - contact HI-TECH bad object code format LINK This file is either corrupted or not a valid object file Bad op d to swaplog CGEN Internal error - contact HI-TECH Bad op n to revlog CGEN Internal error - contact HI-TECH bad origin format in spec LINK An address in a -p option is invalid bad '-p' format LINK The -p option provided is invalid Bad pragma c CGEN The code generator has been passed a pragma it does not know about Bad putwsize CGEN Internal error - contact HI-TECH bad storage class P1, CGEN The speficied storage class is illegal Bad U usage CGEN Internal error - contact HI-TECH Bit field too large (n bits) CGEN A bit field may not be larger than an int Cannot get memory LINK The linker has run out of dynamic memory Can't be both far and near P1 The 'far' and 'near' keywords cannot appear in the same type specifier can't be long P1 Chars and shorts cannot be long can't be register P1 An extern or static variable may not be register HI-TECH C USER'S MANUAL Page 87 can't be short P1 Float and char cannot be short can't be unsigned P1 Float cannot be unsigned can't call an interrupt function P1 A function qualified 'interrupt' can only be called by hardware, not by an ordinary function call Can't create filename CGEN The file specified could not be created Can't create xref file P1 The cross reference file specified could not be created Can't create CPP Output file could not be created Can't create LINK The linker cannot create a file Can't find include file CPP Check and correct the include file name - spaces are not allowed in file names Can't find register for bits CGEN Internal error - contact HI-TECH Can't generate code for this expression CGEN The code generator is unable to generate code for this expression - simplifying the expression (e.g. computing values into temporary variables) will usually correct it, otherwise contact HI-TECH can't have array of functions P1 You cannot have an array of functions - you can have an array of pointers to functions Can't have 'port' variable CGEN You cannot declare a variable to be qualified 'port' - you can only use port to qualify pointers or typecast constant values can't have storage class P1 A storage class may not appear in a prototype argument can't initialise auto aggregates P1 You cannot initialise a structure or array inside a function unless it is static can't initialize arg P1 An argument cannot have an initializer can't mix proto and non-proto args P1 You cannot mix prototype and non-prototype arguments even in a function definition Page 88 HI-TECH C USER'S MANUAL Can't open filename CGEN The file specified could not be opened for reading Can't open LINK The linker cannot open a file Can't seek LINK The linker could not seek in file can't take address of register variable P1 You can't take the address of a variable in a register can't take sizeof func CGEN You can't take the size of a function. You can take the size of a function call can't take this address P1 The expression does not have an address 'case' not in switch P1 A 'case' label is permitted only inside a switch char const too long P1 A character constant may have only one character in it close error (disk space?) P1 Probably out of disk space common symbol psect conflict LINK A common symbol is defined to be in more than one psect constant conditional branch CGEN You have a program structure testing a constant expres- sion, e.g. while(1). You should substitute for this the more efficient for(;;) constant expression required P1 A constant expression is required in e.g. an array dimension constant operand to || or && CGEN A logical operator has a constant operand which has been optimized out declarator too complex P1 This declaration is too complex for the compiler to handle default case redefined P1 Only one default case is permitted in a switch 'default' not in switch P1 A 'default' label is permitted only inside a switch digit out of range P1 An octal constant may not contain 7 or 8, and a decimal constant may not contain A-F HI-TECH C USER'S MANUAL Page 89 dimension required P1 A dimension is required for all except the most signi- ficant in an array declaration Division by zero CGEN Attempt to divide by zero in this expression Duplicate case label n CGEN There are two case labels in this switch that have the same value Duplicate -d flag LINK Only one -d flag is allowed to the linker duplicate label P1 This label is defined twice Duplicate -m flag LINK Only one -m flag is allowed to the linker duplicate qualifier P1 The same qualifier appears more than once in this type specifier entry point multiply defined LINK A program can only have one entry point (start address) EOF in #asm P1 End of file was encounterd after #asm and before a #endasm was seen Error closing output file CGEN,CPP Probably means you have run out of disk space excessive -I file ignored CPP Use fewer -I options expand - bad how CGEN Internal error - contact HI-TECH expand - bad which CGEN Internal error - contact HI-TECH exponent expected P1 An exponent is expected after the 'e' or 'E' in a floating point constant. The exponent must contain only +, - and digits 0-9 Expression error CGEN Internal error - contact HI-TECH expression generates no code CGEN This expression has no side effects and thus generates no code. It has been optimized out expression syntax P1 The expression is badly formed Page 90 HI-TECH C USER'S MANUAL expression too complex P1 The expression has too many nested parantheses or other nested constructs Fixup overflow referencing LINK The linker has relocated a reference to a psect or sym- bol and the relocated address is too big to fit into the space, e.g. a relocated one byte address exceeds 256 or a relocated 16 bit address exceeds 65536 float param coerced to double P1 This float parameter has been converted to double - a prototype will override this coercion function() declared implicit int P1 This function has been called without an explicit declaration. It is wise to explicitly declare all func- tions, preferably with a prototype. This will avoid many potential errors where your program comprises more than one source file function does not take arguments P1 The prototype for this function indicates it takes no arguments function or function pointer required P1 A function identifier or pointer to function is required for a function call. functions can't return arrays P1 A function cannot return an array - it can return a pointer functions can't return functions P1 A function cannot return a function - it can return a pointer to function hex digit expected P1 A hex digit is expected after '0x' identifier is a structure tag P1 A structure tag has been used in a context where another kind of tag is expected, e.g. saying struct fred where fred has previously been declared as union fred. identifier is a union tag P1 Similar to the above error identifier is an enum tag P1 Similar to the above error identifier: large offset CGEN Z80 only: This identifier has a large offset from the stack frame and thus access to it is inefficient. In a function any arrays should be declared after any simple variables HI-TECH C USER'S MANUAL Page 91 identifier redeclared P1 The identifier has been redeclared with different attributes identifier redefined P1 An identifier has been defined twice If-less else CPP Check #if usage If-less endif CPP Check #if usage illegal '#' directive P1 A # directive passed through to the first pass is unk- nown. If this occurs with a #include it may be caused by a previous include file not having a or newline on the last line. Illegal character in preprocessor if CPP Check for strange character illegal character P1 A character unknown to the compiler has been encoun- tered. The value given is the octal value of the char- acter illegal conversion between pointer types P1 The expression causes one pointer type to be converted to another incompatible type illegal conversion of integer to pointer P1 An integer is used where a pointer is expected illegal conversion of pointer to integer P1 A pointer is used where an integer is expected illegal conversion P1 The type conversion here is illegal Illegal flag LINK This option is illegal illegal function qualifier(s) P1 A function cannot have 'const' qualification illegal initialisation P1 The initialisation of this variable is illegal Illegal number CPP Check number syntax illegal type for array dimension P1 An array dimension must be an integral quantity illegal type for index expression P1 An array index must be a simple integral expression Page 92 HI-TECH C USER'S MANUAL illegal type for switch expression P1 The expression in a 'switch' must be integral illegal use of void expression P1 Void expressions may not be used in any way implicit conversion of float to integer P1 A floating point value has been converted to integer - truncation may occur implicit return at end of non-void function P1 A function with a non-void type has returned without a return statement implict signed to unsigned conversion P1 Unwanted sign extension may occur here. Add an explicit typecast to force exactly the conversion you want inappropriate break/continue P1 inappropriate 'else' P1 An 'else' has appeared without a matching 'if' inconsistent storage class P1 Only one storage class may be specified in a declara- tion inconsistent type P1 Only one basic type may be specified in a declaration initialisation illegal in arg list P1 You cannot initialise a function parameter initialisation syntax P1 The syntax of this initialisation is illegal initializer in 'extern' declaration P1 A declaration with the 'extern' keyword has an initial- izer; this is not permitted as the extern declaration reserves no storage integer constant expected P1 An integer constant was expected here integer expression required P1 An integral expression is required here integral type required P1 An integral type is required here large offset CGEN Z80 only: This identifier has a large offset from the stack frame and thus access to it is inefficient. In a function any arrays should be declared after any simple variables HI-TECH C USER'S MANUAL Page 93 Line too long P1 The source line is too long, or does not have a or newline at the end local psect conflicts with global psect of same name LINK A local psect cannot have the same name as a global psect logical type required P1 A logical type (i.e. an integral type) is required as the subject of a conditional expression lvalue required P1 An lvalue, i.e. something which can be assigned to, is required after an '&' or on the left hand of an assign- ment macro recursion CPP A preprocessor macro has attempted to expand itself. This would create infinite recursion member is not a member of the struct/union P1 This member is not in the structure or union with which it is used members cannot be functions P1 A member cannot be a function - it can be a pointer to function Missing arg to -u LINK -u requires an argument Missing arg to -w LINK -w requires an argument missing ) CPP Put correct ) in expression Missing number after % in -p option LINK After % in a -p option there must be a number Missing number after pragma 'pack' P1 The correct syntax is #pragma pack(n) where n is 1, 2 or 4. module has code below file base LINK A -C option was specified but the program has code below the address specified as the base of the binary file multiply defined symbol LINK A symbol is defined more than once name is a union, struct or enum P1 A union, struct or enum tag has been re-used in a dif- ferent context Page 94 HI-TECH C USER'S MANUAL No case labels CGEN This switch has no case labels no identifier in declaration P1 This declaration should have an identifier in it No room CGEN The code generator has run out of dynamic memory. You will need to reduce the number of symbols and/or the complexity of expressions No source file CPP Source file could not be found - check spelling, direc- tory paths etc. no space CPP Reduce number/size of macro definitions no start record: entry point defaults to zero LINK No start address has been specified for the program; the linker has set the start address to 0 Non-constant case label CGEN This case label does not evaluate to an integral con- stant non-void function returns no value P1 A function which should return a value has a 'return' statement with no value not a variable identifier P1 The identifier is not a variable - it may be e.g. a label or structure tag not an argument P1 This identifier is not in the argument list for this function only functions may be qualified interrupt P1 The type qualifier 'interrupt' may be applied only to functions, not variables. only functions may be void P1 Only functions, not variables, may be declared void only lvalues may be assigned to or modified P1 You have attempted to modify an expression which does not identify a storage location only register storage class allowed P1 A parameter may only be auto or register operands of operator not same pointer type P1 The operands to the named operator in the expression are both pointers but are not the same pointer type HI-TECH C USER'S MANUAL Page 95 operands of operator not same type P1 The operands to the named operator in the expression are incompatible types pointer required P1 A pointer is required after a '*' (indirection) opera- tor popreg - bad reg CGEN Internal error - contact HI-TECH portion of expression has no effect CGEN A portion of this expression has no effect on its value and no side effects probable missing '}' in previous block P1 A declaration has been encountered where an expression was expected. The likely cause of this is that you have omitted a closing '}' in the function above this point. psect cannot be in classes a and b LINK A psect can only be in one class psect exceeds max size LINK This psect is larger than a specified maximum size psect is absolute LINK This psect is absolute and cannot have a link address specified in a -p option Psect not loaded on 0xhexnum boundary LINK This psect must be loaded on a specific boundary Psect not relocated on 0xhexnum boundary LINK This psect must be linked on a specific boundary psect origin multiply defined LINK This psect has its link address defined more than once pushreg - bad reg CGEN Internal error - contact HI-TECH redundant & applied to array P1 An array type has an '&' operator applied to it. It has been ignored since use of an array implicitly gives its address regused - bad arg to G CGEN Internal error - contact HI-TECH signatures do not matchLINK An extern function has been declared with an incorrect prototype. For example if an argument is declared as a long in an extern declaration, but is really an int, a signature mismatch will occur. Page 96 HI-TECH C USER'S MANUAL signed bitfields not supported P1 Only unsigned bitfields are supported simple type required P1 An array or structure type cannot be used here Sizeof yields 0 CGEN The size of an object has evaluated to zero in a con- text where this is illegal, e.g. incrementing a pointer to a zero length object. storage class illegal P1 A storage class may not be specified here struct/union member expected P1 A structure or union member is required after a '. or '->' struct/union redefined P1 This structure or union has been defined twice struct/union required P1 A structure or union identifier is required before a '.' Switch on long! CGEN Switching on a long expression is not supported symbol cannot be global LINK Stack, filename or line number symbols cannot be global Syntax error in checksum list LINK The checksum list provided is invalid token too long CPP Shorten token (e.g. identifier) too few arguments P1 The protype for this function lists more arguments than have been supplied too many arguments P1 More arguments have been supplied than listed in the prototype for this function Too many cases in switch CGEN,P1 There are too many cases in this switch too many -D options CPP Use fewer -D options too many defines CPP Reduce number of macro definitions Too many errors CGEN CGEN has given up because there were too many errors. HI-TECH C USER'S MANUAL Page 97 too many formals CPP Reduce number of parameters to this macro definition Too many initializers CGEN There are too many initializers for this object Too many psects LINK There are too many psects for the symbol table Too many symbols LINK There are too many symbols for the linker symbol table too many -U options CPP Use fewer -U options too much defining CPP Reduce number/size of macros too much indirection P1 Too many '*'s in this declaration too much pushback CPP Simplify macro usage type conflict P1 There is a conflict of types in this expression, e.g. attempting to assign a structure to a simple type type specifier reqd. for proto arg P1 A prototype argument must have a basic type undefined control CPP Check use of # undefined enum tag P1 This enumerated type tag has not been defined undefined identifier P1 This identifier has not been defined before use undefined struct/union P1 The structure or union used has not been defined undefined symbol LINK A list of undefined symbols follows. If some of the symbols should be in a library which was linked, it may be caused by a library ordering problem. In this case rebuild the library with the correct ordering or specify the library more than once in the link command unexpected EOF P1 End of file was encountered in the middle of a C con- struct. This is commonly caused by omission of a clos- ing '}' earlier in the program. Unknown predicate CGEN Internal error - contact HI-TECH Page 98 HI-TECH C USER'S MANUAL unknown psect LINK The psect specifed in a -p option is not present in the program. Check the spelling and check the case - upper case does not match lower case unreachable code P1 This section of code can never be executed as there is no possible path to reach it Unreasonable include nesting CPP Reduce number of include files Unreasonable matching depth CGEN Internal error - contact HI-TECH unterminated macro call CPP Probably missing ) void function cannot return value P1 A function declared void cannot return a value Write error (out of disk space?) LINK Probably means the disk is full HI-TECH C USER'S MANUAL Page 99 APPENDIX 2 Standard Library Functions The functions accessible to user programs in the stan- dard library libc.lib are listed below, by category with a short comment, then alphabetically with a longer descrip- tion. In the detailed description of each function, the SYNOPSIS section describes the function in roughly the manner in which the function would be declared in the source file defining it. Where an include file is shown, this implies that that include file must be included in any source file using that function. Where an include file is not provided, it will normally be necessary for an extern declaration of the function to be included in any source module using it, to ensure that the type of the function is correct. For example, if the func- tion _l_s_e_e_k() was to be used, a declaration of the form extern long lseek(); should be in either the source file itself or an include file included in the source file. This ensures that the com- piler knows that _l_s_e_e_k() returns a long value and not the default int. Where reference is made to STDIO, this means the group of functions under the heading STANDARD I/O below. These all have one thing in common; they operate on pointers to a defined data type called FILE. Such a pointer is often referred to as a _s_t_r_e_a_m pointer. The concept of a stream is central to these routines. Essentially a stream is a source or sink of data bytes. To the operating system and library routines this stream is featureless, i.e. no record struc- ture is implied or assumed. Some routines do however recog- nize end of line characters. STANDARD I/O fopen(name, mode) Open file for I/O freopen(name, mode, stream) Re-open existing stream fdopen(fd, mode) Associate a stream with a file descriptor fclose(stream) Close open file fflush(stream) Flush buffered data getc(stream) Read byte from stream fgetc(stream) Same as getc ungetc(c, stream) Push char back onto stream putc(c, stream) Write byte to stream fputc(c, stream) Same as putc() getchar() Read byte from standard input putchar(c) Write byte to standard output getw(stream) Read word from stream Page 100 HI-TECH C USER'S MANUAL putw(w, stream) Write word to stream gets(s) Read line from standard input fgets(s, n, stream) Read string from stream puts(s) Write string to standard output fputs(s, stream) Write string to stream fread(buf, size, cnt, stream) Binary read from stream fwrite(buf, size, cnt, stream) Binary write to stream fseek(stream, offs, wh) Random access positioning ftell(stream) Current file read/write position rewind(stream) Reposition file pointer to start setvbuf(stream, buf, mode, size) Enable/disable buffering of stream fprintf(stream, fmt, args) Formatted output on stream printf(fmt, args) Formatted standard output sprintf(buf, fmt, args) Formatted output to a string vfprintf(stream, fmt, va_ptr) Formatted output on stream vprintf(fmt, va_ptr) Formatted standard output vsprintf(buf, fmt, va_ptr) Formatted output to a string fscanf(stream, fmt, args) Formatted input from stream scanf(fmt, args) Formatted standard input sscanf(buf, fmt, va_ptr) Formatted input from a string vfscanf(stream, fmt, va_ptr) Formatted input from stream vscanf(fmt, args) Formatted standard input vsscanf(buf, fmt, va_ptr) Formatted input from a string feof(stream) True if stream at EOF ferror(stream) True if error on stream clrerr(stream) Reset error status on stream fileno(stream) Return fd from stream remove(name) Remove (delete) file STRING HANDLING atoi(s) Convert ASCII decimal to integer atol(s) Convert ASCII decimal to long integer atof(s) Convert ASCII decimal to float xtoi(s) Convert ASCII hexadecimal to integer memchr(s, c, n) Find char in memory block memcmp(s1, s2, n) Compare n bytes of memory memcpy(s1, s2, n) Copy n bytes from s2 to s1 memmove(s1, s2, n) Copy n bytes from s2 to s1 memset(s, c, n) Set n bytes at s to c strcat(s1, s2) Append string 2 to string 1 strncat(s1, s2, n) Append at most n chars to string 1 strcmp(s1, s2) Compare strings strncmp(s1, s2, n) Compare n bytes of strings strcpy(s1, s2) Copy s2 to s1 strncpy(s1, s2, n) Copy at most n bytes of s2 strerror(errnum) Map errnum to an error message string strlen(s) Length of string strchr(s, c) Find char in string strrchr(s, c) Find rightmost char in string strspn(s1, s2) Length of s1 composed of chars from s2 strcspn(s1, s2) Length of s2 composed of chars not from s2 strstr(s1, s2) Locate the first occurence of s2 in s1 HI-TECH C USER'S MANUAL Page 101 LOW LEVEL I/O open(name, mode) Open a file close(fd) Close a file creat(name) Create a file dup(fd) Duplicate file descriptor lseek(fd, offs, wh) Random access positioning read(fd, buf, cnt) Read from file rename(name1, name2) Rename file unlink(name) Remove file from directory write(fd, buf, cnt) Write to file isatty(fd) True if fd refers to tty-like device stat(name, buf) Get information about a file chmod(name, mode) Set file attributes CHARACTER TESTING isalpha(c) True if c is a letter isupper(c) Upper case letter islower(c) Lower case letter isdigit(c) Digit isalnum(c) Alphnumeric character isspace(c) Space, tab, newline, return or formfeed ispunct(c) Punctuation character isprint(c) Printable character isgraph(c) Printable non-space character iscntrl(c) Control character isascii(c) Ascii character (0-127) FLOATING POINT cos(f) Cosine function sin(f) Sine function tan(f) Tangent function acos(f) Arc cosine function asin(f) Arc sine function atan(f) Arc tangent function exp(f) Exponential of f log(f) Natural log of f log10(f) Base 10 log of f pow(x,y) X to the y'th power sqrt(f) Square root fabs(f) Floating absolute value ceil(f) Smallest integral value >= f floor(f) Largest integral value <= f sinh(f) Hyperbolic sine cosh(f) Hyperbolic cosine tanh(f) Hyperbolic tangent frexp(y, p) Split into mantissa and exponent ldexp(y, i) Load new exponent CONSOLE I/O Page 102 HI-TECH C USER'S MANUAL getch() Get single character getche() Get single character with echo putch(c) Put single character ungetch(c) Push character back kbhit() Test for key pressed cgets(s) Get line from console cputs(s) Put string to console DATE AND TIME FUNCTIONS time(p) Get current date/time gmtime(p) Get broken down Universal time localtime(p) Get broken down local time asctime(t) Convert broken down time to ascii ctime(p) Convert time to ascii MISCELLANEOUS execl(name, args) Execute another program execv(name, argp) Execute another program spawnl(name, arg, ...) Execute a subprogram spawnv(name, argp) Execute a subprogram system(s) Execute system command atexit(func) Install func to be executed on termination exit(status) Terminate execution _exit(status) Terminate execution immediately getuid() Get user id (CP/M) setuid(uid) Set user id (CP/M) chdir(s) Change directory (MS-DOS) mkdir(s) Create directory (MS-DOS) rmdir(s) Remove directory (MS-DOS) getcwd(drive) Get current working directory (MS-DOS) signal(sig, func) Set trap for interrupt condition brk(addr) Set memory allocation sbrk(incr) Adjust memory allocation malloc(cnt) Dynamic memory allocation free(ptr) Dynamic memory release realloc(ptr, cnt) Dynamic memory reallocation calloc(cnt, size) Dynamic memory allocation zeroed perror(s) Print error message qsort(base, nel, width, func) Quick sort srand(seed) Initialize random number generator rand() Get next random number setjmp(buf) Setup for non-local goto longjmp(buf, val) Non-local goto _getargs(buf, name) Wild card expansion and i/o redirection inp(port) Read port outp(port, data) Write data to port bdos(func, val) Perform bdos call (CP/M) msdos(func, val, val, ...) Perform msdos call msdoscx(func, val, val, ...) Alternate msdos call intdos(ip, op) Execute DOS interrupt HI-TECH C USER'S MANUAL Page 103 intdosx(ip, op, sp) Execute DOS interrupt segread(sp) Get segment register values int86(int, ip, op) Execute software interrupt int86x(int, ip, op, sp) Execute software interrupt bios(n, c) Call bios entry (CP/M) ei() Enable interrupts di() Disable interrupts set_vector(vec, func) Set an interrupt vector assert(e) Run time assertion getenv(s) Get environment string (MS-DOS) ACOS, ASIN, ATAN, ATAN2 SYNOPSIS #include double acos(double f) double asin(double f) double atan(double f) double atan2(double x, double y) DESCRIPTION These functions are the converse of the trignometric functions cos, sin and tan. Acos and asin are undefined for arguments whose absolute value is greater than 1.0. The returned value is in radians, and always in the range -pi/2 to +pi/2, except for _c_o_s(), which returns a value in the range 0 to pi. _A_t_a_n_2() returns the inverse tan of x/y but uses the signs of its arguments to return a value in the range -pi to +pi. SEE ALSO sin, cos, tan Page 104 HI-TECH C USER'S MANUAL ATEXIT SYNOPSIS #include int atexit(void (*func)(void)); DESCRIPTION The _a_t_e_x_i_t() function registers the function pointed to by func, to be called without arguments at normal pro- gram termination. _A_t_e_i_x_t() returns zero if the regis- tration succeeds, nonzero if it fails. On program ter- mination, all functions registered by _a_t_e_x_i_t() are called, in the reverse order of their registration. SEE ALSO exit ASCTIME SYNOPSIS #include char * asctime(time_t t) DESCRIPTION _A_s_c_t_i_m_e() takes the broken down time pointed to by its argument, and returns a 26 character string describing the current date and time in the format Sun Sep 16 01:03:52 1973\n\0 Note the newline at the end of the string. The width of each field in the string is fixed. SEE ALSO ctime, time, gmtime, localtime HI-TECH C USER'S MANUAL Page 105 ASSERT SYNOPSIS #include void assert(int e) DESCRIPTION This macro is used for debugging purposes; the basic method of usage is to place assertions liberally throughout your code at points where correct operation of the code depends upon certain conditions being true initially. An _a_s_s_e_r_t() may be used to ensure at run time that that assumption holds. For example, the fol- lowing statement asserts that the pointer tp is non- null: assert(tp); If at run time the expression evaluates to false, the program will abort with a message identifying the source file and line number of the assertion, and the expression used as an argument to it. A fuller discus- sion of the uses of assert is impossible in limited space, but it is closely linked to methods of proving program correctness. ATOF, ATOI, ATOL SYNOPSIS #include double atof(char * s) int atoi(char * s) #include long atol(char * s) DESCRIPTION These routines convert a decimal number in the argument string s into a double float, integer or long integer respectively. Leading blanks are skipped over. In the case of _a_t_o_f(), the number may be in scientific nota- tion. Page 106 HI-TECH C USER'S MANUAL BDOS (CP/M only) SYNOPSIS #include char bdos(int func, int arg) short bdoshl(int func, int arg)(CP/M-80 only) DESCRIPTION _B_d_o_s() calls the CP/M BDOS with func in register C (CL for CP/M-86) and arg in register DE (DX). The return value is the byte returned by the BDOS in register A (AX). _B_d_o_s_h_l() is the same, except that the return value is the value returned by the BDOS in HL. Con- stant values for the various BDOS function values are defined in cpm.h. These functions should be avoided except in programs which are not intended to be used on an operating sys- tem other than CP/M. The standard I/O routines are to be preferred, since they are portable. SEE ALSO bios, msdos BIOS (CP/M only) SYNOPSIS #includ char bios(int n, int a1, int a2) DESCRIPTION This function will call the n'th bios entry point (cold boot = 0, warm boot = 1, etc.) with register BC (CX) set to the argument a1 and DE (DX) set to the argument a2. The return value is the contents of register A (AX) after the bios call. On CP/M-86, bdos function 50 is used to perform the bios call. This function should not be used unless unavoidable, since it is highly non-portable. There is even no guarantee of portability of bios calls between differing CP/M systems. SEE ALSO bdos HI-TECH C USER'S MANUAL Page 107 CALLOC SYNOPSIS #include char * calloc(size_t cnt, size_t size) DESCRIPTION _C_a_l_l_o_c() attempts to obtain a contiguous block of dynamic memory which will hold cnt objects, each of length size. The block is filled with zeroes. A pointer to the block is returned, or 0 if the memory could not be allocated. SEE ALSO brk, sbrk, malloc, free CGETS, CPUTS SYNOPSIS #include char * cgets(char * s) void cputs(char * s) DESCRIPTION _C_p_u_t_s() will read one line of input from the console into the buffer passed as an argument. It does so by repeated calls to _g_e_t_c_h_e(). _C_p_u_t_s() writes its argu- ment string to the console, outputting carriage returns before each newline in the string. It calls _p_u_t_c_h() repeatedly. SEE ALSO getch, getche, putch Page 108 HI-TECH C USER'S MANUAL CHDIR SYNOPSIS #include int chdir(char * s) DESCRIPTION This function is availble only under MS-DOS. It changes the current working directory to the path name supplied as argument. This path name be be absolute, as in A:\FRED, or relative, as in ..\SOURCES. A return value of -1 indicates that the requested change could not be performed. SEE ALSO mkdir, rmdir, getcwd CHMOD SYNOPSIS #include int chmod(char * name, int ) char * name; int mode; DESCRIPTION This function changes the file attributes (or modes) of the named file. The argument name may be any valid file name. The mode argument may include all bits defined in _s_t_a_t._h except those relating to the type of the file, e.g. S_IFDIR. Note however that not all bits may be changed under all operating systems, e.g. nei- ther DOS nor CP/M permit a file to be made unreadable, thus even if mode does not include S_IREAD the file will still be readable (and _s_t_a_t() will still return S_IREAD in flags). SEE ALSO stat, creat HI-TECH C USER'S MANUAL Page 109 CLOSE SYNOPSIS #include int close(int fd) DESCRIPTION This routine closes the file associated with the file descriptor fd, which will have been previously obtained from a call to _o_p_e_n(). _C_l_o_s_e() returns 0 for a success- ful close, or -1 otherwise. SEE ALSO open, read, write, seek CLRERR, CLREOF SYNOPSIS #include void clrerr(FILE * stream) void clreof(FILE * stream) DESCRIPTION These are macros, defined in stdio.h, which reset the error and end of file flags respectively for the speci- fied stream. They should be used with care; the major valid use is for clearing an EOF status on input from a terminal-like device, where it may be valid to continue to read after having seen an end-of-file indication. SEE ALSO fopen, fclose Page 110 HI-TECH C USER'S MANUAL COS SYNOPSIS #include double cos(double f) DESCRIPTION This function yields the cosine of its argument. SEE ALSO sin, tan, asin, acos, atan COSH, SINH, TANH SYNOPSIS #include double cosh(double f) double sinh(double f) double tanh(double f) DESCRIPTION These functions implement the hyperbolic trig func- tions. HI-TECH C USER'S MANUAL Page 111 CREAT SYNOPSIS #include int creat(char * name, int mode) DESCRIPTION This routine attempts to create the file named by name. If the file exists and is writeable, it will be removed and re-created. The return value is -1 if the create failed, or a small non-negative number if it succeeded. This number is a valuable token which must be used to write to or close the file subsequently. Mode is used to initialize the attributes of the created file. The allowable bits are the same as for _c_h_m_o_d(), but for Unix compatibility it is recommended that a mode of 0666 or 0600 be used. Under CP/M the mode is ignored - the only way to set a files attributes is via the _c_h_m_o_d() function. SEE ALSO open, close, read, write, seek, stat, chmod CTIME SYNOPSIS #include char * ctime(time_t t) DESCRIPTION _C_t_i_m_e() converts the time in seconds pointed to by its argument to a string of the same form as described for asctime. Thus the following program prints the current time and date: #include main() { time_t t; time(&t); printf("%s", ctime(&t)); } Page 112 HI-TECH C USER'S MANUAL SEE ALSO gmtime, localtime, asctime, time DIV, LDIV SYNOPSIS #include div_t div(int numer, int denom) ldiv_t ldiv(long numer, long denom) DESCRIPTION The _d_i_v() function computes the quotient and remainder of the divison of numer by denom. The _d_i_v() function returns a structure of type div_t, containing both the quotient and remainder. _l_d_i_v() is similar to _d_i_v() except it takes arguments of type long and returns a structure of type ldiv_t. The types div_t and ldiv_t are defined in as follows: typedef struct { intquot, rem; } div_t; typedef struct { longquot, rem; } ldiv_t; HI-TECH C USER'S MANUAL Page 113 DI, EI SYNOPSIS void ei(void); void di(void); DESCRIPTION _E_i() and _d_i() enable and disable interrupts respec- tivly. DUP SYNOPSIS #include int dup(int fd) DESCRIPTION Given a file descriptor, such as returned by _o_p_e_n(), this routine will return another file descriptor which will refer to the same open file. -1 is returned if the fd argument is a bad descriptor or does not refer to an open file. SEE ALSO open, close, creat, read, write Page 114 HI-TECH C USER'S MANUAL EXECL, EXECV SYNOPSIS #include int execl(char * name, pname, ...) int execv(char * name, ppname) DESCRIPTION _E_x_e_c_l() and _e_x_e_c_v() load and execute the program speci- fied by the string name. _E_x_e_c_l() takes the arguments for the program from the zero-terminated list of string arguments. _E_x_e_c_v() is passed a pointer to an array of strings. The array must be zero-terminated. If the named program is found and can be read, the call does not return. Thus any return from these routines may be treated as an error. SEE ALSO spawnl, spawnv, system EXIT SYNOPSIS #include void exit(int status) DESCRIPTION This call will close all open files and exit from the program. On CP/M, this means a return to CCP level. Status will be stored in a known place for examination by other programs. This is only useful if the program executing was actually invoked by another program which is trapping warm boots. The status value will be stored on CP/M at 80H. This call will never return. SEE ALSO atexit HI-TECH C USER'S MANUAL Page 115 _EXIT SYNOPSIS #include void _exit(int status) DESCRIPTION This function will cause an immediate exit from the program, without the normal flushing of stdio buffers that is performed by _e_x_i_t(). SEE ALSO exit EXP, LOG, LOG10, POW SYNOPSIS #include double exp(double f) double log(double f) double log10(double f) double pow(double x, y) DESCRIPTION _E_x_p() returns the exponential function of its argument, _l_o_g() the natural logarithm of f, and _l_o_g_1_0() the loga- rithm to base 10. _P_o_w() returns the value of x raised to the y'th power. Page 116 HI-TECH C USER'S MANUAL FABS, CEIL, FLOOR SYNOPSIS #include double fabs(double f) double ceil(double f) double floor(double f) DESCRIPTION These routines return respectively the absolute value of f, the smallest integral value not less than f, and the largest integral value not greater than f. FCLOSE SYNOPSIS #include int fclose(FILE * stream) DESCRIPTION This routine closes the specified i/o stream. Stream should be a token returned by a previous call to _f_o_p_e_n(). NULL is returned on a successful close, EOF otherwise. SEE ALSO fopen, fread, fwrite HI-TECH C USER'S MANUAL Page 117 FEOF, FERROR SYNOPSIS #include feof(FILE * stream) ferror(FILE * stream) DESCRIPTION These macros test the status of the EOF and ERROR bits respectively for the specified stream. Each will be true if the corresponding flag is set. The macros are defined in stdio.h. Stream must be a token returned by a previous _f_o_p_e_n() call. SEE ALSO fopen, fclose FFLUSH SYNOPSIS #include int fflush(FILE * stream) DESCRIPTION _F_f_l_u_s_h() will output to the disk file or other device currently open on the specified stream the contents of the associated buffer. This is typically used for flushing buffered standard output in interactive appli- cations. SEE ALSO fopen, fclose Page 118 HI-TECH C USER'S MANUAL FGETC SYNOPSIS #include int fgetc(FILE * stream) DESCRIPTION _F_g_e_t_c() returns the next character from the input stream. If end-of-file is encountered EOF will be returned instead. It is for this reason that the func- tion is declared as int. The integer EOF is not a valid byte, thus end-of-file is distinguishable from reading a byte of all 1 bits from the file. _F_g_e_t_c() is the non-macro version of _g_e_t_c(). SEE ALSO fopen, fclose, fputc, getc, putc FGETS SYNOPSIS #include char * fgets(char * s, size_t n, char * stream) DESCRIPTION _F_g_e_t_s() places in the buffer s up to n-1 characters from the input stream. If a newline is seen in the input before the correct number of characters is read, then _f_g_e_t_s() will return immediately. The newline will be left in the buffer. The buffer will be null ter- minated in any case. A successful _f_g_e_t_s() will return its first argument; NULL is returned on end-of-file or error. HI-TECH C USER'S MANUAL Page 119 FILENO SYNOPSIS fileno(FILE * stream) DESCRIPTION _F_i_l_e_n_o() is a macro from stdio.h which yields the file descriptor associated with stream. It is mainly used when it is desired to perform some low-level operation on a file opened as a stdio stream. SEE ALSO fopen, fclose, open, close FOPEN SYNOPSIS #include FILE * fopen(char * name, char * mode); DESCRIPTION DESCRIPTION _F_o_p_e_n() attempts to open file for reading or writing (or both) according to the mode string supplied. The mode string is interpreted as follows: r The file is opend for reading if it exists. If the file does not exist the call fails. r+ If the file exists it is opened for reading and writ- ing. If the file does not already exist the call fails. w The file is created if it does not exist, or truncated if it does. It is then opened for writing. w+ The file is created if it does not already exist, or truncated if it does. The file is opened for reading and writing. a The file is created if it does not already exist, and opened for writing. All writes will be dynamically forced to the end of file, thus this mode is known as _a_p_p_e_n_d mode. a+ The file is created if it does not already exist, and opened for reading and writing. All writes to the file will be dynamically forced to the end of the file, i.e. while any portion of the file may be read, all writes Page 120 HI-TECH C USER'S MANUAL will take place at the end of the file and will not overwrite any existing data. Calling _f_s_e_e_k() in an attempt to write at any other place in the file will not be effective. The "b" modifier may be appended to any of the above modes, e.g. "r+b" or "rb+" are equivalent. Adding the "b" modifier will cause the file to be opened in binary rather than ASCII mode. Opening in ASCII mode ensures that text files are read in a manner compatible with the Unix-derived conventions for C programs, i.e. that text files contain lines delimited by newline characters. The special treat- ment of read or written characters varies with the operating system, but includes some or all of the following: NEWLINE (LINE FEED) Converted to carriage return, line feed on output. RETURN Ignored on input, inserted before NEWLINE on output. CTRL-Z Signals EOF on input, appended on fclose on output if necessary on CP/M. Opening a file in binary mode will allow each character to be read just as written, but because the exact size of a file is not known to CP/M, the file may contain more bytes than were written to it. See _o_p_e_n() for a description of what constitutes a file name. When using one of the read/write modes (with a '+' character in the string), although they permits reading and writing on the same stream, it is not possible to arbi- trarily mix input and output calls to the same stream. At any given time a stream opened with a "+" mode will be in either an input or output state. The state may only be changed when the associated buffer is empty, which is only guaranteed immediately after a call to _f_f_l_u_s_h() or one of the file positioning functions _f_s_e_e_k() or _r_e_w_i_n_d(). The buffer will also be empty after encountering EOF while read- ing a binary stream, but it is recommended that an explicit call to _f_f_l_u_s_h() be used to ensure this situation. Thus after reading from a stream you should call _f_f_l_u_s_h() or _f_s_e_e_k() before attempting to write on that stream, and vice versa. SEE ALSO fclose, fgetc, fputc, freopen HI-TECH C USER'S MANUAL Page 121 FPRINTF SYNOPSIS #include fprintf(FILE * stream, char * fmt, ...); vfprintf(FILE * stream, va_list va_arg); DESCRIPTION _F_p_r_i_n_t_f() performs formatted printing on the specified stream. Refer to _p_r_i_n_t_f() for the details of the avail- able formats. _V_f_p_r_i_n_t_f() is similar to _f_p_r_i_n_t_f() but takes a variable argument list pointer rather than a list of arguments. See the description of _v_a__s_t_a_r_t() for more information on variable argument lists. SEE ALSO printf, fscanf, sscanf FPUTC SYNOPSIS #include int fputc(int c, FILE * stream) DESCRIPTION The character c is written to the supplied stream. This is the non-macro version of _p_u_t_c(). The character is returned if it was successfully written, EOF is returned otherwise. Note that "written to the stream" may mean only placing the character in the buffer asso- ciated with the stream. SEE ALSO putc, fgetc, fopen, fflush Page 122 HI-TECH C USER'S MANUAL FPUTS SYNOPSIS #include int fputs(char * s, FILE * stream) DESCRIPTION The null-terminated string s is written to the stream. No newline is appended (cf. _p_u_t_s() ). The error return is EOF. SEE ALSO puts, fgets, fopen, fclose FREAD SYNOPSIS #include int fread(void * buf, size_t size, size_t cnt, FILE * stream) DESCRIPTION Up to cnt objects, each of length size, are read into memory at buf from the stream. The return value is the number of objects read. If none is read, 0 will be returned. Note that a return value less than cnt, but greater than 0, may not represent an error (cf. _f_w_r_i_t_e() ). No word alignment in the stream is assumed or necessary. The read is done via successive _g_e_t_c()'s. SEE ALSO fwrite, fopen, fclose, getc HI-TECH C USER'S MANUAL Page 123 FREE SYNOPSIS #include void free(void * ptr) DESCRIPTION _F_r_e_e() deallocates the block of memory at ptr, which must have been obtained from a call to _m_a_l_l_o_c() or _c_a_l_- _l_o_c(). SEE ALSO malloc, calloc FREOPEN SYNOPSIS #include FILE * freopen(char * name, char * mode, FILE * stream) DESCRIPTION _F_r_e_o_p_e_n() closes the given stream (if open) then re- opens the stream attached to the file described by name. The mode of opening is given by mode. It either returns the stream argument, if successful, or NULL if not. See _f_o_p_e_n() for more information. SEE ALSO fopen, fclose Page 124 HI-TECH C USER'S MANUAL FREXP, LDEXP SYNOPSIS #include double frexp(double f, int * p) double ldexp(double f, int i) DESCRIPTION _F_r_e_x_p() breaks a floating point number into a normal- ized fraction and an integral power of 2. The integer is stored into the int object pointed to by p. Its return value x is in the interval [0.5, 1.0) or zero, and f equals x times 2 raised to the power stored in *p. If f is zero, both parts of the result are zero. _L_d_e_x_p() performs the reverse operation; the integer i is added to the exponent of the floating point f and the resultant value returned. FSCANF SYNOPSIS #include int fscanf(FILE * stream, char * fmt, ...) DESCRIPTION This routine performs formatted input from the speci- fied stream. See _s_c_a_n_f() for a full description of the behaviour of the routine. _V_f_s_c_a_n_f() is similar to _f_s_c_a_n_f() but takes a variable argument list pointer rather than a list of arguments. See the description of _v_a__s_t_a_r_t() for more information on variable argument lists. SEE ALSO scanf, sscanf, fopen, fclose HI-TECH C USER'S MANUAL Page 125 FSEEK SYNOPSIS #include int fseek(FILE * stream, long offs, int wh) DESCRIPTION _F_s_e_e_k() positions the "file pointer" (i.e. a pointer to the next character to be read or written) of the speci- fied stream as follows: _____________________________ |_w_h__|____r_e_s_u_l_t_a_n_t__l_o_c_a_t_i_o_n____| | 0 | offs | | 1 | offs+previous location| | 2 | offs+length of file | |____|_________________________| It should be noted that offs is a signed value. Thus the 3 allowed modes give postioning relative to the beginning of the file, the current file pointer and the end of the file respectively. EOF is returned if the positioning request could not be satisfied. Note how- ever that positioning beyond the end of the file is legal, but will result in an EOF indication if an attempt is made to read data there. It is quite in order to write data beyond the previous end of file. _F_s_e_e_k() correctly accounts for any buffered data. SEE ALSO lseek, fopen, fclose Page 126 HI-TECH C USER'S MANUAL FTELL SYNOPSIS #include long ftell(FILE * stream) DESCRIPTION This function returns the current position of the con- ceptual read/write pointer associated with stream. This is the position relative to the beginning of the file of the next byte to be read from or written to the file. SEE ALSO fseek FWRITE SYNOPSIS #include int fwrite(void * buf, size_t size, size_t cnt, FILE * stream) DESCRIPTION Cnt objects of length size bytes will be written from memory at buf, to the specified stream. The number of whole objects written will be returned, or 0 if none could be written. Any return value not equal to cnt should be treated as an error (cf. _f_r_e_a_d() ). SEE ALSO fread, fopen, fclose HI-TECH C USER'S MANUAL Page 127 _GETARGS SYNOPSIS #include char ** _getargs(char * buf, char * name) extern int _argc_; DESCRIPTION This routine performs I/O redirection (CP/M only) and wild card expansion. Under MS-DOS I/O redirection is performed by the operating system. It is called from startup code to operate on the command line if the -R option is used to the C command, but may also be called by user-written code. If the buf argument is null, it will read lines of text from standard input. If the standard input is a terminal (usually the console) the name argument will be written to the standard error stream as a prompt. If the buf argument is not null, it will be used as the source of the string to be pro- cessed. The returned value is a pointer to an array of strings, exactly as would be pointed to by the argv argument to the main() function. The number of strings in the array may be obtained from the global _argc_. For example, a typical use of this function would be: #include main(argc, argv) char ** argv; { extern char ** _getargs(); extern int _argc_; if(argc == 1) {/* no arguments */ argv = _getargs(0, "myname"); argc = _argc_; } . . . } There will be one string in the array for each word in the buffer processed. Quotes, either single (') or double (") may be used to include white space in "words". If any wild card characters (? or *) appear in a non-quoted word, it will be expanded into a string of words, one for each file matching the word. The usual CP/M conventions are followed for this expansion. On CP/M any occurence of the redirection characters > and < outside quotes will be handled in the following manner: > name will cause standard output to be redirected to the file name. Page 128 HI-TECH C USER'S MANUAL < name will cause standard input to be redirected from the file name. >> name will cause standard output to append to file name. White space is optional between the > or < character and the file name, however it is an error for a redirection character not to be followed by a file name. It is also an error if a file cannot be opened for input or created for output. An append redirection (>>) will create the file if it does not exist. If the source of text to be processed is standard input, several lines may be supplied by ending each line (except the last) with a backslash (\). This serves as a continuation character. Note that the newline follow- ing the backslash is ignored, and not treated as white space. GETC SYNOPSIS #include int getc(FILE * stream) FILE * stream; DESCRIPTION One character is read from the specified stream and returned. EOF will be returned on end-of-file or error. This is the macro version of _f_g_e_t_c(), and is defined in stdio.h. HI-TECH C USER'S MANUAL Page 129 GETCH, GETCHE, UNGETCH, PUTCH SYNOPSIS #include char getch(void) char getche(void) void putch(int c) DESCRIPTION _G_e_t_c_h() reads a single character from the console key- board and returns it without echoing. _G_e_t_c_h_e() is similar but does echo the character typed. _U_n_g_e_t_c_h() will push back one character such that the next call to _g_e_t_c_h() or _g_e_t_c_h_e() will return that character. _P_u_t_c_h() outputs the character c to the console screen, prepending a carriage return if the character is a new- line. SEE ALSO cgets, cputs GETCHAR SYNOPSIS #include int getchar(void) DESCRIPTION _G_e_t_c_h_a_r() is a _g_e_t_c(_s_t_d_i_n) operation. It is a macro defined in stdio.h. Note that under normal cir- cumstances getchar() will NOT return unless a carriage return has been typed on the console. To get a single character immediately from the console, use the routine _g_e_t_c_h(). SEE ALSO getc, fgetc, freopen, fclose Page 130 HI-TECH C USER'S MANUAL GETCWD (MS-DOS only) SYNOPSIS #include char * getcwd(int drive) DESCRIPTION _G_e_t_c_w_d() returns the path name of the current working directory on the specified drive, where drive == 0 represents the current drive, drive == 1 represents A:, drive == 2 represents B: etc. The return value is a pointer to a static area of memory which will be overwritten on the next call to _g_e_t_c_w_d(). SEE ALSO chdir GETENV SYNOPSIS #include char * getenv(char * s) extern char ** environ; DESCRIPTION _G_e_t_e_n_v() will search the vector of environment strings for one matching the argument supplied, and return the value part of that environment string. For example, if the environment contains the string COMSPEC=A:\COMMAND.COM then _g_e_t_e_n_v("_C_O_M_S_P_E_C") will return A:\COMMAND.COM. The global variable environ is a pointer to an array of pointers to environment strings, terminated by a null pointer. This array is initialized at startup time under MS-DOS from the environment pointer supplied when the program was executed. Under CP/M no such environ- ment is supplied, so the first call to _g_e_t_e_n_v() will attempt to open a file in the current user number on the current drive called ENVIRON. This file should con- tain definitions for any environment variables desired to be accessible to the program, e.g. HITECH=0:C: Each variable definition should be on a separate line, consisting of the variable name (conventionally all in upper case) followed without intervening white space by HI-TECH C USER'S MANUAL Page 131 an equal sign ('=') then the value to be assigned to that variable. GETS SYNOPSIS #include char * gets(char * s) DESCRIPTION _G_e_t_s() reads a line from standard input into the buffer at s, deleting the newline (cf. _f_g_e_t_s() ). The buffer is null terminated. It returns its argument, or NULL on end-of-file. SEE ALSO fgets, freopen GETUID (CP/M only) SYNOPSIS #include int getuid(void) DESCRIPTION _G_e_t_u_i_d() returns the current user number. On CP/M, the current user number determines the user number associ- ated with an opened or created file, unless overridden by an explicit user number prefix in the file name. SEE ALSO setuid, open Page 132 HI-TECH C USER'S MANUAL GETW SYNOPSIS #include int getw(FILE * stream) DESCRIPTION _G_e_t_w() returns one word (16 bits for the Z80 and 8086) from the nominated stream. EOF is returned on end-of- file, but since this is a perfectly good word, the _f_e_o_f() macro should be used for testing for end-of- file. When reading the word, no special alignment in the file is necessary, as the read is done by two con- secutive _g_e_t_c()'s. The byte ordering is however unde- fined. The word read should in general have been writ- ten by _p_u_t_w(). SEE ALSO putw, getc, fopen, fclose GMTIME, LOCALTIME SYNOPSIS #include struct tm * gmtime(time_t * t) struct tm * localtime(time_t * t) DESCRIPTION These functions convert the time pointed to by t which is in seconds since 00:00:00 on Jan 1, 1970, into a broken down time stored in a structure as defined in _t_i_m_e._h. _G_m_t_i_m_e() performs a straight conversion, while _l_o_c_a_l_t_i_m_e() takes into account the contents of the glo- bal integer time_zone. This should contain the number of minutes that the local time zone is WESTWARD of Greenwich. Since there is no way under MS-DOS of actu- ally pre-determining this value, by default _l_o_c_a_l_t_i_m_e() will return the same result as _g_m_t_i_m_e(). SEE ALSO ctime, asctime, time HI-TECH C USER'S MANUAL Page 133 INP, OUTP SYNOPSIS char inp(unsigned port) void outp(unsigned, unsigned data) DESCRIPTION These routines read and write bytes to and from I/O ports. _I_n_p() returns the data byte read from the specified port, and _o_u_t_p() outputs the data byte to the specified port. INT86, INT86X, INTDOS, INTDOSX SYNOPSIS #include int int86(int intno, union REGS * inregs, union REGS * outregs) int int86x(int intno, union REGS inregs, union REGS outregs, struct SREGS * segregs) int intdos(union REGS * inregs, union REGS * outregs) int intdosx(union REGS * inregs, union REGS * outregs, struct SREGS * segregs) DESCRIPTION These functions allow calling of software interrupts from C programs. _I_n_t_8_6() and _i_n_t_8_6_x() execute the software interrupt specified by _i_n_t_n_o while _i_n_t_d_o_s() and _i_n_t_d_o_s_x() execute interrupt 21(hex), which is the MS-DOS system call interrupt. The inregs pointer should point to a union containing values for each of the general purpose registers to be set when executing the interrupt, and the values of the registers on return are copied into the union pointed to by outregs. The _x versions of the calls also take a pointer to a union defining the segment register values to be set on execution of the interrupt, though only ES and DS are actually set from this structure. SEE ALSO segread Page 134 HI-TECH C USER'S MANUAL ISALNUM, ISALPHA, ISDIGIT, ISLOWER et. al. SYNOPSIS #include isalnum(char c) isalpha(char c) isascii(char c) iscntrl(char c) isdigit(char c) islower(char c) isprint(char c) isgraph(char c) ispunct(char c) isspace(char c) isupper(char c) char c; DESCRIPTION These macros, defined in ctype.h, test the supplied character for membership in one of several overlapping groups of characters. Note that all except isascii are defined for _c iff _i_s_a_s_c_i_i(_c) is true. isalnum(c) c is alphanumeric isalpha(c) c is in A-Z or a-z isascii(c) c is a 7 bit ascii character iscntrl(c) c is a control character isdigit(c) c is a decimal digit islower(c) c is in a-z isprint(c) c is a printing char isgraph(c) c is a non-space printable character ispunct(c) c is not alphanumeric isspace(c) c is a space, tab or newline isupper(c) c is in A-Z isxdigit(c) c is in 0-9 or a-f or A-F SEE ALSO toupper, tolower, toascii HI-TECH C USER'S MANUAL Page 135 ISATTY SYNOPSIS #include int isatty(int fd) DESCRIPTION This tests the type of the file associated with fd. It returns true if the file is attached to a tty-like dev- ice. This would normally be used for testing if stan- dard input is coming from a file or the console. For testing STDIO streams, use _i_s_a_t_t_y(_f_i_l_e_n_o(_s_t_r_e_a_m)). KBHIT SYNOPSIS #include int kbhit(void) DESCRIPTION This function returns 1 if a character has been pressed on the console keyboard, 0 otherwise. Normally the character would then be read via _g_e_t_c_h(). SEE ALSO getch, getche Page 136 HI-TECH C USER'S MANUAL LONGJMP SYNOPSIS #include void longjmp(jmp_buf buf, int val) DESCRIPTION _L_o_n_g_j_m_p(), in conjunction with _s_e_t_j_m_p(), provides a mechanism for non-local gotos. To use this facility, _s_e_t_j_m_p() should be called with a jmp_buf argument in some outer level function. The call from _s_e_t_j_m_p() will return 0. To return to this level of execution, _l_o_n_j_m_p() may be called with the same jmp_buf argument from an inner level of execution. Note however that the function which called _s_e_t_j_m_p() must still be active when _l_o_n_g_j_m_p() is called. Breach of this rule will cause disaster, due to the use of a stack containing invalid data. The val argument to _l_o_n_g_j_m_p() will be the value apparently returned from the _s_e_t_j_m_p(). This should normally be non-zero, to distinguish it from the genuine _s_e_t_j_m_p() call. For example: #include static jmp_buf jb_err; main() { if(setjmp(jb_err)) { printf("An error occured0); exit(1); } a_func(); } a_func() { if(do_whatever() != 0) longjmp(jb_err, 1); if(do_something_else() != 0) longjmp(jb_err, 2); } The calls to _l_o_n_g_j_m_p() above will never return; rather the call to _s_e_t_j_m_p() will appear to return, but with a return value equal to the argument supplied to _l_o_n_g_j_m_p(). SEE ALSO setjmp HI-TECH C USER'S MANUAL Page 137 LSEEK SYNOPSIS #include long lseek(int fd, long offs, int wh) DESCRIPTION This function operates in an analogous manner to _f_s_e_e_k(), however it does so on unbuffered low-level i/o file descriptors, rather than on STDIO streams. It also returns the resulting pointer location. Thus _l_s_e_e_k(_f_d, _0_L, _1) returns the current pointer location without moving it. -1 is returned on error. SEE ALSO open, close, read, write MALLOC SYNOPSIS #include void * malloc(size_t cnt) DESCRIPTION _M_a_l_l_o_c() attempts to allocate cnt bytes of memory from the "heap", the dynamic memory allocation area. If suc- cessful, it returns a pointer to the block, otherwise 0 is returned. The memory so allocated may be freed with _f_r_e_e(), or changed in size via _r_e_a_l_l_o_c(). _M_a_l_l_o_c() calls _s_b_r_k() to obtain memory, and is in turn called by _c_a_l_l_o_c(). _M_a_l_l_o_c() does not clear the memory it obtains. SEE ALSO calloc, free, realloc Page 138 HI-TECH C USER'S MANUAL MEMSET, MEMCPY, MEMCMP, MEMMOVE SYNOPSIS #include void memset(void s, char c, size_t n) void * memcpy(void * d, void * s, size_t n) int memcmp(void * s1, void * s2, size_t n) void * memmove(void * s1, void * s2, size_t n) void * memchr(void * s, int c, size_t n) DESCRIPTION _M_e_m_s_e_t() initializes n bytes of memory starting at the location pointed to by s with the character c. _M_e_m_c_p_y() copies n bytes of memory starting from the location pointed to by s to the block of memory pointed to by d. The result of copying overlapping blocks is undefined. _M_e_m_c_m_p() compares two blocks of memory, of length n, and returns a signed value similar to _s_t_r_n_c_m_p(). Unlike _s_t_r_n_c_m_p() the comparision does not stop on a null char- acter. The ascii collating sequence is used for the comparision, but the effect of including non-ascii characters in the memory blocks on the sense of the return value is indeterminate. _M_e_m_m_o_v_e() is similar to _m_e_m_c_p_y() except copying of overlapping blocks is han- dled correctly. The _m_e_m_c_h_r() function locates the first occurence of c (converted to unsigned char) in the ini- tial n characters of the object pointed to by s. SEE ALSO strncpy, strncmp, strchr HI-TECH C USER'S MANUAL Page 139 MKDIR, RMDIR SYNOPSIS #include int mkdir(char * s) int rmdir(char * s) DESCRIPTION These functions allow the creation (_m_k_d_i_r()) and dele- tion (_r_m_d_i_r()) of sub-directories under the MS-DOS operating system. The argument s may be an arbitrary pathname, and the return value will be -1 if the crea- tion or removal was unsuccessful. SEE ALSO chdir MSDOS, MSDOSCX SYNOPSIS #include long msdos(int ax, int dx, int cx, int bx, int si, int di) long msdoscx(int ax, int dx, int cx, int bx, int si, int di) DESCRIPTION These functions allow direct access to MS-DOS system calls. The arguments will be placed in the registers implied by their names, while the return value will be the contents of AX and DX (for _m_s_d_o_s()) or the contents of DX and CX (for _m_s_d_o_s_c_x()). Only as many arguments as necessary need be supplied, e.g. if only AH and DX need have specified valued, then only 2 argument would be required. The following piece of code outputs a form-feed to the printer. msdos(0x500, '\f'); Note that the system call number (in this case 5) must be multiplied by 0x100 since MS-DOS expects the call number in AH, the high byte of AX. SEE ALSO intdos, intdosx, int86, int86x Page 140 HI-TECH C USER'S MANUAL OPEN SYNOPSIS #include int open(char * name, int mode) DESCRIPTION _O_p_e_n() is the fundamental means of opening files for reading and writing. The file specified by name is sought, and if found is opened for reading, writing or both. Mode is encoded as follows: Mode Meaning 0 Open for reading only 1 Open for writing only 2 Open for both reading and writing The file must already exist - if it does not, _c_r_e_a_t() should be used to create it. On a successful open, a file descriptor is returned. This is a non-negative integer which may be used to refer to the open file subsequently. If the open fails, -1 is returned. The syntax of a CP/M filename is: [uid:][drive:]name.type where uid is a decimal number 0 to 15, drive is a letter A to P or a to p, name is 1 to 8 characters and type is 0 to 3 characters. Though there are few inherent restrictions on the characters in the name and type, it is recommended that they be restricted to the alphanumerics and standard printing characters. Use of strange characters may cause problems in accessing and/or deleting the file. One or both of uid: and drive: may be omitted; if both are supplied, the uid: must come first. Note that the [ and ] are meta-symbols only. Some examples are: fred.dat file.c 0:xyz.com 0:a:file1.p a:file2. If the uid: is omitted, the file will be sought with uid equal to the current user number, as returned by getuid(). If drive: is omitted, the file will be sought on the currently selected drive. The following special file names are recognized: HI-TECH C USER'S MANUAL Page 141 lst: Accesses the list device - write only pun: Accesses the punch device - write only rdr: Accesses the reader device - read only con: Accesses the system console - read/write File names may be in any case - they are converted to upper case during processing of the name. MS-DOS filenames may be any valid MS-DOS 2.xx filename, e.g. fred.nrk A:\HITECH\STDIO.H The special device names (e.g. CON, LST) are also recognized. These do not require (and should not have) a trailing colon. SEE ALSO close, fopen, fclose, read, write, creat PERROR SYNOPSIS #include void perror(char * s) DESCRIPTION This routine will print on the stderr stream the argu- ment s, followed by a descriptive message detailing the last error returned from an open, close read or write call. Unfortunately CP/M does not provide definitive information relating to the error, except in the case of a random read or write. Thus this routine is of lim- ited usefulness under CP/M. MS-DOS provides much more information however, and use of _p_e_r_r_o_r() after MS-DOS file handling calls will certainly give useful diagnos- tics. SEE ALSO open, close, read, write Page 142 HI-TECH C USER'S MANUAL PRINTF, VPRINTF SYNOPSIS #include int printf(char * fmt, ...) int vprintf(char * fmt, va_list va_arg) DESCRIPTION _P_r_i_n_t_f() is a formatted output routine, operating on stdout. There are corresponding routines operating on a given stream (_f_p_r_i_n_t_f()) or into a string buffer (_s_p_r_i_n_t_f()). _P_r_i_n_t_f() is passed a format string, fol- lowed by a list of zero or more arguments. In the for- mat string are conversion specifications, each of which is used to print out one of the argument list values. Each conversion specification is of the form %m.nc where the percent symbol % introduces a conversion, followed by an optional width specification m. n is an optional precision specification (introduced by the dot) and c is a letter specifying the type of the conversion. A minus sign ('-') preceding m indicates left rather than right adjustment of the converted value in the field. Where the field width is larger than required for the conversion, blank padding is per- formed at the left or right as specified. Where right adjustment of a numeric conversion is specified, and the first digit of m is 0, then padding will be per- formed with zeroes rather than blanks. If the character * is used in place of a decimal con- stant, e.g. in the format %*d, then one integer argu- ment will be taken from the list to provide that value. The types of conversion are: f Floating point - m is the total width and n is the number of digits after the decimal point. If n is omitted it defaults to 6. e Print the corresponding argument in scientific nota- tion. Otherwise similar to f. g Use e or f format, whichever gives maximum precision in minimum width. o x X u d Integer conversion - in radices 8, 16, 10 and 10 respectively. The conversion is signed in the case of d, unsigned otherwise. The precision value is the total number of digits to print, and may be used to force leading zeroes. E.g. %8.4x will print at least 4 hex digits in an 8 wide field. Preceding the key letter with an l indicates that the value argument is a long integer or unsigned value. The letter X prints out hexadecimal numbers using the upper case letters _A-_F rather than _a-_f as would be printed when using x. HI-TECH C USER'S MANUAL Page 143 s Print a string - the value argument is assumed to be a character pointer. At most n characters from the string will be printed, in a field m characters wide. c The argument is assumed to be a single character and is printed literally. Any other characters used as conversion specifications will be printed. Thus %% will produce a single percent sign. Some examples: printf("Total = %4d%%", 23) yields 'Total =23%' printf("Size is %lx" , size) where size is a long, prints size as hexadecimal. printf("Name = %.8s", "a1234567890") yields 'Name = a1234567' printf("xx%*d", 3, 4) yields 'xx 4' Printf returns EOF on error, 0 otherwise. _V_p_r_i_n_t_f() is similar to _p_r_i_n_t_f() but takes a variable argument list pointer rather than a list of arguments. See the description of _v_a__s_t_a_r_t() for more information on vari- able argument lists. SEE ALSO fprintf, sprintf Page 144 HI-TECH C USER'S MANUAL PUTC SYNOPSIS #include int putc(int c, FILE * stream) DESCRIPTION _P_u_t_c() is the macro version of _f_p_u_t_c() and is defined in stdio.h. See _f_p_u_t_c() for a description of its behaviour. SEE ALSO fputc, getc, fopen, fclose PUTCHAR SYNOPSIS #include int putchar(int c) DESCRIPTION _P_u_t_c_h_a_r() is a _p_u_t_c() operation on stdout, defined in stdio.h. SEE ALSO putc, getc, freopen, fclose HI-TECH C USER'S MANUAL Page 145 PUTS SYNOPSIS #include int puts(char * s) DESCRIPTION _P_u_t_s() writes the string s to the stdout stream, appending a newline. The null terminating the string is not copied. EOF is returned on error. SEE ALSO fputs, gets, freopen, fclose PUTW SYNOPSIS #include int putw(int w, FILE * stream) DESCRIPTION _P_u_t_w() copies the word w to the given stream. It returns w, except on error, in which case EOF is returned. Since this is a good integer, _f_e_r_r_o_r() should be used to check for errors. SEE ALSO getw, fopen, fclose Page 146 HI-TECH C USER'S MANUAL QSORT SYNOPSIS #include void qsort(void * base, size_t nel, size_t width, int (*func)()) DESCRIPTION _Q_s_o_r_t() is an implementation of the quicksort algo- rithm. It sorts an array of nel items, each of length width bytes, located contiguously in memory at base. Func is a pointer to a function used by _q_s_o_r_t() to com- pare items. It calls func with pointers to two items to be compared. If the first item is considered to be greater than, equal to or less than the second then _f_u_n_c() should return a value greater than zero, equal to zero or less than zero respectively. static short array[100]; #define SIZE sizeof array/sizeof array[0] a_func(p1, p2) short * p1, * p2; { return *p1 - *p2; } sort_em() { qsort(array, SIZE, sizeof array[0], a_func); } This will sort the array into ascending values. Note the use of sizeof to make the code independent of the size of a short, or the number of elements in the array. HI-TECH C USER'S MANUAL Page 147 RAND SYNOPSIS #include int rand(void) DESCRIPTION _R_a_n_d() is a pseudo-random number generator. It returns an integer in the range 0 to 32767, which changes in a pseudo-random fashion on each call. SEE ALSO srand READ SYNOPSIS #include int read(int fd, void * buf, size_t cnt) DESCRIPTION _R_e_a_d() will read from the file associated with fd up to cnt bytes into a buffer located at buf. It returns the number of bytes actually read. A zero return indicates end-of-file. A negative return indicates error. Fd should have been obtained from a previous call to _o_p_e_n(). It is possible for _r_e_a_d() to return less bytes than requested, e.g. when reading from the console, in which case _r_e_a_d() will read one line of input. SEE ALSO open, close, write Page 148 HI-TECH C USER'S MANUAL REALLOC SYNOPSIS void * realloc(void * ptr, size_t cnt) DESCRIPTION _R_e_a_l_l_o_c() frees the block of memory at ptr, which should have been obtained by a previous call to _m_a_l_- _l_o_c(), _c_a_l_l_o_c() or _r_e_a_l_l_o_c(), then attempts to allocate cnt bytes of dynamic memory, and if successful copies the contents of the block of memory located at ptr into the new block. At most, _r_e_a_l_l_o_c() will copy the number of bytes which were in the old block, but if the new block is smaller, will only copy cnt bytes. If the block could not be allocated, 0 is returned. SEE ALSO malloc, calloc, realloc REMOVE SYNOPSIS #include int remove(char * s) DESCRIPTION _R_e_m_o_v_e() will attempt to remove the file named by the argument s from the directory. A return value of -1 indicates that the attempt failed. SEE ALSO unlink HI-TECH C USER'S MANUAL Page 149 RENAME SYNOPSIS #include int rename(char * name1, char * name2) DESCRIPTION The file named by name1 will be renamed to name2. -1 will be returned if the rename was not successful. Note that renames across user numbers or drives are not per- mitted. SEE ALSO open, close, unlink REWIND SYNOPSIS #include int rewind(FILE * stream) DESCRIPTION This function will attempt to re-position the read/write pointer of the nominated stream to the beginning of the file. A return value of -1 indicates that the attempt was not successful, perhaps because the stream is associated with a non-random access file such as a character device. SEE ALSO fseek, ftell Page 150 HI-TECH C USER'S MANUAL SBRK SYNOPSIS char * sbrk(int incr) DESCRIPTION _S_b_r_k() increments the current highest memory location allocated to the program by incr bytes. It returns a pointer to the previous highest location. Thus _s_b_r_k(_0) returns a pointer to the current highest location, without altering its value. If there is insufficient memory to satisfy the request, -1 is returned. SEE ALSO brk, malloc, calloc, realloc, free SCANF SYNOPSIS #include int scanf(char * fmt, ...) int vscanf(char *, va_list ap); DESCRIPTION _S_c_a_n_f() performs formatted input ("de-editing") from the stdin stream. Similar functions are available for streams in general, and for strings. The function _v_s_c_a_n_f() is similar, but takes a pointer to an argument list rather than a series of additional arguments. This pointer should have been initialized with _v_a__s_t_a_r_t(). The input conversions are performed according to the fmt string; in general a character in the format string must match a character in the input; however a space character in the format string will match zero or more "white space" characters in the input, i.e. spaces, tabs or newlines. A conversion specification takes the form of the character %, optionally followed by an assignment suppression character ('*'), optionally fol- lowed by a numerical maximum field width, followed by a conversion specification character. Each conversion specification, unless it incorporates the assignment suppression character, will assign a value to the vari- able pointed at by the next argument. Thus if there are two conversion specifications in the fmt string, there should be two additional pointer arguments. The conversion characters are as follows: o x d Skip white space, then convert a number in base 8, 16 or 10 radix respectively. If a field width was HI-TECH C USER'S MANUAL Page 151 supplied, take at most that many characters from the input. A leading minus sign will be recognized. f Skip white space, then convert a floating number in either conventional or scientific notation. The field width applies as above. s Skip white space, then copy a maximal length sequence of non-white-space characters. The pointer argument must be a pointer to char. The field width will limit the number of characters copied. The resultant string will be null-terminated. c Copy the next character from the input. The pointer argument is assumed to be a pointer to char. If a field width is specified, then copy that many characters. This differs from the s format in that white space does not terminate the character sequence. The conversion characters o, x, u, d and f may be pre- ceded by an l to indicate that the corresponding pointer argument is a pointer to long or double as appropriate. A preceding h will indicate that the pointer argument is a pointer to short rather than int. _S_c_a_n_f() returns the number of successful conversions; EOF is returned if end-of-file was seen before any conversions were performed. Some examples are: scanf("%d %s", &a, &s) with input "12s" will assign 12 to a, and "s" to s. scanf("%4cd %lf", &c, &f) with input " abcd -3.5" will assign " abc" to c, and -3.5 to f. SEE ALSO fscanf, sscanf, printf, va_arg Page 152 HI-TECH C USER'S MANUAL SEGREAD SYNOPSIS #include int segread(struct SREGS * segregs) DESCRIPTION _S_e_g_r_e_a_d() copies the values of the segment registers into the structure pointed to by segregs. SEE ALSO int86, int86x, intdos, intdosx SETJMP SYNOPSIS #include int setjmp(jmp_buf buf) DESCRIPTION _S_e_t_j_m_p() is used with _l_o_n_g_j_m_p() for non-local gotos. See _l_o_n_g_j_m_p() for further information. SEE ALSO longjmp HI-TECH C USER'S MANUAL Page 153 SETUID (CP/M only) SYNOPSIS #include void setuid(int uid) DESCRIPTION _S_e_t_u_i_d() will set the current user number to uid. Uid should be a number in the range 0-15. SEE ALSO getuid SETVBUF, SETBUF SYNOPSIS #include int setvbuf(FILE * stream, char * buf, int mode, size_t size); void setbuf(FILE * stream, char * buf) DESCRIPTION The _s_e_t_v_b_u_f() function allows the buffering behaviour of a STDIO stream to be altered. It supersedes the function _s_e_t_b_u_f() which is retained for backwards com- patibility. The arguments to _s_e_t_v_b_u_f() are as follows: stream designates the STDIO stream to be affected; buf is a pointer to a buffer which will be used for all subsequent I/O operations on this stream. If buf is null, then the routine will allocate a buffer from the heap if necessary, of size BUFSIZ as defined in . mode may take the values _IONBF, to turn buffering off completely, _IOFBF, for full buffering, or _IOLBF for line buffering. Full buffering means that the associated buffer will only be flushed when full, while line buffering means that the buffer will be flushed at the end of each line or when input is requested from another STDIO stream. size is the size of the buffer supplied. For example: setvbuf(stdout, my_buf, _IOLBF, sizeof my_buf); If a buffer is supplied by the caller, that buffer will remain associated with that stream even over_f_c_l_o_s_e(), _f_o_p_e_n() calls until another _s_e_t_v_b_u_f() changes it. Page 154 HI-TECH C USER'S MANUAL SEE ALSO fopen, freopen, fclose SET_VECTOR SYNOPSIS #include typedef interrupt void (*isr)(); isr set_vector(isr * vector, isr func); DESCRIPTION This routine allows an interrupt vector to be initial- ized. The first argument should be the address of the interrupt vector (not the vector number but the actual address) cast to a pointer to _i_s_r, which is a typedef'd pointer to an interrupt function. The second argument should be the function which you want the interrupt vector to point to. This must be declared using the _i_n_t_e_r_r_u_p_t type qualifier. The return value of _s_e_t__v_e_c_t_o_r() is the previous contents of the vector. SEE ALSO di(), ei() HI-TECH C USER'S MANUAL Page 155 SIGNAL SYNOPSIS #include void (* signal)(int sig, void (*func)()); DESCRIPTION _S_i_g_n_a_l() provides a mechanism for catching control-C's (ctrl-BREAK for MS-DOS) typed on the console during I/O. Under CP/M the console is polled whenever an I/O call is performed, while for MS-DOS the polling depends on the setting of the BREAK command. If a control-C is detected certain action will be performed. The default action is to exit summarily; this may be modified with _s_i_g_n_a_l(). The sig argument to signal may at the present time be only SIGINT, signifying an interrupt condition. The func argument may be one of SIG_DFL, representing the default action, SIG_IGN, to ignore control-C's com- pletely, or the address of a function which will be called with one argument, the number of the signal caught, when a control-C is seen. As the only signal supported is SIGINT, this will always be the value of the argument to the called function. SEE ALSO exit SIN SYNOPSIS #include double sin(double f); DESCRIPTION This function returns the sine function of its argu- ment. SEE ALSO cos, tan, asin, acos, atan Page 156 HI-TECH C USER'S MANUAL SPAWNL, SPAWNV, SPAWNVE SYNOPSIS int spawnl(char * n, char * argv0, ...); int spawnv(cahr * n, char ** v) int spawnve(char * n, char ** v, char ** e) DESCRIPTION These functions will load and execute a sub-program, named by the argument n. The calling conventions are similar to the functions _e_x_e_c_l() and _e_x_e_c_v(), the difference being that the spawn functions return to the calling program after termination of the sub-program, while the exec functions return only if the program could not be executed. _S_p_a_w_n_v_e() takes an environment list in the same format as the argument list which will be supplied to the executed program as its environment. SEE ALSO execl, execv SPRINTF SYNOPSIS #include int sprintf(char * buf, char * fmt, ...); int vsprintf(char * buf, char * fmt, va_list ap); DESCRIPTION _S_p_r_i_n_t_f() operates in a similar fashion to _p_r_i_n_t_f(), except that instead of placing the converted output on the stdout stream, the characters are placed in the buffer at buf. The resultant string will be null- terminated, and the number of characters in the buffer will be returned. _V_s_p_r_i_n_t_f takes an argument pointer rather than a list of arguments. SEE ALSO printf, fprintf, sscanf HI-TECH C USER'S MANUAL Page 157 SQRT SYNOPSIS #include double sqrt(double f) DESCRIPTION _S_q_r_t() implements a square root function using Newton's approximation. SEE ALSO exp SSCANF SYNOPSIS #include int sscanf(char * buf, char * fmt, ...); int vsscanf(char * buf, char * fmt, va_list ap); DESCRIPTION _S_s_c_a_n_f() operates in a similar manner to _s_c_a_n_f(), except that instead of the conversions being taken from stdin, they are taken from the string at buf. SEE ALSO scanf, fscanf, sprintf Page 158 HI-TECH C USER'S MANUAL SRAND SYNOPSIS #include void srand(int seed) DESCRIPTION _S_r_a_n_d() initializes the random number generator accessed by _r_a_n_d() with the given seed. This provides a mechanism for varying the starting point of the pseudo-random sequence yielded by _r_a_n_d(). On the z80, a good place to get a truly random seed is from the refresh register. Otherwise timing a response from the console will do. SEE ALSO rand STAT SYNOPSIS #include int stat(char * name, struct stat * statbuf) DESCRIPTION This routine returns information about the file by name. The information returned is operating system dependent, but may include file attributes (e.g. read only), file size in bytes, and file modification and/or access times. The argument name should be the name of the file, and may include path names under DOS, user numbers under CP/M, etc. The argument statbuf should be the address of a structure as defined in _s_t_a_t._h which will be filled in with the information about the file. The structure of _s_t_r_u_c_t _s_t_a_t is as follows: struct stat { short st_mode; /* flags */ long st_atime; /* access time */ long st_mtime; /* modification time */ long st_size; /* file size */ }; The access and modification times (under DOS these are both set to the modification time) are in seconds since 00:00:00 Jan 1 1970. The function _c_t_i_m_e() may be used to convert this to a readable HI-TECH C USER'S MANUAL Page 159 value. The file size is self explanatory. The flag bits are as follows: Flag Meaning ____________________________________ S_IFMT mask for file type S_IFDIR file is a directory S_IFREG file is a regular file S_IREAD file is readable S_IWRITE file is writeable S_IEXEC file is executable S_HIDDEN file is hidden S_SYSTEM file is marked system S_ARCHIVE file has been written to _S_t_a_t returns 0 on success, -1 on failure, e.g. if the file could not be found. SEE ALSO ctime, creat, chmod STRCAT, STRCMP, STRCPY, STRLEN et. al. SYNOPSIS #include char * strcat(char * s1, char * s2); int strcmp(char * s1, char * s2); char * strcpy(char * s1, char * s2); int strlen(char * s); char * strncat(char * s1, char * s2, size_t n); int strncmp(char * s1, char * s2, size_t n); char * strncpy(char * s1, char * s2, size_t n); DESCRIPTION These functions provide operations on null-terminated strings. _S_t_r_c_a_t() appends the string s2 to the end of the string s1. The string at s1 will be null ter- minated. Needless to say the buffer at s1 must be big enough. _S_t_r_c_m_p() compares the two strings and returns a number greater than 0, 0 or a number less than 0 according to whether s1 is greater than, equal to or less than s2. The comparision is via the ascii collat- ing order, with the first character the most signifi- cant. _S_t_r_c_p_y() copies s2 into the buffer at s1, null terminating it. _S_t_r_l_e_n() returns the length of s1, not including the terminating null. _S_t_r_n_c_a_t(), _s_t_r_n_c_m_p() and _s_t_r_n_c_p_y() will catenate, compare and copy s2 and s1 in the same manner as their similarly named counter- parts above, but involving at most n characters. For _s_t_r_n_c_p_y(), the resulting string may not be null ter- minated. Page 160 HI-TECH C USER'S MANUAL STRCHR, STRRCHR SYNOPSIS #include char * strchr(char * s, int c) char * strrchr(char * s, int c) DESCRIPTION These functions locate an instance of the character c in the string s. In the case of _s_t_r_c_h_r() a pointer will be returned to the first instance of the character found be searching from the beginning of the string, while _s_t_r_r_c_h_r() searches backwards from the end of the string. A null pointer is returned if the character does not exist in the string. SEE ALSO SYSTEM SYNOPSIS #include int system(char * s) DESCRIPTION When executed under MS-DOS _s_y_s_t_e_m() will pass the argu- ment string to the command processor, located via the environment string COMSPEC, for execution. The exit status of the command processor will be returned from the call to system(). For example, to set the baud rate on the serial port on an MS-DOS machine: system("MODE COM1:96,N,8,1,P"); This function will not work on CP/M-86 since it does not have an invokable command interpreter. Under Con- current CP/M the CLI system call is used. SEE ALSO spawnl, spawnv HI-TECH C USER'S MANUAL Page 161 TAN SYNOPSIS #include double tan(double f); DESCRIPTION This is the tangent function. SEE ALSO sin, cos, asin, acos, atan TIME SYNOPSIS #include time_t time(time_t * t) DESCRIPTION This function returns the current time in seconds since 00:00:00 on Jan 1, 1970. If the argument t is non- null, the same value is stored into the object pointed to by t. The accuracy of this function is naturally dependent on the operating system having the correct time. This function does not work under CP/M-86 or CP/M 2.2 but does work under Concurrent-CP/M and CP/M+. SEE ALSO ctime, gmtime, localtime, asctime Page 162 HI-TECH C USER'S MANUAL TOUPPER, TOLOWER, TOASCII SYNOPSIS #include char toupper(int c); char tolower(int c); char toascii(int c); char c; DESCRIPTION _T_o_u_p_p_e_r() converts its lower case alphabetic argument to upper case, _t_o_l_o_w_e_r() performs the reverse conver- sion, and _t_o_a_s_c_i_i() returns a result that is guaranteed in the range 0-0177. _T_o_u_p_p_e_r() and _t_o_l_o_w_e_r return their arguments if it is not an alphabetic character. SEE ALSO islower, isupper, isascii et. al. UNGETC SYNOPSIS #include int ungetc(int c, FILE * stream) DESCRIPTION _U_n_g_e_t_c() will attempt to push back the character c onto the named stream, such that a subsequent _g_e_t_c() opera- tion will return the character. At most one level of pushback will be allowed, and if the stream is not buf- fered, even this may not be possible. EOF is returned if the _u_n_g_e_t_c() could not be performed. SEE ALSO getc HI-TECH C USER'S MANUAL Page 163 UNLINK SYNOPSIS int unlink(char * name) DESCRIPTION _U_n_l_i_n_k() will remove (delete) the named file, that is erase the file from its directory. See _o_p_e_n() for a description of the file name construction. Zero will be returned if successful, -1 if the file did not exist or it could not be removed. SEE ALSO open, close, rename, remove VA_START, VA_ARG, VA_END SYNOPSIS #include void va_start(va_list ap, _p_a_r_m_N); _t_y_p_e va_arg(ap, _t_y_p_e); void va_end(va_list ap); DESCRIPTION These macros are provided to give access in a portable way to parameters to a function represented in a proto- type by the ellipsis symbol (...), where type and number of arguments supplied to the function are not known at compile time. The rightmost parameter to the function (shown as _p_a_r_m_N) plays an important role in these macros, as it is the starting point for access to further parameters. In a function taking variable numbers of arguments, a variable of type va_list should be declared, then the macro va_start invoked with that variable and the name of _p_a_r_m_N. This will initialize the variable to allow subsequent calls of the macro va_arg to access successive parameters. Each call to va_arg requires two arguments; the variable previously defined and a type name which is the type that the next parameter is expected to be. Note that any arguments thus accessed will have been widened by the default conventions to _i_n_t, _u_n_s_i_g_n_e_d _i_n_t or _d_o_u_b_l_e. For exam- ple if a character argument has been passed, it should be accessed by va_arg(ap, int) since the char will have been widened to _i_n_t. An example is given below of a function taking one integer parameter, followed by a number of other parameters. In this example the func- tion expects the subsequent parameters to be pointers to char, but note that the compiler is not aware of this, and it is the programmers responsibility to Page 164 HI-TECH C USER'S MANUAL ensure that correct arguments are supplied. #include prf(int n, ...) { va_list ap; va_start(ap, n); while(n--) puts(va_arg(ap, char *)); va_end(ap); } WRITE SYNOPSIS #include int write(int fd, void * buf, size_t cnt) DESCRIPTION _W_r_i_t_e() will write from the buffer at buf up to cnt bytes to the file associated with the file descriptor fd. The number of bytes actually written will be returned. EOF or a value less than cnt will be returned on error. In any case, any return value not equal to cnt should be treated as an error (cf. _r_e_a_d() ). SEE ALSO open, close, read HI-TECH C USER'S MANUAL Page 165 INDEX 8086 70 CP/M 26,106,131,155 absolute value 116 CP/M-80 compiler 2 acos() 103 cputs() 107 address creat() 111 link 73 creating a library 76 load 73 CREF 83 ANSI Standard 13,17 cross compilers 3 array cross reference 36,83 dimension 16 ctime() 111 index 16 ctrl-Z 26,120 size 16 date and time 104 ASCII 26 debugging 10,105 asctime() 104 device name as file 23 asin() 103 device assembler as file 141 in C programs 20 di() 113 assert() 105 directory 108,139 atan() 103 current 130 atan2() 103 disk changing on floppy disk Atari ST 3 systems 3 atexit() 104 disk space 33 atof() 105 div() 112 atoi() 105 div_t 112 atol() 105 dup() 113 bdos() 106 editor 3,33 binary output file 8 ei() 113 bios() 106 entering long commands 7 braces Enumerated Types 16 omission of 16 environment 130 byte ordering 21 error message: C command 3,7 Can't generate code 33 C reference books 2 Error closing file 33 calloc() 107 No room 33 carriage return 26,120 out of memory 33 ceil() 116 Undefined symbol 33 cgets() 107 Write error 33 change file attributes 108 error messages 23,33 character testing 134 format of 23 chdir() 108 LIBR 78 checksum 79,80 list of 23,85 chmod() 108 redirection of 23 class name 70 execl() 114 close() 109 executing a sub-program 156 clreof() 109 executing system commands clrerr() 109 160 command line 7,12,77,160 execution profiling 10 Compatibility 25 execv() 114 compiler driver 3 exit() 114 Compiler Structure 5 exp() 115 console I/O 107,129,135 exponentional functions 115 control-C handling 155 Extern Declarations 30 converting ascii to binary fabs() 116 105 fclose() 116 cos() 110 feof() 117 cosh() 110 ferror() 117 Page 166 HI-TECH C USER'S MANUAL fflush() 117 getw() 132 fgetc() 118 global variables 30 fgets() 118 gmtime() 132 FILE 99 hex output file 8 file descriptor 27,111,119 I/O redirection 127 duplicating 113 I/O FILE pointer 27 ASCII 26 file Binary 26 access time 158 standard 25,99 attributes 108,158 in-line assembler 20 closing a 109,116 Initialization Syntax 16 creating a 111 initializer 16 deleting a 148,163 inp() 133 flushing buffer to a 117 int86() 133 information about a 158 int86x() 133 modification time 158 intdos() 133 opening a 119,123,140 intdosx() 133 random access to a Intel hex format 79 125,137 interrupt 133 reading from a 122,147 interrupt handling 155 renaming a 149 interrupt vector size 158 setting 154 type of a 135 isalnul() 134 writing to a 126,164 isalnum() 134 fileno() 119 isalpha() 134 floating point isascii() 134 library 27 isatty() 135 options required to use iscntrl() 134 4 isdigit() 134 floor() 116 isgraph() 134 fopen() 26,119 islower() 134 formatted input 124,150 ispunct() 134 formatted printing 121,142 isspace() 134 fprintf() 121 isupper() 134 fputc() 121 kbhit() 135 fputs() 122 Kernighan and Ritchie 2,16 fread() 122 large model 70,80 free() 123 ldexp() 124 freopen() 123 ldiv() 112 frexp() 124 LIBR 75 fscanf() 124 librarian 75 fseek() 125 libraries 7 ftell() 126 library manager 75 function parameter 163 library ordering 77 function library declaration 17 creating 76 large 33 floating point 33 parameters 17 ordering 33 prototype 17,163 line number symbols 10 fwrite() 126 linker 69 getc() 128 LINT 16 getch() 129 localtime 132 getchar() 25,129 log() 115 getche() 129 log10() 115 getcwd() 130 logarithmic functions 115 getenv() 130 long 30 gets() 131 longjmp() 136 getuid() 131 lseek() 137 HI-TECH C USER'S MANUAL Page 167 Machine Dependencies 21 pack pragma 20 macros parameter predefined 21 type 17 malloc() 137 perror() 141 Member Names 13,29 portable code 21 memcmp() 138 pow() 115 memcpy() 138 pragma 20,21 memory allocation printf 33 107,148,150 printf() 142 releasing 123 program execution 156 memory model 31 psect memory requirements 2 linking 69 memset() 138 local 70 mkdir() 139 putc() 144 Motorola hex format 80 putch() 129 MS-DOS 108,133,139,155 putchar() 144 msdos() 139 puts() 145 msdoscx() 139 putw() 145 multiple definitions 30 qsort() 146 newline 26 rand() 147 Newton's approximation 157 random numbers 147,158 non-local goto 136,152 read() 147 objtohex 72,79 realloc() 148 open() 140 relocation 69 Operating Details 7 remove() 148 options 7 rename() 149 -1 10 return 26,120 -11 11 rewind() 149 -2 11 rmdir() 139 -6301 11 S format hex 80 -A 8 sbrk() 150 -B 9 scanf 33 -C 7 scanf() 150 -CPM 7 segment registers 152 -CR 7 segread() 152 -D 8 self relocation 72 -E 10 setbuf() 153 -F 8 setjmp() 152 -G 10 setuid() 153 -H 10 setvbuf() 153 -I 8 set_vector() 154 -LF 4,27,33 shift -M 8 signed 14 -O 8 unsigned 14 -Ooutfile 8 short 21,30 -P 10 signal() 155 -R 8 sin() 155 -S 7 sinh() 110 -U 8 size of data types 21 -V 3,8 sorting 146 -W 10 source file naming 3 -X 8 source level debugging 10 -Z 10 spawnl() 156 linker 71 spawnv() 156 outp() 133 spawnve() 156 pack 21 Specific Features 13 sprintf() 156 sqrt() 157 Page 168 HI-TECH C USER'S MANUAL square root function 157 Unsigned Types 14 srand() 158 user ID 131,153 sscanf() 157 V3.09 2 Standard Libraries 25 va_arg 18,163 Standard Library Functions va_end 163 99 va_start 163 stat() 158 void 18 stdarg.h 18,163 Pointer to 18 STDIO 25,27,99 warning level 10 storage allocator 18 warning messages strcat() 159 suppressing 10 strchr() 160 wild card expansion 127 strcmp() 159 Wordstar 33 strcpy() 159 write() 164 stream 27,99 Z180 MMU 68 string manipulation 159 Bank Base Register 68 strlen() 159 BBR 68 strncat() 159 CBAR 68 strncmp() 159 CBR 68 strncpy() 159 Common Base Register 68 strrchr() 160 Common/Bank Area Regis- Structure Operations 15 ter 68 structure packing 20 Z180 Registers 68 structures ASCI 68 as function argument 15 Bank Base Register 68 assignment 15 BBR 68 functions returning 15 BCR0H 68 Stylistic Considerations 29 BCR0L 68 symbol file 10,80 BCR1H 68 symbols BCR1L 68 cross reference 83 CBAR 68 global 70,76 CBR 68 System Requirements 2 CNTLA0 68 system() 160 CNTLA1 68 tan() 161 CNTLB0 68 tanh() 110 CNTLB1 68 temporary files 4 CNTR 68 text editor 3 Common Base Register 68 time and date 104 Common/Bank Area Regis- time() 161 ter 68 toascii() 162 CSI/0 68 tolower() 162 DAR0B 68 toupper() 162 DAR0H 68 trigonometric functions DAR0L 68 103,110 DCNTL 68 hyperbolic 110 DMA 68 Type Checking 13 DMA Byte Count 68 type qualifiers 19 DMA Desitination Address typecast 13 68 typecasting 18 DMA Mode Register 68 ungetc() 162 DMA Source Address 68 ungetch() 129 DMA Status Register 68 Unix DMODE 68 C compiler 16 DSTAT 68 V7 25 FRC 68 unlink() 163 Free Running Counter 68 unsigned 23 IAR1H 68 unsigned char 21 IAR1L 68 HI-TECH C USER'S MANUAL Page 169 ICR 68 INC 55 IL 68 IND 55 Interrupt Vector Regis- INDR 56 ter 68 INI 56 ITC 68 INIR 56 MAR1B 68 JP 56 MAR1H 68 JR 56 MAR1L 68 LD 56,57,58,59 MMU 68 LDD 59 OMCR 68 LDDR 59 RCR 68 LDI 59 Refresh Control Register LDIR 59 68 MLT 59 RLDR0H 68 NEG 59 RLDR0L 68 NOP 59 RLDR1H 68 OR 59,60 RLDR1L 68 OTDM 61 SAR0B 68 OTDMR 60 SAR0H 68 OTDR 60 SAR0L 68 OTIM 61 STAT0 68 OTIMR 60 STAT1 68 OTIR 60 TCR 68 OUT 60 TDR0 68 OUT0 60 TDR1 68 OUTD 60 TIMER 0 68 OUTI 61 TIMER 1 68 POP 61 TMDR0H 68 PUSH 61 TMDR0L 68 RES 61,62,63 TMDR1H 68 RET 63 TMDR1L 68 RETI 63 TRDR 68 RETN 63 TSR0 68 RL 63 TSR1 68 RLA 63 Z80 Instructions 50 RLC 63 ADC 51 RLCA 63 ADD 51 RLD 63 AND 51 RR 63,64 BIT 52,53 RRA 64 CALL 53 RRC 64 CCF 53 RRCA 64 CP 53,54 RRD 64 CPD 54 RST 64 CPDR 54 SBC 64 CPI 54 SCF 64 CPIR 54 SET 64,65,66 CPL 54 SLA 66 DAA 54 SLP 66 DEC 54 SRA 66 DI 54 SRL 67 DJNZ 54 SUB 67 EI 54 TST 67 EX 55 TSTIO 67 EXX 55 XOR 67 HALT 55 Z80 pseudo ops IM 55 IRP 47 IN 55 IRPC 47 IN0 55 ZAS directives 48 Page 170 HI-TECH C USER'S MANUAL title 48 operators 38 ZAS options program sections 39 -J 35 PSECT 43 -L 36 psects 39,43 -N 35 pseudo ops 40 -O 36 relocatable object code -U 35 39 -W 36 temporary labels 37 ZAS psect flags Z180 35 ABS 43 Zilog 35 GLOBAL 43 _exit() 115 LOCAL 43 _getargs() 127 OVRLD 43 PURE 43 ZAS pseudo ops 40 COND 42 DB 40 DEFB 40 DEFF 41 DEFL 41 DEFM 42 DEFS 41 DEFW 41 ELSE 42 END 42 ENDC 42 ENDM 44 EQU 41 GLOBAL 43 IF 42 LOCAL 45 MACRO 44 ORG 44 PSECT 43 REPT 46 ZAS 64180 35 arithmetic overflow 35 binary constants 37 character constants 38 condition codes 48 conditional assembly 42 constants 37 directives 48 extended condition codes 48 external symbols 35 floating point constants 38 hexadecimal constants 37 jump optimization 35 jumps 35 labels 36 listing 36 macros 44 mnemonics 35 octal constants 37 opcode constants 38