Aztec_C_CPM_1.06_User_Manual_Mar84 Aztec C CPM 1.06 User Manual Mar84
Aztec_C_CPM_1.06_User_Manual_Mar84 manual pdf -FilePursuit
Aztec_C_CPM_1.06_User_Manual_Mar84 Aztec_C_CPM_1.06_User_Manual_Mar84
User Manual: Aztec_C_CPM_1.06_User_Manual_Mar84
Open the PDF directly: View PDF .
Page Count: 242
Download | |
Open PDF In Browser | View PDF |
SOFTWARE SYSTEMS o o o o o o o • I • I • Ie i er AZTEC C II User Manual Release 1.06 March 1984 Copyright (C) 1984 by Manx Software Systems, Inc. All Rights Reserved Worldwide Distribut:ed by: Manx software Systems P. O. Box 55 Shrewsbury, N. J. 07701 201-780-4004 SOFTWARE LlCERSE Aztec C II, Manx AS, and Manx LN are licensed software products. Manx Software Systems reserves all distribution rights to these products. Use of these products is prohibited without a valid license agreement. The license agreement is provided with each package. Before using any of these products the license agreement must be signed and mailed to: Manx Software Systems P. O. Box 55 Shrewsbury, N. J 07701 The license agreement limits use of these products to one machine and explicitly limits duplication of the products to no more than two copies whose sole purpose will be for backup. Any uses of these products that might lead to the creation of or distribution of unauthorized copies of these products will be a breach of the licensing agreement and Manx Software Systems will excercise its right to reclaim the original and any and all copies derived in whole or in part from first or later generations and to pursue any appropriate legal actions. Software that is developed with Aztec C II, Manx AS, or Manx LN can be run on machines that are not licensed for these products as long as no part of the Aztec C II software, libraries, supporting files, or documentation is distributed with or required by the software. In the latter case a licensed copy of the appropriate Aztec C software is required for each machine utilizing the software. There is no licensing required for executable modules that include library routines. The only restriction is that neither the source, the libraries themselves, or the relocatable object of the library routines can be distributed. COPYRIGHT Copyright (C) 1981, 1982, 1984 by Manx Software Systems. All rights reserved. No part of this publication may be reproduced, transmitted, transcribed, stored in a retrieval system, or translated into any language or computer language, in any form or by any means, electronic, mechanical, magnetic, optical, chemical, manual or otherwise, without prior written permission of Manx Software Systems, Box 55, Shrewsbury, N. J. 07701. DISCLAIMER Manx Software Systems makes no representations or warranties with respect to the contents hereof and specifically disclaims any implied warranties of merchantability or fitness for any particular purpose. Manx Software Systems reserves the right to revise this publication and to make changes from time to time in the content hereof without obligation of Manx Software Systems to notify any person of such revision or changes. TRADEMARKS Aztec C II, Manx AS, and Manx LN are trademarks of Manx Software Systems. Credit is given to Digital Research of California for its trademarks: CP/M, MP/M, and RMAC. Credit is given to Microsoft of Washington for its trademarks: MACRO-BO, and LINK80. Any references to MBO and LBO also refer to the appropriate trademarked software packages. UNIX is a trademark of Bell Laboratories. Contents section title abbreviation I. Overview. II. Tutorial Introduction. · . . . . . . . . . . . . . . . . . . . . . . . . . . . . . t u t • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • OV III. Aztec C II Compiler •.•.•••.•...•.••.•..•••••••.•••.•• cc IV. Aztec AS Assembler. .as V. Aztec LN Linker •••• .In VI. Libutil the Library Utility ••...•.•..•...••••.• lbutl VII. Library Functions ••••. · .......................... . • .lib VIII.Technical Information. .tech IX. o data formats .•.••.•• .tech.l o floating point support •.•... .tech.3 o assembly language interface. .tech.7 Software Extensions. . .•...• ext o the tiny library. .ext.l o a fast linker ...• .ext.3 o interface with other assemblers. .ext.4 o Manx overlay support •••.•..•••••.•.•. ext.5 o generating ROMable code. .ext.12 o utility programs X. CNM (object file profiler) .ext.17 SQZ (library squeeze) ••••• .ext.20 SIDSYM (debugging support) .ext.2l Style ••••••• •••••.••••.•• style XI. Error Messages •••••••••••••••••••••••••••.•••••••••• err o compiler error codes ••••••••••••••••• err.l o fatal error messages •••••••••••••••• err.32 o errors during assembly. .err.34 o linker errors ••••••••••••••••••••••. err.36 SECTION I Overview Aztec C OVERVIEW This manual was written to provide the shortest path between any two points. The table of contents provides a straightforward outline of the text. This section explains in more detail what is discussed in each section of the manual. If you are new to compilers and the C language, you will want to read section II, since it gives a more detailed introduction to the package as a whole. Each of the subsequent sections explores a new topic. Sections III - VI describe the principal programs available with Aztec C and give complete, specific information on their use. Section VII shows which functions are available in the standard libraries, and how they can be called from a C program. The section has a short preface which explains how to use the summaries effectively. For all users, the library section is a handy reference and source of examples. Miscellaneous topics are treated in section VIII. The summary of data formats explains how C data types are handled by the compiler. It is worth reading this section even if you are just learning C, since it offers insight into the differences between the data types available to you. The guide to the assembly language interface demonstrates how you can use your own assembly code with the Aztec compiler. However, it also provides a closer look at function calls in C, at the assembly language level. Section IX describes the extensions which are available for the Aztec C development system. The introduction specifies which programs and features are included in the standard package, and which can be purchased separately. Section X provides a closer look at the C language and this package. It will be most useful if you are just learning the language, as it clarifies the problems that are frequently encountered by beginners-- and non-beginners as well. The final section lists and explains the error messages which are generated by the Aztec software. Although there is always a new way to produce a given message, this section should start you looking in the right direction for a cause. It is conveniently located in the rear of the manual for easy access. copyright (c) 1984 by Manx Software Systems, Inc. oV.l SECTION II A Tuto'rial Introduction Aztec C TUTORIAL I ntrod uction The software provided by Hanx is comprised of four indispensible tools. They are called the compiler, assembler, linker and librarian. These are generic names. The Manx compiler is known as Aztec C II (see two). The assembler, designed with crI in mind, is called AS. The Aztec linker is called simply LN. Another word for "linker" is "link editor". As its name might imply, LN is what ties together the process of developing a program. The development of larger applications is made easier with the help of a librarian such as LIBUTIL. It will help to manage your files when a program grows very large. Just what these programs are and how they are used is the subject of the next several sections. However, before you move on to the complete descriptions, you may want to read the more general section which follows. Through it, you will become acquainted with the structure of the package and how to use the tools it makes available. Getting Started Manx has sent you one or more diskettes, or floppy disks. Each diskette is labeled with the name of the product, the version number and a fraction indicating which member of the set it is. If the diskette is reversible (a flippy), be sure to note that both sides may be used, in which case each side will have a different label. The diskettes in your package are not bootable. use them, you will first have to boot CP/M. In order to Checking the Files You should take a directory listing of your disks and check the results against the list given in the release document enclosed with your package. If at any time you believe that a Manx file is corrupted or bad, you can test it using the program called CRC.COM. For a given file or for an entire disk, the CRC (cyclic redundancy check) program will compute a unique hexadecimal number. When a file is altered in any way, its CRC number must change also. In order to test the entire disk, simply run the program by typing in "crc" to the CP/M prompt. The general form of the command is: crc filename Copyright (c) 1984 by Manx Software Systems, Inc. tut.l Aztec C TUTORIAL This will run the CRC check on the given file. also be specified: A drive can crc a:exmpl.c The CRC numbers of the files supplied with the package are listed in the release document. If a different value is generated by the eRC program for a file, the file is IIbad A CRC number remains the same only until the file is changed. li • Back up the Disks! Before going too far with your disks, it is important that you back them up. Backup disks are nothing more than copies of the original disks which insure against accidental erasure of valuable files. The CP/M copy utility is generally adequate for backing up your distribution disks. Any further considerations are explained in the release document accompanying this manual. The release document should be read over at this point. It is the real introduction to your version of the package. It explains the changes that have been made since the last release as well as any problems reported by our users. When you have made your backup disks, store the originals away in a safe place-- but not somewhere so safe that you can It find them later on. You should also copy the version number of the package from the label of your distribution disks. This version number may differ from that which appears when a particular program is run. The Working Disk It is a good idea to create a working disk, that is, a disk which contains all the files you will need right away. A working disk will eliminate all the extraneous files which appear on the originals. For now, you will need the following files: cc.com, as.com, In.com, c.lib and exmpl.c. These files can be transferred to a formatted CP/M disk with the utility, PIP. If these files do not fit onto a single disk, you may want to put In.com and c.lib on a second disk. That little extra trouble may prove to be worthwhile in the future, if only for your own peace of mind. Now we can leave the disk swapping behind and see how this package is put together. The Z80 Compiler and The Aztec C II development system contains two compilers, cc cz. While either compiler will run on the zao Copyright (c) 1984 by Manx Software Systems, Inc. tut.2 Aztec C TUTORIAL microprocessor, cz makes special use of the Z80. chip, only cc can be used. On the 8080 For the purposes of this introduction, either compiler will work just as well on the Z80. The differences between them are described in section III. If you wish to use the ez compiler in the following example, simply copy the file, cz.com, onto your working disk instead of cc.com. Anywhere reference is made to ee, read ez. An Examp1e As depicted in the diagram, there are five steps to developing an executable program. Most of your work is done in steps one and five. The intervening steps are accomplished with the aid of the software in this package. For now, we will assume you are interested in seeing the example program, exmpl.c, run on your computer. Although the program itself is not very engaging, we hope that compiling it will familiarize you with the Aztec development system. Compi1ing the Examp1e "exmpl.c"' is an ordinary text file. Normally, you will have created it with a text editor. It is special only in that its contents are a C language program. Aztec C II translates this program into an assembly language program. This translation process is called compilation. It is begun by running the compiler with this command: ce exmpl.e If exmpl.c is not on the disk in the default disk drive, you can specify a drive as follows: a:ec b:exmp1.e The same convention is used for running any CP/M program. CP/M should go to the appropriate disk drive to find the file, CC.COM. That is the compiler. Then the compiler will go searching for the file, exmpl.c. When the compiler is finished, it will leave behind a new file on the disk, EXAMPL.ASM. This too is just a text file, which can be printed out with the CP/M command, type, and edited with a text editor. Assembly language programmers can edit this file to "hand optimize" certain parts of the code to make it run faster. Otherwise, though, you should not have to concern yourself with this file directly. Copyright (c) 1984 by Manx software Systems, Inc. tut.3 Aztec C TUTORIAL 1. +---------------------+ I EDITOR I +---------------------+ I / II e" \ source file 1 \ 2. I / +---------------------+ I Aztec C II compiler I +---------------------+ I I / "ASM" source file \ 3. \ I / +---------------------+ MANX AS Assembler +---------------------+ 1 1 I / I "0" object file \ \ +---------------------+ 1---> 1 LIBUTIL librarian I / +---------------------+ 1 4. +---------------------+ / 1 MANX LN Link Editor 1<-- 1 +---------------------+ \ I / 1 COM executable file \ 5. II II subroutine \ library I / \ 1 / +---------------------+ +------------------+ 1 program execution 1<---->1 debugging 1 l i t h e program +---------------------+ +------------------+ Figure 1. Developing "C· programs with Aztec C II The Assembly step The next step is to convert this assembly code into what is called object code. This is the job of the assembler. AS was specifically designed to handle the output of the Aztec compiler, so this step should run very smoothly unless: 1. there is not enough space on the disk, or 2. you are including assembly code you have written yourself. If neither of these things are true, everything will run very smoothly. Copyright (c) 1984 by Manx Software Systems, Inc. tut.4 Aztec C TUTORIAL The assembly is begun with the following command: as exmpl.asm As always, a drive identifier can be given to specify on which disk either of the files are located. The assembler will leave its output in a file called exmpl.o. The assembler output is known as relocatable object code because it can be relocated anywhere in memory; this is done by the linker. The linker will convert this code from relocatable object format to absolute data, that is, a program which will be loaded and run at a specific address in memory. Linking the Example When the assembler is finished, The command to the linker is: we are left with exmpl.o. In exmpl.o c.lib The file, c.lib, is a library full of object modules similar to exmpl.o. They are relocatable object code produced by compiling and assembling the routines which are available in the library. In the example program, printf is a function which comes from this library. During the link step, the linker will search the library for this function and "pull in" the object module in which it is defined. More about libraries later. Most programs will need to be linked with c.lib, since there are many functions in it which remain invisible to you. Try the following link command: In exmpl.o The linker will report that several names were undefined. These are needed support functions which your program called without knowing it. The output of the linker is an executable program file. Here, "exmpl.com" was produced. This program can be run by entering the name of the file minus the extent: exmpl This is the way any CP/M program is run. Copyright (c) 1984 by Manx Software Systems, Inc. tut.S Aztec C TUTORIAL So the process of going from source code to an executable program consists of these three steps: cc exmpl.c compile as exmpl.asm assemble In exmpl.o c.lib link If your system allows it, you can use a submit file to perform any or all of these steps. If You Run Out of Disk Space The only difficulty you may have is running out of disk space. The danger of this occurring varies from system to system. If you are having trouble in this respect, here are a few suggestions: 1. Use two disks. The first disk might contain the compiler and assembler, while the second disk contains the linker and library. 2. If the three programs from Manx and the library all fit on a single disk, then leave all of your software on a second disk, perhaps in drive B. Make B the default drive by entering "B:". Then, for example, your link command would look like this: a:ln exmpl.o a:c.lib 3. The assembler has an option called -ZAP which will cause it to delete its input file. This keeps assembly files, which are not always useful to you, from cluttering up the disk. So the following command: as -ZAP exmpl.asm will leave "exmpl.o" on the disk but delete "exmpl.asm". Copyright (c) 1984 by Manx Software systems, Inc. tut.6 SECTION III The Compiler Aztec C COMPILER The Compiler The Aztec C II compiler is implemented according to the language description supplied by Brian W. Kernighan and Dennis M. Ritchie, in The C programming Language. Where discrepancy or ambiguity iSfound in that text, reference is made to the implementation of the language under UNIX version 7. The Aztec C manual should bring to light any areas where there may be confusion as regards Aztec C. Since this manual is not intended as a complete guide to the C language, you may need another text handy to answer questions about proper syntax and usage. Several strong tutorials are available: some are suggested in the appendix. The Kernighan and Ritchie book is generally considered the place to turn to for the final word. You may want to have a copy, whatever other books you might own. This section will explain how to use the compiler. There are a variety of options which can be specified at compile time. These enhance the flexibility of the system, so that you will eventually want to become familiar with what is available. If you are just trying out some small programs similar to the example program of the last section, not all of the material in this section will be of immediate importance to you. Running the Compiler The compiler is invoked by a command of the format: cc [-options] filename.c If the filename does not have an extension, the compiler will assume it ends in II.C It is recommended that C source files have this extension although the compiler will allow a different one, as in II filename.src Il • ll • The C source statements found in the given file are translated into assembly language and written to a file. This output file is named IIfilename.asm by default. (The assembler will expect the lI.asm extent the same way that the compiler expected the II.CIl.) An alternate output file can be specified with the 11-011 option. For example, ll ll cc -0 file.aBO file will compile the program in IIfile.c language equivalent to IIfile.aBO ll and write the assembly Ii • The compiler will append the II.C Il only if it doesn't see a period (.) in the filename. So that if you want to name a source Copyright (c) 1984 by Manx Software Systems, Inc. cc.l Aztec C COMPILER file wi thout any extension at all, to compile it in this way: as in II srcfil", you will have cc srcfil. The period at the end of the filename stops the compiler from tacking on the ".C". The remaining compiler options have more specialized uses. They are described below. The 8080 and Z80 Compilers The Aztec C II development system includes two compilers, cc and cz. Both support the full C language, as explained above. Both compilers generate 8080 assembler mnemonics. cc can be used in conjunction with either the 8080 or Z80. In either situation, one register is available for use by a variable through the C language storage class, register. cz can be run on only the Z80, and produces code intended for the Z80. It uses the Z80 index registers, IX and IY, to hold additional register variables, for a total of three. This results in a higher throughput. To simplify the descriptions in this manual, reference is made only to cc throughout. On Z80 systems, the two compilers can be used interchangeably. The assembly output of either compiler can be assembled by the Manx AS assembler and linked with the standard libraries, c.lib and m.lib. A call to either csave or zsave is made at the entry point of each C function. Both functions are pulled into every linked program. Copyright (c) 1984 by Manx Software systems, Inc. cc.2 Aztec C COMPILER Compiler options utility options -D Defines a symbol for the preprocessor. -F Forces frame allocation to take place in-line rather than through a call to a library function. -I Causes search for included files in specified areas. -M This option causes the compiler to produce code for the Microsoft assembler (see section XI for details). -0 Used to specify an alternate output file. -P Sends error messages to the printer. -Q Converts default automatic variables statics for efficiency. to -R This option is a special extension to the compiler which causes it to produce code for the Digital Research assembler (see section XI for details). -8 Causes search for undefined structure members as described below. -T This option will insert the C source statements as comments in the assembly code output. Each source statement appears before the assembly code it generates. -u Converts default global variables externs (except initialized data). into Table Manipulation -E Specifies the size of the expression table. -L Specifies the size of the local symbol table. -y Specifies the maximum number of outstanding cases allowed in a switch. -z Specifies the size of the table for literal strings . . Copyright (c) 1984 by Manx Software Systems, Inc. cc.3 Aztec C COMPILER utility Options -D Option The -D option defines a symbol in the same way as the preprocessor directive, 'define. Its usage is as follows: cc -Dmacro[=text] prog.c For example, cc -DMAXLEN=lOOO prog.c is equivalent to inserting the following line at the beginning of the program: 'define MAXLEN 1000 Since the -D option causes a symbol to be defined for the preprocessor, this can be used in conjunction with the preprocessor directive, lifdef, to selectively include code in a compilation. A common example is code such as the following: ,ifdef DEBUG printf("value: %d\n", i): .endif This debugging code would be included in the compiled source by the following command: cc -dDEBUG program.c When no SUbstitution text is defined as the numerical value, one. specified, the symbol is This capability is useful when small pieces of code must be altered for different operating environments. Rather than maintaining two copies of such a program, this compile time switch can be used to generate the code needed for a specific environment. For example, ,ifdef APPLE appleinit(): .else ibminit(): .endif -F Option line. The -F option causes function entry code to be generated inNormally, every compiled C function begins with a call to , Copyright (c) 1984 by Manx Software systems, Inc. cc.4 Aztec C COMPILER a routine in c.lib. equivalent code. This option replaces this call with the This results in a small savings time the compiled function is called. repeatedly, the savings can add up to execution time of the program. As a will slightly increase the size of the in execution speed every If the function is called a large difference in the side effect, this option compiled code. -1 Option The -1 option causes the compiler to search in a specified area for files included in the source code. By default, the compiler will search for included files in the current user and user 0 on the default drive and in user 0 on drive A, if that drive has been logged in (i.e., if drive A has already been accessed). The -1 option is used to specify a more extended search. For example, tinclude'd header files might be kept in particular user, such as user 5 on drive A. Then a compile command might be this: cc -i 5/a: program.c The parameter for the option has the form: [user number]/[drive identifier] Each user area to be searched requires its own option letter. The -I can be specified up to eight times in a single command. -p Option The -P option redirects the screen output of the compiler to the printer. This produces a hard copy of the error messages generated during compilation. -0 Option -0 is an option which causes the compiler to treat automatic variables as statics. This will essentially convert an automatic lIint ill within a function to a IIstatic int ill. This can cause a significant increase in execution speed, since it is much less expensive to address statics than variables on the stack. As an empirical example, a version of the infamous Eratosthenes ' sieve program which ran in 33 seconds was reduced Copyright (c) 1984 by Manx software Systems, Inc. cc.5 Aztec C COMPILER to a run of only 24 seconds, just by specifying the -Q option. A declaration using the "auto" keyword, such as "auto int "auto" forces the i", will not be affected by the -Q option. variable to remain an automatic. If a variable are no available automatic storage static under the -Q is declared as a "register int i", but there registers, the variable defaults to the class. So a "register int i" will become a option, if there is not a free register. Like any other static data, an auto-turned-static is initialized to zero before the program begins. Note that calling a function recursively may cause problems when the -Q option is used. Consider a function with a "static int i" which increments i and then calls itself: qtest( ) { static int i; if (++i < 100) qtest(i): return (i): } The following program will print out "100": main ( ) { printf("%d", qtest(»: } If the integer variable in qtest() was not static, the recursive call would have to be "i = qtest(i)". Although qtest() does not seem to save the value returned by the call to itself, the static variable retains its value throughout the nesting. -u Option The -u option performs a different storage class conversion. It converts global variables into externs. That is, under -U, "int i" outside any function becomes "extern int i". This is useful in that it allows all global variables to be defined in a single file without having to specify an "extern" with each other declaration. The universal way of defining a global integer, i, is to have the statement, "int i", in one file and the statement, "extern int i" in all other program files in which the variable is used. The "int i" is a "definition" of the variable since it causes space to be reserved in memory for the variable. Th~ "extern" causes no memory to be reserved; it says, "This variable Copyright (c) 1984 by Manx Software Systems, Inc. cc.6 Aztec C COMPILER is defined somewhere else but it is going to be used in this file of the program. II When using the Aztec assembler and linker, the only requirement is that a global variable must be defined at least once. So in this example, it is also possible to have lIint ill in every file: the lIextern ll keyword is not extremely significant in this case. Although there may turn out to be more than one global lIint ill in the program, memory will be allocated for just one. This is also the behavior under UNIX. The situation is slightly different when employing the assembler and linker provided by Microsoft or Digital Research. (These programs can be used only with a compiler which has the extended options, -M and -R.) When using the Microsoft or DRI assembler and linker, a global variable must be defined exactly once. That is, lIextern int i II must appear in every declaration except one, which must be an lIint ill. This is where the -u option is useful. By specifying it for all but a single source file, you will not have to worry about having too many or not enough externs: the lIexterns ll can be left off entirely since they will be tacked on under the -u option. A global initialization is immune to the -u option. Hence, lIint i = 3: 11 is unchanged by it. Initializing a global variable to zero will cause it to be ignored by -u. This is one means for forcing a data definition when using this option. -8 option The -8 option is best illustrated by an example: struct atype { char aI, a2: } a: struct btype { char bI, b2: } b: a.bI b.c2 = = 4: 6: Normally, both of the assignments will cause a compiler error, since IIbl li is not a member of lIa ll , and IIc211 is not a member of lIa li • However, under the -S option, the first assignment will be legal and the second will be illegal. Under -S, the compiler will not generate an error when it notices that IIbl li is not a member of lIa li • Instead, it will proceed to search through all the previously defined structures until it finds the member IIbl li . The member of structure lib II I Copyright (c) 1984 by Manx Software Systems, Inc. cc.7 Aztec C COMPILER namely IIbl ll , is taken to be referenced by lIa.bl ll • The second assignment will generate an error with or without the -s option, since Ic2" is not a member of a previously defined structure. The -s option refers only to previously defined structures. Table Manipulation An explanation of the remaining options requires a little background. As the compiler is compiling a C program, it has to keep track of all the symbols in the source code-- mainly variable and function names. It has to remember some information about each variable, such as its data type. All this is stored in symbol tables in memory. The symbol tables start out with a certain default size. This size is usually sufficient for compiling a moderately sized source file. However, depending on the complexity of the program, the compiler might use up all the entries in a table during compilation. In this case, the compiler will terminate with an appropriate error message. If this happens, you will need to adjust the sizes of the tables. Usually, this will call for just increasing the size of a single table. The default sizes are given below, along with examples for each option. The amount of memory available to the compiler is obviously limited. It will read into memory only as much of the source file as it needs in order to generate output. Aside from the w~rk space needed for this task, it maintains the following tables: expression work table, macro/global work table, case table, string table, label table, and local symbol table. The label table holds information on all the labels in the program (a label is the destination of a goto). It is fixed at a generous size. If it overflows, the compiler will generate error code 54, and you will have to decrease the number of labels in your program. The macro table is where macros defined with "#define" are remembered. It also contains information about all global symbols. Unlike the other symbol tables, it is self-adjusting, and is never larger than it needs to be. Note that this is different from versions previous to 1.06 of the compiler. This change has made the "-X" option obsolete. If the Compiler Runs Out of Memory If the compiler aborts with a message indicating that it ran out of memory, you will have to decrease the size of one or more Copyright (c) 1984 by Manx Software Systems, Inc. cc.8 Aztec C COMPILER of the tables. There is no harm in doing so, since the compiler will always complain when a table overflows. Decreasing the size of a table will free up space in memory for the compiler. As indicated in section XI, the compiler may run out of memory without overflowing any particular table. In this case, a generic "out of memory" message will appear. If the module you are compiling is extremely large, the simplest solution may be to break i t into two or more separate modules. However, if the module is of reasonable size, it is possible to decrease the size of a table which is not fully used, thereby freeing up memory for the compilation. Choosing which table to decrease and by how much is a matter of estimation. If a particular table overflows, the appropriate error will be generated. It is then necessary to increase the size of that table. Table sizes specified by option letters are used for only a single compilation. The Expression Table: This is the area where the "current II expression is handled. It is the compiler's work space as it interprets a line of C code. The various parts of the line are stored here while the statement is being compiled. When the compiler moves on to the next expression, this space is again freed for use. The default value for -E is 60 entries. Each "entry" in the table consumes 14 bytes in memory. So the expression table starts at 840 bytes. Each operand and operator in an expression is one entry in the symbol table-- another fourteen bytes. The term, "operator", includes each function and each comma in an argument list, as well as the symbols you would normally expect (+, &, "', etc.). There are some other rules for determining the number of entries an expression will require. Since they are not straightforward and are subject to change, they will not be discussed here. The following expression uses 15 entries in the table: a =b + function { a + 7, b, d) * x Everything is an entry except for the ")", commas which separate the function arguments. including the the compiler I f the expression table overflows, generate error number 36, "no more expression space." will This command will reserve space for 100 entries (1800 bytes) in the expression table: cc -EIOO filename Copyright (c) 1984 by Manx Software Systems, Inc. cc.9 Aztec C COMPILER The option must be given before the filename. no space between the option letter and the value. There can be The Loca1 Symbo1 Tab1e: New symbols can be declared after any open brace. Most commonly, a declaration list appears at the beginning of a function body_ The symbols declared here are added to the local symbol table. If a variable is declared in the body of, say, a for loop, it is added to the table. When the compiler has finished compiling the loop, that entry in the table is freed up. And when it has finished the function, the table will be empty. The default size of the table is 30 entries. Since each entry consumes 26 bytes, the table begins at 520 bytes. If the table overflows, the compiler will send a message to the screen and stop. The number of entries in the table can be adjusted with the -L option. The following compilation will use a table of 75 entries, or almost 2000 bytes: cc -L75 program.c The Case Tab1e: When the compiler looks at a switch statement, it builds a table of the cases in it. When it IIleaves ll the switch statement, it frees up the entries for that switch. For example, the following will use a maximum of four entries in the case table: { switch (a) case 0: a += 1; break; case 1: { switch (x) case I a' : func1 (a) ; break; case I b' : func2 (b) ; break; } a = 5; case 3: func2 (a) ; break; /* one */ /* two */ /* three */ /* four */ /* re1ease the 1ast two */ /* tota1 ends at three */ } Copyright (c) 1984 by Manx Software Systems, Inc. cc.10 Aztec C COMPILER The table defaults to 40 entries, each using up four bytes. I f the compiler returns with an error 76 (licase table exhausted you will have to recompile with a new size, as in: ll ), cc -YlOO file The string Table: This is where the compiler saves IIliterals or strings. The size of this area defaults to 1000 bytes. Each string occupies a number ·~f bytes equal to the size of the string. The size of a string is just the number of characters in it plus one (for the null terminator). ll , If the string table overflows, the compiler will generate error 2, IIstring space exhausted ll • The following command will reserve 2000 bytes for the string table: cc -Z2000 file The size of the string table needs to be increased if an error 2 (string space exhausted) is encountered. Copyright (c) 1984 by Manx Software Systems, Inc. cc.ll Aztec C COMPILER Error checking Compiler errors corne in two varieties-- fatal and not fatal. Fatal errors cause the compiler to make a final statement and stop. Running out of memory and finding no input are examples of fatal errors. Both kinds of errors are described in section XII. The non-fatal sort are introduced below. The compiler will report any errors it finds in the source file. It will first print out a line of code. The up-arrow (carot) in this line indicates how far the compiler went before it was able to detect the error. The name of the source file will appear, followed by a line number, an error number and the symbol which may have caused the error. The compiler is not always able to give a precise description of an error. Usually, it must proceed to the next item in the file to ascertain that an error was encountered. Once an error is found, it is not obvious how to interpret the subsequent code, since the compiler cannot second-guess the programmer's intentions. This may cause it to flag perfectly good syntax as an error. If errors arise at compile time, it is a general rule of thumb that the very first error should be corrected first. This may clear up some of the errors which follow. The best way to attack an error is first to look up the meaning of the error code in the back of this manual. Some hints are given there as to what the problem might be. And you will find it easier to understand the error and the message if you know why the compiler produced that particular code. The error codes indicate what the compiler was doing when the error was found. Copyright (c) 1984 by Manx Software systems, Inc. cc.12 SECTION IV The As-sembler Aztec C ASSEMBLER The Assembler The Manx AS assembler accepts a subset of the Microsoft MACRO-BO assembler language. The Manx AS assembler does not support macros or ZBO mnemonics. The Manx AS assembler is a relocating assembler. invoked by the command line: It is AS fi1ename.asm The relocatable object file produced by the assembly will be named "filename.o". An alternate object filename can be supplied by specifiying -0 filename (0 is a letter). The object file will be written to the filename following "-0", as in the following example: as -0 newfi1.obj filename.asm The output filename does not have to end wi th ". 0 ", but that is the recommended format. The assembly language source file can also have any extension. If none is given, the extension defaults to ".asm". When assembling compiler output, a useful option is -ZAP. After creating the object code output file, the assembler will delete the (intermediate) assembly language file. This conserves disk space and is especially useful when compiling a large number of C source files. It is common practice to create a C language source file ending in ".C", such "prog.c", and leave off the extension entirely when compiling and assembling: cc prog as -ZAP prog To produce an assembly listing, specify the -L option, as in the following example. The assembler is a one pass assembler so forward address references will not appear on the listing. as -1 prog Copyright (c) 19B4 by Manx Software Systems, Inc. as.l Aztec C ASSEMBLER The following assembler: summaries define the syntax for the AS STATEMENTS Source files for the Manx AS assembler consist of statements of the form: [1abe1[:]] [opcode] [argument] [:comment] The brackets "[ •.• J II indicate an optional element. LABELS A label consists of 1 to 8 alphanumerics followed by an optional colon. A label ITlust start in column one. If a statement is not labeled, then column one must be left blank. A label must start with an alphabeti.c. An alphabetic is defined to be any letter or one of the special characters: @ $ An alphanumeric is cln alphabetic, or a digit from 0 to 9. A label followed by "##" is declared external. EXPRESSIONS Expressions are evaluated from left to right according to parenthesization, wit:h precedence given unary operators. Operators are: + - * / A'~ID OR XOR NOT 8m. 8HR MOD CONSTANTS The default base for numeric constants is decimal. A number suffixed by a "B" is bi nary, e.g. lOOlOllOB. A number suffixed by a "D" is decimal, e.g. 765D. A number suffixed by an 0 or Q is octal, e.g. 1260 or 1261:2. A number or alphabetic A-F suffixed by an "HI! is hexadecimal, e.g. OFEEH. A character constant is of the character enclosed by ~3ingle quotes. Copyright (c) 1984 b~r form: 'A', l\1anx Software Systems, Inc. that is, as.2 a Aztec C ASSEMBLER ASSEMBLER DIRECTIVES The Manx AS assembler supports the operations: following pseudo BSS sym_name, size creates symbol (sym name) of 'size' bytes in the BSS segment (which contains static data from C source code) • COMMON // sets the location counter to the selected cornmon block. CSEG select code segment. DB define byte constant. DSEG select data segment. DW define word constant (2 bytes) • END end of assembler source statements. GLOBAL sym_name, size creates an external symbol with size, 'size' bytes. An uninitialized global char in C compiles to a global of one byte. If a symbol is defined with global more than once, storage is allocated by the linker for the largest size given. NLIST turn off listing LIST turn on listing MACLIB/XTEXT filename include statements from another file PUBLIC/EXT/EXTRN label declares label to be external or entry Copyright (c) 1984 by Manx Software Systems, Inc. as.3 SECTION V The Linker Aztec C LINKER The Linker The Aztec linker is the software which ties together the pieces of a program which were compiled and assembled separately. The assembler produces a file containing what is called relocatable object code. The Manx AS assembler generates object files with a specific object file format. The Aztec linker expects that the files it links will be in this format. That is why AS and LN must be used together. The following pages are a brief introduction to linking and what the linker does. If you have had previous experience with linkage editors, you may wish to continue reading with the paragraph heading, "using the Linker." There you will find a concise description of the command format for the linker. Relocatable Object Files The object code produced by the assembler is "relocatable" because it can be loaded anywhere in memory. One task of the linker is to assign specific addresses to the parts of the program. Thjs tells the operating system where to load the program when it is run. Linkin9 hello.o It is very unusual for a C program to consist of a single, self-contained module. Let's consider a simple program which prints "hello, world" using the function, printf. The terminology here is precise: printf is a function and not an intrinsic feature of the language. It is a function which you might have written, but it already happens to be provided in the file, "c.lib". This file is a library of all the standard i/o functions. It also contains many support routines which are called in the code generated by the compiler. These routines aid in integer arithmetic, operating system support, etc. When the linker sees that a call to printf was made, it pulls the function from the library and combines it with the "hello, world" program. The link command would look like this: In hello.o c.lib When "hello.c" was compiled, calls were made to some invisible support functions in the library. So linking without the standard library will cause some unfamiliar symbols to be undefined. All programs will need to be linked wi th "c.lib". Copyright (c) 1984 by Manx software Systems, Inc. In.l Aztec C LINKER The Linking Process Since the standard library contains only a limited number of general purpose functions, all but the most trivial programs are certain to call user-defined functions. It is up to the linker to connect a function call with the definition of the function somewhere in the code. In the example given below, the linker will find two function calls in file 1. The reference to funcl is "resolved" when the definition of funcl is found in the same file. The following command In filel.o c.lib will cause an error indicating that "func2" is an undefined symbol. The reason is that the definition of func2 is in another file, namely file2.o. The linkage has to include this file in order to be successful: In filel.o file2.o c.lib file 2 file 1 main ( ) func2( ) { { funcl(). func2(); return; } } funcl() { return; } Libraries A library is a collection of object files put together by a librarian. Libraries intended for use with LN must be built with the Aztec librarian, LIBUTIL. This ut~lity is described in the next section. All the object files specified to the linker will be "pulled into" the linkage; they are automatically included in the final executable file. However, when a library is encountered, it is searched. Only those modules in the library which satisfy a previous function call are pulled in. For Example Consider the "hello, world" example. Having looked at the module, "hello.o", the linker has built a list of undefined Copyright (c) 1984 by Manx Software Systems, Inc. In.2 Aztec C LINKER symbols. This list includes all the global symbols that have been referenced but not defined. Global variables and all function names are considered to be global symbols. The list of undefined's for "hello.o" includes the symbol, "printf". When the linker reaches the standard library, this is one of the symbols it will be looking for. It will discover that "printf" is defined in a library module whose name also happens to be "printf". (There is not any necessary relation between the name of a library module and the functions defined within it.) The linker pulls in the "printf" module in order to resolve the reference to the "printf" function. Files are examined in the order in which they are specified on the command line. So the following linkages are equivalent: In hell0.o In c.lib hello.o Since no symbols are undefined when the linker searches c.lib in the second line, no modules are pulled in. It is good practice to leave all libraries at the end of the command line, with the standard library last of all. The Order of Library Modules For the same reason, the order of the modules within a library is significant. The linker searches a library once, from beginning to end. If a module is pulled in at any point, and that module introduces a new undefined symbol, then that symbol is added to the running list of undefined's. The linker will not search the library twice to resolve any references which remain unresolved. A common error lies in the following situation: module of program references (function calls) main.o getinput. do calc input.o gets calc.o output.o printf Suppose we build a library to hold the last three modules of this program. Then our link step will look like this: In main.o proglib.lib c.lib But it is important that "proglib.lib" is built in the right order. Let's assume that main() calls two functions, getinput() and do_calc(). getinput() is defined in the module, input.o. It Copyright (c) 1984 by Manx Software Systems, Inc. In.3 Aztec C LINKER in turn calls the standard library function, gets () . do_calc () is in calc.o and calls put_value(). put_value() is in output.o and calls printf(). What happens at link time if proglib.lib is built as follows? proglib.lib: input.o output.o ca1c.o After main.o, the linker has "getinput ll and "do calc undefined (as well as some other obscure functions in c.lib). Then it begins the search of proglib.lib. It looks at the library module, "input", first. Since that module defines "getinput", that symbol is taken off the list of undefined's. But IIgets" is added to it. ll The symbols "do calc" and "gets" linker examines the module, "output". symbols are defined there, that module module, "calc", the reference to "do "put_value" is a new undefined symbol. are undefined when the Since neither of these is ignored. In the next calc" is resolved but The linker still has "getsll and "put value" undefined. It then moves on to c.lib, where "gets" is resolved. But the call to "put value" is never satisfied. The error from the linker will look like this: Undefined symbol: put_va1ue_ This means that the module defining "put value" was not pulled into the linkage. The reason, as we-saw, was that "put value ll was not an undefined symbol when the "output" module was -passed over. This problem would not occur with the library built this way: prog1ib.lib: input.o calc.o output.o The standard libraries were put together with much care so that this kind of problem would not arise. Occasionally it becomes difficult or impossible to build a library so that all references are resolved. In the example, the problem could be solved with the following command: In main.o prog1ib.1ib prog1ib.1ib c.1ib The second time through proglib.lib, the linker will pull in the module "output". The reason this is not the most satisfactory solution is that the linker has to search the library twice; this will lengthen the time needed to link. Copyright (c) 1984 by Manx Software Systems, Inc. 1n.4 Aztec C LINKER Using the Linl LIBUTIL -0 example.lib subl.o sub2.0 2. LIBUTIL option-a USE to append to a library FUNCTION- the following appends example.lib >LIBUTIL exmpl.o to the -0 example. lib -a exmpl.o this function can be used to append any number of .0 files to the library. For e x amp 1 e , the 'f 0 110 win g a p pen d s exmpl.o and smpl.o to the example.lib >LIBUTIL -0 example.lib -a exmpl.o smpl.o NB If a large number of files need to be a p pen de d to' a l i bra r y , i t i s advantageous to use the dot option (see item 6). Copyright (c) 1984 by Manx Software Systems, Inc. Ibutl.l LIBUTIL Aztec C 3. LIBUTIL option-t USE - to produce an index listing of modules in a given library FUNCTION- the following displays a listing of all modules in a particular library, example.lib: >LIBUTIL -0 example. lib -t NB this function will allow only one library to be listed at a time; also, this lists only module names, and not the functions which each module may contain. 4. LIBUTIL option-x USE - a. copies a particular library module into a relocatable object file b. copies a complete library into relocatable object files FUNCTION- a. the following copies library module, exmpl into a relocatable object file: >LIBUTIL -0 example.lib -x exmpl b. the following copies a complete library, example.lib, (including all modules contained within it) into relocatable object files: >LIBUTIL -0 NB. 5. LIBUTIL example. lib -x It shou ld be noted tha t when copying a single module the LIBUTIL executes the command and returns. When copying a complete library, the LIBUTIL lists the modules being copied. option-r USE - to replace a library module wi th the contents of a relocatable object file FUNCTION- the fo llow ing rep lac e s the library module subl with the relocatable object file subl.o >LIBUTIL -0 example. lib -r subl.o Copyright (c) 1984 by Manx Software systems, Inc. 1but1.2 Aztec C LIBUTIL 6. LIBUTIL -0 library name . to create a library using an extended command 1 ine the following creates a library, subl.o, charles.lib and appends to it sub2.0, sub3.0, sub4.0, etc. USE FUNCTION >xsub LIBUTIL -0 charles lib . subl.o sub2.o sub3.o sub4.0 7. LIBUTIL option -v to report the current status of a library during an operation by LIBUTIL. USE In More Detail ••• Creating a Library The command for creating a new library has this format: LIBUTIL [-0 ] The -0 option specifies the name of the library being created. If the option is not given, then the library name is assumed to be IIlibc.lib It is not recommended that LIBUTIL be used without naming a library with this option. li • How it Works First, LIBUTIL creates the library in a new file with a temporary name. If this file was successfully written, LIBUTIL erases the file with the same name as the library, if one exists. In effect, it makes sure that the new library can be created before destroying the old. Then the temporary file is renamed to the library name. Note that there must be room on the disk for both the old library and the new. The is a list of the object files which are to be included in the library. These are usually files generated by the Manx assembler. Naming Conventions An input filename can include a drive specification, as in the name, b:modulel.o. Otherwise, the file is assumed to be on the default drive. Also, the 11.0 ending can be left off 11 Copyright (c) 1984 by Manx Software Systems, Inc. lbutl.3 Aztec C LIBUTIL altogether. added on. When an input filename lacks an extent, ".0" is When an input file contains a single relocatable object module, the name of the module in the library will be the filename, less the drive specification and the extension. For example, if the input file is b:subl.o, then the module name inside the new library will be subl. An input file can be a library itself. In this case, the module names in the new library are the same as those in the input library. For example, if the input file is a library containing modules subl, sub2 and sub3, then the names of these modules in the created library will also be subl, sub2 and sub3. Since the list of input files for a library often will not fit on a single line, there is a convenient way to extend the command line. A period on the command line directs the linker to start reading filenames from standard input. When another period is read, the linker returns to the command line to read in the remaining filenames. Order in a Library The order in which a library is built is often crucial for easy linking. Modules go into a new library in the order in which they are read by LIBUTIL. Consider the following example: Let's assume there is currently a library, contains three modules: which sub3 sub2 subl oldlib.lib, The following command might be given: LIBUTIL -0 newlib.lib oldlib.lib sub4 • subS sub6.o sub7.o sub8 This will create a library called newlib.lib. The first three modules copied into it come from oldlib.lib. Then the contents of sub4.0 become the module, sub4, in the library. When LIBUTIL finds a period, it continues reading the filenames from standard input. So the next three files copied into newlib.lib are sub6.0, sub7.0 and sub8.0. Notice that ". 0 " after a filename in the c?~mand is assumed. The last module read in the example is in subS.o. final makeup of newlib.lib is: subl sub8 sub2 subS sub3 suM sub6 Copyright (c) 1984 by Manx Software Systems, Inc. So the sub7 Ibutl.4 Aztec C LIBUTIL Listing the Modules in a Library A listing such as this can be obtained with the -T option. This option simply produces a listing of the modules in the order in which they appear in a library. The -0 option is used in this case to specify which library is to be listed. For example, the listing above would be produced by entering: libutil -0 newlib.lib -t If the -0 option is missing, assumed. the library, libc.lib, is LIBUTIL will not perform multiple functions during a single invocation. For example, you cannot make it create a library and then list its contents with a single command~ you would need to run LIBUTIL for each task. There are just a few ways to use the -T option, such as: libutil - t libutil -ot example.lib libutil -t -0 example.lib Note that the listing the modules of a library does not give a true representation of what functions are defined within the library. For instance, a module named "prog inp" might contain the functions, "get_record", "get_name" and "get_num". Adding and Replacing Modules The -A and -R options are used to add or replace modules in a library. These options actually refer to the same process. The method used by LIBUTIL is fairly simple. be The -0 option is used to specify the library that going to as always, this defaults to c.lib. modified~ LIBUTIL creates a temporary file, just as it did when making a new library. Each module of the old library is then copied, in order, to the new file. Whenever a module name matches a name given on the command line, the old library module is ignored, and the contents of the file given in the command are copied to that module in the new file. When the last module in the old library has either been copied or skipped over, LIBUTIL returns to the command line. The files which have already been copied to the new library are checked off. LIBUTIL then copies to the new library all the remaining files on the command line, which have not been copied to the new library. Copyright (c) 1984 by Manx Software Systems, Inc. lbutl.5 Aztec C LIBUTIL For example, given an obsolete library, obslib.lib: mod 2 modI mod 3 and the following command: libutil -oa obslib.lib mod2 • sub2 subi LIBUTIL first copies modI from obslib to the temporary file. Since mod2 is specified on the command line, it copies the contents of mod2.0 to the temporary file and ignores the mod2 in obslib. It continues to copy mod3 from obslib, subl and sub2 to the temporary file, in that order. Then the temporary file is renamed to obslib.lib and the old library is erasede Just as in library creation, the old and the new libraries exist on disk at the same time, before the old is erased. There has to be enough room for both. Consider the following command: Iibutil -oa obslib.lib obslib.lib LIBUTIL will copy obslib to the temporary file, since none of the module names appear on the command line. Then the remaining files from the input list are copied to the temporary file. So that a listing of the resulting obslib.lib would be: modI mod2 mod 3 modI mod2 mod 3 This curious naming of modules does not affect the way their contents are treated by the linker. For example, the first modI might contain a single function, "get value", while the second contains a function, "get num". If "get value" is an undefined symbol when the linker searches the library, just the first modI will be pulled into the link, and similarly the second will be pulled in for an undefined "get_num". Copyright (c) 1984 by Manx Software Systems, Inc. Ibutl.6 SECTION VII Library Functions Library Functions This chapter describes the functions which come with the Aztec C package. It's divided into four subchapters: introduction, overview, functions, and system dependent functions. The 'overview' subchapter presents an overview of several topics, including i/o processing, memory usage, and error handling. The 'functions' subchapter describes in detail the functions in the Aztec C package which are common to all systems supported by Aztec C. Most of these functions are also supported by unix; those which aren't are clearly identified. The 'system dependent functions' functions which are unique to a system. subchapter describes A table of contents is provided at the beginning of the two functions subchapters. Copyright (c) 1984 by Manx Software Systems, Inc. lib.l Li brary Overvi ew Overview of Library Functions This subchapter contains several sections, each of which presents an overview of a different topic. The following sections are provided: I/O Introduces the i/o system provided in the Aztec C package. STANDARD I/O The i/o functions can be grouped into two sets~ this section describes one of them, the standard i/o functions. UNBUFFERED I/O This section describes the other set of i/o functions, the unbuffered. CONSOLE I/O Describes special topics relating to console i/o. DYNAMIC BUFFER ALLOCATION Discusses related to dynamic memory allocation. ERRORS Presents an overview of error processing. Copyright (c) 1984 by Manx Software Systems, Inc. lib.2 Overview of I/O There are two sets of functions for accessing files and devices: the unbuffered i/o functions and the standard i/o functions. These functions are identical to their UNIX equivalents, and are described in chapters 7 and 8 of The ~ programming Language. The unbuffered i/o functions are so called because, with few exceptions, they transfer information directly between a program and a file or device. By contrast, the standard i/o functions maintain buffers through which data must pass on its journey between a program and a disk file. The unbuffered i/o functions are used by programs which perform their own blocking and deblocking of disk files. The standard i/o functions are used by programs which need to access files but don't want to be bothered with the details of blocking and deblocking the file records. The unbuffered and standard i/o functions each have their own overview section (UNBUFFERED I/O and STANDARD I/O). The remainder of this section discusses features which the two sets of functions have in common. The basic same for both must first be i/o operations procedure for accessing files and devices is the standard and unbuffered i/o: the device or file "opened", that is, prepared for processing: Then occur: then the device or file is "closed". A maximum of eleven files and devices can be open at once for both standard and unbuffered i/o. When this limit is reached, an open file or device must be closed before another can be opened. Each set of functions has its own functions for performing these operations. For example, each set has its own functions for opening a file or device. Once a file or device has been opened, it can be accessed only by functions in the same set as the function which performed the open, and must be closed by the appropriate function in the same set. There are exceptions to this non-intermingling which are described below. There are two ways a file or device can be opened: first, the program can explicitly open it by issuing a function call. Second, it can be associated with one of the logical devices standard input, standard output, or standard error, and then opened when the program starts. Standard input, standard output, and standard error devices There are three logical devices which are automatically opened when a program is started: standard input, standard output, and standard error. By default, these are associated with the console. The operator, as part of the command line which Copyright (c) 1984 by Manx Software Systems, Inc. lib.3 I/O Overview I/O starts the program, can specify that these logical devices are to be "redirected" to another device or file. Standard input is redirected by entering on the command line, after the program name, the name of the file or device, preceeded by the character 1<1. Standard output is redirected by entering the name of the file or device, preceeded by I>'. For example, suppose the executable program copy reads standard input and writes it to standard output. Then the following command will read lines from the keyboard and write them to the display: copy The following will read from the keyboard and write it to the file testfile: copy >testfi1e This will copy the file exmplfil to the console: copy testfile Aztec C will pass command line arguments to the user's program via the user's function main{argc, argyl. argc is an integer containing the number of arguments plus one; argv is a pointer to a an array of character pointers, each of which, except the first, points to a command line argument. The first array element on some systems points to the command; on other systems, for example, CP/M and CP/M-86, the first pointer is null. For example, if the following command is entered: cat argl arg2 arg3 the program cat will be activated and execution begins at the user's function main. The first parameter to main is the integer 4. The second parameter is a pointer to an array of four character pointers; on some systems the first array element will point to the string "cat" and on others it will be a null pointer. The second, third, and fourth array elements will be pointers to the strings "argl", "arg 2", and "arg 3 respectively. II The command line can contain both arguments to be passed to the user's program and i/o redirection specifications. The i/o redirection strings wonlt be passed to the user's program, and can appear anywhere on the command line after the command name. For example, the standard output of the cat program can be redirected to the file outfile by any of the following commands; in each case the argc and argv parameters to the main function of cat are the same as if the redirection specifier wasn't present: Copyright (c) 1984 by Manx Software Systems, Inc. lib.4 I/O Overview I/O cat argl arg2 arg3 >outfile cat >outfile argl arg2 arg3 cat argl >outfile arg2 arg3 Sequentia1 I/O A program can access files both sequentially and randomly. For sequential access, a program simply issues any of the various read or write calls. The transfer will begin at the file's "current position", and will leave the current position set to the byte following the last byte transferred. A file can be opened for read or write access; in this case, its current position is initially the first byte in the file. A file can also be opened for append access; in this case its current position is initially the end of the file. On systems which don't keep track of the last character written to a file, such as CP/M and Apple DOS, it isn't always possible to correctly position a file to which data is to be appended. See below for details. Random I/O Two functions are provided which allow a program to set the current position of an open file: fseek, for a file opened for standard i/o; and lseek, for a file opened for unbuffered i/o. A program accesses a file randomly by first modifying the file's current position using one of the seek functions. Then the program issues any of the various read and write calls, which sequentially access the file. A file can be positioned relative to its beginning, current position, or end. positioning relative to the beginning and current position is always correctly done. For systems which don't keep track of the last character written to a file, such as CP/M and Apple DOS, positioning relative to the end of a file can't always be correctly done. See below for details. Finding the end of a fi1e UNIX keeps track of the last character written to a file. Since the Aztec I/O functions attempt to make a file look like a UNIX file to a program, when a program requests that a file be positioned relative to its end (that is, relative to the last character which was written to it), the Aztec C routines must try to locate the last character which was written to it. This can always be done if the operating system on which Aztec C is running also keeps track of the last character written to a file. However, CP/M, CP/M-86, and Apple DOS only keep track of the last record written to a file. For these systems, it is not Copyright (c) 1984 by Manx Software Systems, Inc. lib.5 I/O Overview I/O always possible for the Aztec C i/o functions to determine the last character written to the file, and hence for these systems it is not always possible to position a file relative to its end. When a program running on one of the systems mentioned in the last paragraph requests positioning of a file relative to its end, the Aztec i/o functions try to find the last character written to the file. They always succeed if the file contains only text: for files containing arbitrary data, they may not succeed. To locate the last valid character in a file on one of these systems, the Aztec routines use the following fact: when a file is created on these systems using Aztec C, the last record in the file is padded at the end with the special character which denotes the end of a text file. For CP/M and CP/M-86, the special character is control-z: for Apple DOS, it's a null character. If the program exactly filled the last record, it won't have any padding. When a program requests that a file be positioned relative to its end, the Aztec C i/o routines search the file's last record; end of file is declared to be located at the position following the last non-end-of-file character. For files of text, this algorithm always correctly determines the last character in the file, so appending to text files is always correctly done. For other files, this algorithm will still correctly determine the last valid character in the file ••. most of the time. However, if the last valid characters in the file are endof-file characters, the file will be incorrectly positioned. Opening files Opening files is somewhat system dependent: the parameters to the open functions are the same on the Aztec C packages for all systems, but some system dependencies exist, to conform with the system conventions. For example, the syntax of file names and and the areas searched for files differ from system to system. The following paragraphs describe, for the systems supported by Aztec C, system dependent information related to the opening of files. Opening files on CP/M, CP/M-86, and related systems The character string which specifies the file to be opened has the following fields, which must be in the order listed: (1) a user number followed by a forward slash, (2) a drive identifier followed by a colon, (3) the filename, (4) a period followed by an extension. Only the third field is mandatory. If a user Copyright (c) 1984 by Manx Software Systems, Inc. lib.6 Overview I/O I/O number isn't specified, the file is assumed to be on the current user. If the drive isn't specified, the file is assumed to be on the default drive. For example, the following are valid file names: file. ext b:file.ext IS/file.ext 12/c:file.ext file. ext file.ext file. ext file.ext is is is is on on on on default drive, current user b: drive, current user default drive, user 15 c: drive, user 12 A program can have files located in several different user areas open at once. There are several functions which may be useful to programs which need to access files in various user areas: getusr, which returns the current user number: setusr, which sets the current user number: and rstusr, which resets the current user number. See the section USER in the system dependent subchapter for more details. Opening files on TRSDOS and related systems When opening a file on TRSDOS or related systems, the filename has the standard TRSDOS format: that is, (l) filename, (2) followed by a slash and an extention, (3) followed by a period and a password, (4) followed by a colon and a drive number. Only the first field is mandatory. If a drive specifier is given, the file will be searched for, and created if necessary, on that drive. Otherwise, following the TRSDOS convention, a search for the file will be made on all drives, beginning with drive :0. If the file is found, and must be recreated, it will be recreated on the same drive. Accessing Devices Aztec C allows programs to access devices as well as files. Each system has its own names for devices, so the following table lists the devices and, for each system, its name. In this table, "CPM" refers to CP/M, CP/M-86, and related systems: PCDOS also includes MSDOS: TRSDOS includes LDOS and DOSPLUS. device keyboard display printer CPM can: can: prn: .. 1st: RS232 in rdr: RS232 out pun: PCDOS can: can: prn Apple DOS ki: do: pr: Copyright (c) 1984 by Manx Software systems, Inc. TRSDOS *ki *do *pr *ri *ro lib.7 I/O Overview I/O On model 4 TRSDOS, dynamically created devices can also be accessed. Mixing unbuffered and standard i/o calls As mentioned above, a program generally accesses a file or device using functions from one set of functions or the other, but not both. However, there are functions which facilitate this dual access: if a file or device is opened for standard i/o, the function fileno returns a file descriptor which can be used for unbuffered access to the file or device. If a file or device os open for unbuffered i/o, the function fdopen will prepare it for standard i/o as well. Care is warranted when accessing devices and files with both standard and unbuffered i/o functions. Copyright (c) 1984 by Manx Software Systems, Inc. lib.8 Overview: Standard I/O The standard i/o functions are used by programs to access files and devices. They are compatible with their UNIX counterparts, with few exceptions, and are also described in chapter 8 of The C programming Language. The exceptions concern appending data to files and positioning files relative to their end, and are discussed below. These functions provide programs with convenient and efficient access to files and devices. When accessing files, the functions buffer the file data: that is, handle the blocking and deblocking of file data. Thus the user's program can concentrate on its own concerns. Buffering of data to devices when using the standard i/o functions is discussed below. For programs which perform their own file buffering, another set of functions are provided. These are described in the section UNBUFFERED I/O. opening files and devices Before a program can access a file or device, it must be "opened", and when processing on it is done it must be "closed". An open device or file is called a "stream" and has associated with it a pointer, called a "file pointer", to a structure of type FILE. This identifies the file or device when standard i/o functions are called to access it. There are two ways for a file or device to be opened for standard i/o: first, the program can explicitly open it, by calling one of the functions fopen, freopen, or fdopen. In this case, the open function returns the file pointer associated with the file or device. fopen just opens the file or device. freopen reopens an open stream to another file or device: it's mainly used to change the file or device associated with one of the logical devices standard output, standard input, or standard error. fdopen opens for standard i/o a file or device already opened for unbuffered i/O. Alternatively, the file or device can be automatically opened as one of the logical devices standard input, standard output, or standard error. In this case, the file pointer is stdin, stdout, or stderr, respectively. These symbols are defined in the header file stdio.h. See the section entitled I/O for more information on logical devices. Closing streams A file or device opened for standard i/o can be closed in two ways: first, the program can explicitly close it by calling Copyright (c) 1984 by Manx Software Systems, Inc. lib.9 STANDARD I/O Overview STANDARD I/O the function fclose. Alternatively, when the program terminates, either by falling off the end of the function main, or by calling the function exit, the system will automatically close all open streams. Letting the system automatically close open streams is error-prone: data written to files using the standard i/o functions is buffered in memory, and a buffer isn't written to the file until it's full or the file is closed. Most likely, when a program finishes writing to a file, the file's buffer will be partially full, with this information not having been written to the file. If a program calls fclose, this function will write the partially filled buffer to the file and return an error code if this couldn't be done. If the program lets the system automatically close the file, the program won't know if an error occurred on this last write operation. Sequential I/O Files can be accessed sequentially and randomly. For sequential access, simply issue repeated read or write calls; each call transfers data beginning at the "current position" of the file, and updates the current position to the byte following the last byte transferred. When a file is opened, its current position is set to zero, if opened for read or write access, and to its end if opened for append. On systems which don't keep track of the last character written to a file, such as CP/M and Apple DOS, not all files can be correctly positioned for appending data. See the section entitled I/O for details. Random I/O The function fseek allows a file to be accessed randomly, by changing its current position. positioning can be relative to the beginning, current position, or end of the file. For systems which don't keep track of the last character written to a file, such as CP/M and Apple DOS, positioning relative to the end of a file cannot always be correctly done. See the I/O overview section for details. Buffering When the standard i/o functions are used to access a file, the i/o is buffered. Either a user-specified or dynamicallyallocated buffer can be used. The user's program specifies a l024-byte buffer to be used Copyright (c) 1984 by Manx Software Systems, Inc. lib.lO STANDARD I/O Overview STANDARD I/O for a file by calling the function setbuf after the file has been opened but before the first i/o request to it has been made. If, when the first i/o request is made to a file, the user hasn't specified the buffer to be used for the file, the system will automatically allocate, by calling malloc, a I024-byte buffer for it. When the file is closed it's buffer will be freed, by calling free. Dynamically allocated buffers are obtained from the one region of memory (the heap), whether requested by the standard i/o functions or by the user's program. For more information, see the overview section DYNAMIC BUFFER ALLOCATION. A program which both functions and has overlays that an overlay won't be allocated for file i/o. For overlay support. accesses files using standard i/o has to take special steps to insure loaded over a buffer dynamically more information, see section IX on By default, output to the console using standard i/o functions is unbuffered~ all other device i/o using the standard i/o functions is buffered. Console input buffering can be disabled using the ioctl function~ see the CONSOLE I/O overview for details. Buffering of standard i/o to other devices can be disabled using the setbuf function. See the description of setbuf for details. Errors There are three fields which may be set when an exceptional condition occurs during stream i/o. Two of the fields are unique to each stream (that is, each stream has its own pair). The other is a global integer. One of the fields associated with a stream is set if end of file is detected on input from the strearn~ the other is set if an error occurs during i/o to the stream. Once set for a stream, these flags remain set until the stream is closed or the program calls the clearerr function for the stream. The only exception to the last statement is that when called, fseek will reset the end of file flag for a stream. A program can check the status of the eof and error flags for a stream by calling the functions feof and ferror, respectively. The other field which may be set is the global integer errno. By convention, a system function which returns an error status as its value can also set a code in errno which more fully defines the error. The section ERRORS defines the values which may be set in errno. If an error occurs when a stream is being accessed, a standard i/o function returns EOF (-1) as its value, after setting a code in errno and setting the stream's error flag. Copyright (c) 1984 by Manx Software Systems, Inc. lib.II STANDARD I/O Overview STANDARD I/O If end of file is reached on an input stream, a standard i/o function returns EOF after setting the stream's eof flag. There are two techniques a program can use for errors during stream i/o. First, the program can check of each i/o call. Second, the program can issue i/o only periodically check for errors (for example, check all i/o is completed). On input, operation. detecting the result calls and only after a program will generally check the result of each On output to a file, a program can use either error checking technique; however, periodic checking by calling ferror is more efficient. When characters are written to a file using the standard i/o functions they are placed in a buffer, which is not written to disk until it is full. If the buffer isn't full, the function will return good status. It will only return bad status if the buffer was full and an error occurred while writing it to disk. Since the buffer size is 1024 bytes, most write calls will return good status, and hence periodic checking for errors is sufficient and most efficient. Once a file opened for standard i/o is closed, ferror can't be used to determine if an error has occurred while writing to it. Hence ferror should be called after all writing to the file is completed but before the file is closed. The file should be explicitly closed by fclose, and its return value checked, rather than letting the system automatically close it, to know positively whether an error has occurred while writing to the file. The reason for this is that when the writing to the file is completed, it's standard i/o buffer will probably be partly full. This buffer will be written to the file when the file is closed, and fclose will return an error status if this final write operation fails. Copyright (c) 1984 by Manx Software Systems, Inc. lib.12 STANDARD I/O Overview STANDARD I/O The standard i/o functions The standard i/o functions can be grouped into two sets: those that can access only the logical devices standard input, standard output, and standard error; and all the rest. Here are the standard i/o functions that can only access stdin, stdout, and stderr. These are all ASCII functions; that is, they expect to deal with text characters only. getchar gets printf puterr putchar puts scanf get an ASCII character from stdin get a line of ASCII characters from stdin format data and send it to stdout send a character to stderr send a character to stdout send a character string to stdout get a line from stdin and convert it Here are the rest of the standard i/o functions: agetc aputc fopen fdopen freopen fclose feof ferror fileno fflush fgets fprintf fputs fread fscanf fseek ftell fwrite getc getw putc putw setbuf ungetc get an ASCII character send an ASCII character open a file or device open as a stream a file or device already open for unbuffered i/o open an open stream to another file or device close an open stream check for end of file on a stream check for error on a stream get file descriptor associated with stream write stream's buffer get a line of ASCII characters format data and write it to a stream send a string of ASCII characters to a stream read binary data get data and convert it set current position within a file get current position write binary data get a binary character get two binary characters send a binary character send two binary characters specify buffer for stream push character back into stream Copyright (c) 1984 by Manx Software systems, Inc. lib.13 OVerview of unbuffered I/O The unbuffered I/O functions are used to access files and devices. They are compatible with their UNIX counterparts and are also described in chapter 8 of The f programming Language. As their narne implies, a program using these functions, with two exceptions, communicates directly with files and devices; data doesn't pass through system buffers. Some unbuffered I/O, however, is buffered: when data is transferred to or from a file in blocks smaller than a certain value, i t is buffered temporarily. This value differs from system to system, but is always less than or equal to 512 bytes. Also, console input can be buffered, and is, unless specific actions are taken by the user's program. programs which use the unbuffered i/o functions to access files generally handle the blocking and deblocking of file data themselves. programs requiring file access but unwilling to perform the blocking and deblocking can use the standard i/o functions; see the section STANDARD I/O for more information. Here are the unbuffered i/o functions: open creat close read write lseek rename unlink ioctl isatty - prepares a file or device for unbuffered i/o creates a file and opens it concludes the i/o on an open file or device read data from an open file or device write data to an open file or device change the current position of an open file renames a file deletes a file change console i/o mode is an open file or device the console? Before a program can access a file or device, it must be "opened", and when processing on it is done, it must be "closed". An open file or device has an integer known as a "file descriptor" associated with it; this identifies the file or device when it's accessed. There are two ways for a file or device to be opened for unbuffered i/o. First, it can explicitly open it, by calling the function open. In this case, open returns the file descriptor to be used when accessing the file or device. Alternatively, the file or device can be automatically opened as one of the logical devices standard input, standard output, or standard error. In this case, the file descriptor is the integer value 0, I, or 2, respectively. See the section entitled I/O for more information on this. An open file or device is closed by calling the function close. When a program ends, any devices or files still opened for unbuffered i/o will be closed. Copyright (c) 1984 by Manx Software Systems, Inc. lib. 14 UNBUFFERED I/O Overview UNBUFFERED I/O If an error occurs during an unbuffered i/o operation, the function returns -1 as its value and sets a code in the global integer errno. For more information on error handling, see the section ERRORS. The remainder of this section discusses unbuffered i/o to the various devices and to files. Console I/O Console I/O can be performed in a variety of ways. There's a default mode, and other modes can be selected by calling the function ioctl. When the console is in default mode, console input is buffered and is read from the keyboard a line at a time. Typed characters are echoed to the screen and the operator can use the standard operating system line editing facilities. A program doesn't have to read an entire line at a time (although the system software does this when reading keyboard input into it's internal buffer), but at most one line will be returned to the program for a single read request. The other modes of console i/o allow a program to get characters from the keyboard as they are typed, with or without their being echoed to the display; to disable normal system line editing facilities; and to terminate a read request if a key isn't depressed within a certain interval. Output to the console is always unbuffered: characters go directly from a program to the display. The only choice concerns translation of the newline character; by default, this is translated into a carriage return, line feed sequence. Optionally, this translation can be disabled. For more information see the section CONSOLE I/O. I/O to Hon-console Devices I/O to devices other than the system console is always unbuffered, with no translations. File I/O Programs call the functions read and write to access a file; the transfer begins at the "current position" of the file and proceeds until the number of characters specified by the program have been transferred. The current position of a file can be manipulated in various ways by a program, allowing both sequential and random acccess to Copyright (c) 1984 by Manx Software Systems, Inc. lib.IS UNBUFFERED I/O Overview UNBUFFERED I/O the file. For sequential access, a program simply issues consecutive i/o requests. After each operation, the current position of the file is set to the character following the last one accessed. The function lseek provides random access to a file by setting the current position to a specified character location. lseek allows the current position of a file to be set relative to the end of a file. For systems which don't keep track of the last character written to a file, such positioning cannot always be correctly done. For more information, see the section enti tled I/O. open provides a mode, 0 APPEND, which causes the file being opened to be positioned at its end. This mode is supported on UNIX Systems 3 and 5, but not UNIX version 7. As with lseek, the positioning may not be correct for systems which don't keep track of the last character written to a file. Copyright (c) 1984 by Manx Software Systems, Inc. lib.16 OVerview of Console I/O Console I/O can be performed in a variety of ways: o console input can be buffered: o console input can be unbuffered, with the program receiving characters as they're typed: o echoing of typed characters to the display can be enabled or disabled: o an input operation can be automatically terminated if a character isn't received in a certain interval: o mapping of CR to LF on input and LF to CR-LF on output can be enabled or disabled. There is a default mode for console i/o, which is in effect unless changed by a call to the function ioctl. Thus, programs can access the console in the default mode without doing anything special. Or, console i/o can easily be customized to behave as desired by the programmer. In the default mode for console input, the system maintains an internal buffer of characters which it has read from the keyboard. Characters are returned to the program from this buffer. When the buffer is empty, the system reads a line of characters from the keyboard into the buffer: the program is suspended while this occurs. The operator can use the line editing facilities provided by the operating system, and typed characters are echoed to the display. Finally, carriage return characters are converted to newline characters. In the default mode, console output is unbuffered (as it is for all other modes). Newline characters are converted to carriage return - line feed sequence. A program selects console I/O modes using the function ioctl. This has the form: 'include ··sgtty.h" ioctl(fd, code, arg) struct sgttyb *arg: The header file sgtty.h defines symbolic values for the code parameter (which tells ioctl what to do) and the structure sgttyb. The parameter fd is a file descriptor associated with the console. On UNIX, this parameter defines the file descriptor associated with the device to which the ioctl call applies. Here, ioctl always applies to the console. Copyright (c) 1984 by Manx Software Systems, Inc. lib.17 Overview of Conso1e I/O The parameter code defines the action to be performed by ioct1. It can have these values: TIOCGETP fetch the console parameters and store them in the structure pointed at by arg TIOCSETP and TIOCSETN set the console parameters according to the structure pointed at by arg The argument arg points to a structure having the following format: struct sgttyb { char sg erase: char sg-ki11: int sg=f1ags: } Only sg f1ags is used by Aztec C: the rest are provided for UNIX compatibili ty. sg f1ags determines the console I/O mode. These are the symbolic values it can assume: RAW CBREAK ECHO CRMOD set RAW mode (turns off CBREAK, ECHO, & CRMOD) return each character as soon as typed echo input characters to the display map CR to LF on input; convert LF to CR-LF on output More than one of these codes can be specified in a single call to ioct1: the values are simply 'or'ed together. If the RAW option is selected, none of the other options have any effect. When the console is in RAW mode, following features: console input has the o no character translations are performed o the operator can't editing facilities o typed characters aren't echoed to the screen o the system will attempt to read the number of characters requested by the read request: however, after one character has been received, the operation will be terminated if a character isn't received within a certain period of time. This period is hard coded into ioct1.c. use the operating Copyright (c) 1984 by Manx Software Systems, Inc. system's line 1ib.18 Overview of Console I/O If CBREAK is selected, and RAW is not, console input has the following features: o the system will attempt to read the number of characters requested. if ECHO isn't specified, the operation will time out after one character has been received if a character isn't received within a certain period of time. If ECHO is specified, the operation won't terminate until all characters requested have been received. o If ECHO is selected, input characters are echoed to the display: otherwise, they're not. o If CRMOD is selected carriage returns are translated into line feeds. If neither RAW nor CBREAK is selected, a mode is selected which is either similar or identical to the default mode described above. If CRMOD is set, the mode is identical. Otherwise, the only difference is that the translation of carriage return into newline on input and the translation of newline to carriage return - linefeed sequence on output doesn't occur. As mentioned above, when the console is in RAW mode or CBREAK without ECHO mode, a read request to the console will always return at least one character, but will terminate without having read the specified number of characters if a character isn't received within a certain interval. Actually, only the unbuffered read request may time out: the standard i/o functions are implemented in such a way that they will return the requested number of characters. For example, when the console is in RAW or CBREAK without ECHO mode, read(fd, buf, 80) will always return at least one character, but may not return return all 80 if the operator delays too long between subsequent key strokes. With the console still in a time-out-able mode getc(fp) directed to the console will always return one character, and gets (buf, 80, fp) will always return an entire line of characters. Copyright (c) 1984 by Manx Software Systems, Inc. lib.l9 OVerview of Console I/O EXAMPLES 1. Console input using default mode The following program copies characters from stdin to stdout. The console is in default mode, and assuming these streams haven't been redirected by the operator, the program will read from the keyboard and write to the display. In this mode, the operator can use the operating system's line editing facilities, such as backspace, and characters entered on the keyboard will be echoed to the display. The characters entered won't be returned to the program until the operator depresses carriage return. 'include IIstdio.h D 'include .Isgtty.h" main ( ) { int c: while ({c = getchar(» putchar(c): 1= EOF) } 2. Console input - RAW mode In this example, a program opens the console for standard i/o, sets the console in RAW mode, and goes into a loop, waiting for characters to be read from the console and then processing them. The characters typed by the operator aren't displayed unless the program itself displays them. The input request won't terminate until a character is received. This example assumes that the console is named Icon:'; on systems for which this is not the case, just substitute the appropriate name. 'include Iistdio.h li 'include I'sgtty.h ll main { ) { int c: FILE *fp: struct sgttyb stty: if {( fp = fopen{ Dcon: A. lirA) = NULL) { printf("canlt open the console\n R ) : exit(): } stty.sg flags = RAW: ioctl{fileno{fp). TIOCSETP. &sttY)i for (:i){ c = getc ( fp) : } ... } Copyright (c) 1984 by Manx Software Systems, Inc. lib.20 Overview of Console I/O 3. Console input - console in CBREAK + ECHO mode This example modifies the previous program so that characters read from the console are automatically echoed to the display. The program accesses the console via the standard input device. It uses the function isatty to verify that stdin is associated with the console; if it isnlt, the program reopens stdin to the console using the function freopen. Again, the console is assumed to be named Icon:l. ,include "stdio.h" 'include Ilsgtty.h main ( ) ll { int Ci struct sgttyb sttYi if (lisatty(stdin» freopen ( • con: •• II r·. stdin): stty.sg flags = CBREAK I ECHOi ioctl(O; TIOCSETP. &stty): for (ii){ c = getchar()i } } copyright (c) 1984 by Manx Software Systems, Inc. lib.21 Overview of Dynamic Buffer Allocation Several functions are provided for the dynamic allocation and deal location of buffers from a section of memory called the 'heap'. They are: malloc calloc realloc free allocates a buffer allocates a buffer and initializes it to zeroes allocates more space to a previously allocated buffer releases an allocated buffer for reuse In addition, the function sbrk allows users to implement their own dynamic buffer allocation scheme: when passed an integer, sbrk increments an internal pointer by that amount and returns the original value of the pointer. The pointer initially points to the base of the heap. Dynamic allocation of standard i/o buffers Buffers used for standard i/o are dynamically allocated from the heap unless specific actions are taken by the user's program. Standard i/o calls to dynamically allocate and deallocate buffers can be interspersed with those of the user's program. programs which perform standard i/o and which must have absolute control of the heap can explicitly define the buffers to be used by a standard i/o stream. See the standard i/o overview for details. Heap - stack positioning The starting address of a program's heap is assigned when the program is linked. The linker chapter describes how this assignment is made. When a program is activated, a 2048-byte block of memory is reserved for the stack. The location of this block is system dependent, but it's always above the beginning of the heap. The heap's ending address is then set to the beginning of the stack segment. On CP/M, the top of the stack is the base of the CP/M bdoSi on TRSDOS, it's $HIGHi on Apple DOS, it's the base of the DOS file buffers. Buffers can't be allocated above the heap-stack boundary, but nothing prevents the stack from growing below the boundary. This, of course, presents the possibility of the stack overwriting a dynamically allocated buffer. The function rsvstk can be used to change the heap-stack boundary. Copyright (c) 1984 by Manx Software Systems, Inc. lib.22 Overview of Error processing This section discusses error processing which relates to the global integer errno. This variable is modified by the standard i/o, unbuffered i/o, and scientific (eg, sin, sqrt) functions as part of their error processing. The handling of floating point exceptions (overflow, underflow, and division by zero) is discussed in chapter VIII. When a standard i/o, unbuffered i/o, or scientific function detects an error, it sets a code in errno which describes the error. If no error occurs, the scientific functions don't modify errno. If not error occurs, the i/o functions mayor may not modify errno. Also, when an error occurs, o a standard i/o function returns -1 and sets an error flag for the stream on which the error occurred; o an unbuffered i/o function returns -1; o a scientific function returns an arbitrary value. When performing scientific calculations, a program can check errno for errors as each function is called. Alternatively, since errno is modified only when an error occurs, errno can be checked only after a sequence of operations; if it's non-zero, then an error has occurred at some point in the sequence. This latter technique can only be used when no i/o operations occur during the sequence of scientific function calls. Since errno may be modified by an i/o function even if an error didn't occur, a program can't perform a sequence of i/o operations and then check errno afterwards to detect an error. Programs performing unbuffered i/o must check the result of each i/o call for an error. Programs performing standard i/o operations cannot, following a sequence of standard i/o calls, check errno to see if an error occurred. However, associated with each open stream is an error flag. This flag is set when an error occurs on the stream and remains set until the stream is closed or the flag is explicitly reset. Thus a program can perform a sequence of standard i/o operations on a stream and then check the stream s error flag. For more details, see the standard i/o overview section. l Copyright (c) 1984 by Manx Software Systems, Inc. lib.23 ERRORS Overview ERRORS The following table lists the values which may be placed in errno. In addition, positive values may be set in errno following an i/o operation: these are error codes returned by the CP/M bdos. The symbolic values listed below are defined in the header file errno.h. #define ENOENT -1 #define E2BIG -2 #define EBADF -3 #define ENOMEM -4 #define #define #define #define EEXIST EINVAL ENFILE EMFILE -5 -6 -7 -8 #define #define #define #define ENOTTY EACCES ERANGE EDOM -9 -10 -20 -21 file does not exist not used bad file descriptor - file is not open or improper operation requested insufficient memory for requested operation file already exists on creat request invalid argument exceeded maximum number of open files exceeded maximum number of file descriptors ioctl attempted on non-console invalid access request math function value can't be computed invalid argument to math function Copyright (c) 1984 by Manx Software Systems, Inc. lib.24 System Independent Functions This subchapter describes in detail the functions which are common to all Aztec C packages. The chapter is divided into sections, each of which describes a group of related functions. Each section has a name, and the sections are ordered alphabetically by name. Following this introduction is a cross reference which lists each function and the name of the section in which it is described. A section is organized into the following subsections: TITLE Lists the name of the section, a phrase which is intended to catagorize the functions described in the section, and one or more letters in parentheses which specify the libraries containing the section's functions. The letters which may appear corresponding libraries are: C M in parentheses and their c.lib m.lib On some systems, the actual library name may be a variant on the name given above. For example, on TRSDOS, the libraries are named c/lib and m/lib. SYNOPSIS Indicates the types of arguments that the functions described in the section require, and the values they return. For example, the function atof converts character strings into double precision numbers. It is listed in the synopsis as double atof(s) char *s; This means that atof{) returns a value of type double and require~ as an argument a pointer to a character string. Since atof returns a non-integer value, prior to use of the function it must be declared: double atof(); The notation t include II header • h II at the beginning of a synopsis indicates that such a statement should appear at the beginning of any program calling one of the functions described in the section. On Radio Shack systems, a header file can use either a period or a slash to separate the filename from the extent. Copyright (c) 1984 by Manx Software Systems, Inc. lib.2S SYSTEM INDEPENDENT FUNCTIONS That is, the include statement can be as listed above, or #include IIheader/h ll DESCRIPTION Describes the sectionls functions. SEE ALSO Lists relevant sections. A letter in parentheses may follow a section name. This specifies where the section is located: no letter means that the section is in the current subchapter; 10 1 means that itls in the overview subchapter; lSI means that itls in the system dependent subchapter. DIAGNOSTICS Describes the error codes that the section l s functions may return. The section ERRORS presents an overview of error processing. EXAMPLES Gives examples on use of the sectionls functions. Copyright (c) 1984 by Manx Software Systems, Inc. lib.26 SYSTEM INDEPENDENT FUNCTIONS Index to System Independent Functions function SIN GETC PUTC SIN SIN SIN ATOF ATOF ATOF MALLOC FLOOR FERROR CLOSE SIN SINH SIN CREAT EXP FCLOSE FOPEN FERROR FERROR FCLOSE GETS FERROR FLOOR FOPEN PRINTF PRINTF PUTS FREAD MALLOC FOPEN FREXP SCANF FSEEK FSEEK ATOF FREAD GETC GETC GETS GETW STRING IOCTL CTYPE IOCTL FREXP log . . . . . . . . . . . . EXP acos ••••••••.•• agetc ......•... aputc •.•.•.•.•• asin ••..•••.•.. a tan ••••••••••• a tan2 ...••.••.. atof a toi ••.•••.•••. atol ••.....•••• calloc ...•••... ceil ••••••••••• clearerr ••••••• close •••••••.•. cos .•..•••.••.. cosh ••..••••••. cotan ...•.•••.. crea t •.•••••.•. exp ••••.••••••• fclose .•.•••.•• fdopen ••••.•••• feof ••.•••••.•• ferror ••••••••• fflush ••••••••• fgets •••••••••• fileno ••••••••• floor ..•.•••.•• fopen •.••.••••• format .•••••.•. fprintf .••••.•• fputs •..••••••. fread •••.•••••. free •••.•.•..•. freopen •••••.•• frexp •.•••••••• fscanf ••.••...• f seek •••••••••• ftell •••••••••• ftoa •••..•••••• fwrite ••••••••• getc ••••••••••• getchar •.•••••• gets ••••••••••• getw ••••.•••••• index •••••••••• ioctl •••••••••• isalpha •••••••• isatty ••••••.•. ldexp ••.••••••• Copyright (c) 1984 by Manx Software Systems, Inc. lib.27 SYSTEM INDEPENDENT FUNCTIONS log 10 ••••••.••. long jmp •..••••• lseek ••••••.••. malloc ........ . movmem ••••••••. modf ••.••••.••. open •.•..••.•.• pow ••.••.•...•• printf •••...•.. putc •.•••....•• putchar •.••.••• puterr .•....••• puts •.•••....•• putw •...•....•• ran •••.•••..... read •..••....•. rename .•....••• rindex •........ scanf ........•. setbuf setjmp •.•...••. setmem .•..••••. sin ............ . sinh •.••.•••... sprintf •••.•.•. sqrt .•..••••••• sscanf strcat strcmp strcpy strlen strncat strncmp strncpy swapmem tan •••••••••••• tanh ••••••••..• tolower •.•••••• toupper .••••••• ungetc ••••.•••. unlink ••.•••••• write •••••••••• EXP SETJMP LSEEK MALLOC MOVMEM FREXP OPEN EXP PRINTF PUTC PUTC PUTC PUTS PUTC RAN READ RENAME STRING SCANF SETBUF SETJMP MOVME~l SIN SINH PRINTF EXP SCANF STRING STRING STRING STRING STRING STRING STRING MOVMEM SIN SINH TOUPPER TOUPPER UNGETC UNLINK WRITE Copyright (c) 1984 by Manx Software Systems, Inc. lib.28 Function Definitions ATOF (e. M) utility Functions ATOF NAME atof, atoi, atol - convert ASCII to numbers ftoa - convert floating point to ASCII SYNOPSIS double atof(cp) char *cp; atoi(cp) char *cp: long atol(cp) char *cp: ftoa(val, buf, precision, type) double val: char *buf: int precision, type: DESCRIPTION atof, atoi, and atol convert a string of text characters pointed at by the argument cp to double, integer, and long representations, respectively. atof recognizes a string containing leading blanks and tabs, which it skips, then an optional sign, then a string of digits optionally containing a decimal point, then an optional lei or lEI followed by an optionally signed integer. atoi and atol recognize a string containing leading blanks and tabs, which are ignored, then an optional sign, then a string of digits. ftoa converts a double precision floating point number to ASCII. val is the number to be converted and buf points to the buffer where the ASCII string will be placed. precision specifies the number of digits to the right of the decimal point. type specifies the format: 0 for "E" format, 1 for "F" format, 2 for "G" format. atof and ftoa are in the library m.1ib: the other functions are in c.1ib. copyright (c) 1984 by Manx Software Systems, Inc. lib.29 CLOSE (C) unbuffered I/O Function CLOSE NAME close - close a device or file SYNOPSIS close(fd) int fd; DESCRIPTION close closes a device or disk file which is opened for unbuffered i/o. The parameter fd is the file descriptor associated with the file or device. If the device or file was explicitly opened by the program by calling open or creat, fd is the file descriptor returned by open or create close returns 0 as its value if successful. SEE ALSO UNBUFFERED I/O (0), ERRORS (0) DIAGNOSTICS If close fails, it returns -1 and sets an error code in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.30 CREAT (c) Unbuffered I/O Function CHEAT KAME creat - create a new file SYBOPSIS creat(name, pmode) char *name: int pmode: DESCRIPTION creat creates a file and opens it for unbuffered, write-only access. If the file already exists, it is truncated so that nothing is in it (this is done by erasing and then creating the file). creat returns as its value an integer called a "file descriptor". Whenever a call is made to one of the unbuffered i/o functions to access the file, its file descriptor must be included in the function's parameters. The parameter name is a pointer to a character string which is the name of the device or file to be opened. See the I/O overview section for details. The parameter pmode is optional. If specified, it is ignored. The pmode parameter should be included, however, for programs for which UNIx-compatibility is required, since the UNIX creat function requires it. In this case, pmode should have an octal value of 0666. SEE ALSO UNBUFFERED I/O (0), ERRORS (0) DIAGNOSTICS If creat fails, it returns -1 as its value and sets a code in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.31 CTYPE (e) utility Functions C'l'YPE NAME isalpha, isupper, islower, isdigit, ispunct, isprint, iscntrl, isascii - character clasification functions isalnum, isspace, SYNOPSIS tinclude ··ctype.h" isalpha(c) DESCRIPTION These macros classify ASCII-coded integer lookup, returning nonzero if the integer is zero otherwise. isascii is defined for all The others are defined only when isascii is single non-ASCII value EOF (-1). isalpha isupper islower isdigit isalnum isspace ispunct isprint iscntrl isascii values by table in the catagory, integer values. true and on the c c c c c c is a letter is an upper case letter is a lower case letter is a digit is an alphanumeric character is a space, tab, carriage return, newline, or formfeed c is a punctuation character c is a printing character, valued Ox20 (space) through Ox7e (tilde) c is a delete character (Oxff) or ordinary control character (value less than Ox20) c is an ASCII character, code less than OxlOO Copyright (c) 1984 by Manx Software Systems, Inc. lib.32 EXP (M) Math Functions EXP NAME exponential, logarithm, power, square root functions: exp, log, 10glO, pow, sqrt SYNOPSIS double exp{x) double x·, double log{x) double x·, double 10glO{x) double x·, double pow{x, Y) double X,Yi double sqrt{x) double x·, DESCRIPTION exp returns the exponential function of x. log returns the natural logarithm of x: 10glO returns the base 10 logarithm. pow returns x ** y ( x to the y-th power). sqrt returns the square root of x~ SEE ALSO ERRORS DIAGNOSTICS If a function can't perform the computation, it sets an error code in the global integer errno and returns an arbitrary value: otherwise it returns the computed value without modifying errno. The symbolic values which a function can place in errno are EDOM, signifying that the argument was invalid, and ERANGE, meaning that the value of the function couldn't be computed. These codes are defined in the file errno.h. Copyright (c) 1984 by Manx Software Systems, Inc. lib.33 EXP (M) Math Functions EXP The following table lists, for each function, the error codes that can be returned, the function value for that error, and the meaning of the error. The symbolic values are defined in the file math.h. Ifunction I error f(x) Meaning I ------------------------------------------------------exp II log 10glO pow II II sqrt ERANGE ERANGE EDOM EDOM EDOM ERANGE ERANGE EDOM HUGE 0.0 -HUGE -HUGE -HUGE HUGE 0.0 0.0 I I X <= a I X <= o I x < 0, x=y=O I y*log(x) >LOGHUGE I y*log(x) LOG HUGE x < LOGTINY Copyright (c) 1984 by Manx software Systems, Inc. lib. 34 FCLOSE (c) Standard I/O Functions FCLOSE NAME fclose, fflush - close or flush a stream SYNOPSIS 'include ··stdio.h ll fclose(stream) FILE * stream: fflush(stream) FILE * stream: DESCRIPTION fclose informs the system that the user's program has completed its buffered i/o operations on a device or file which it had previously opened (by calling fopen). fclose releases the control blocks and buffers which i t had allocated to the device or file. Also, when a file is being closed, fclose writes any internally buffered information to the file. fclose is called automatically by exit. fflush causes any buffered information for the named output stream to be written to that file. The stream remains open. If fclose or fflush is successful, value. SEE ALSO STANDARD it returns 0 as its r/o (0) DIAGNOSTICS If the operation fails, -1 is returned, and an error code is set in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.3S FERROR (c) standard I/O Functions FERROR NAME feof, ferror, clearerr, fileno - stream status inquiries SYNOPSIS t include II stdio • h II feof(stream) FILE * stream; ferror(stream) FILE * stream; clearerr(stream) FILE *stream; fileno(stream) FILE *stream; DESCRIPTION feof returns non-zero when end-of-file is reached on the specified input stream, and zero otherwise. ferror returns non-zero when an error has occurred on the specified stream, and zero otherwise. Unless cleared by clearerr, the error indication remains set until the stream is closed. clearerr resets an error indication on the specified stream. fileno returns the integer file descriptor associated with the stream. These functions are defined as macros in the file stdio.h. SEE ALSO STANDARD I/O (0) copyright (c) 1984 by Manx software Systems, Inc. lib.36 FLOOR Math utility Functions (M) FLOOR NAME fabs, floor, ceil - absolute value, floor, ceiling routines SYNOPSIS double floor(x) double X·• double ceil(x) double X·• double fabs(x) double X·• DESCRIPTION fabs returns the absolute value of x. floor returns the largest integer not greater than x. ceil returns the smallest integer not less than x. Copyright (c) 1984 by Manx Software Systems, Inc. lib.37 FOPEN (c) standard I/O Functions FOPEN NAME fopen, freopen, fdopen - open a stream SYNOPSIS 'include Iistdio.h li FILE *fopen(filename, mode) char * filename , *mode; FILE *freopen{filename, mode, stream) char *filename, *mode; FILE *stream: FILE *fdopen(fd, mode) char *mode; DESCRIPTION These functions prepare a device or disk file for access by the standard i/o functions; this is called "opening" the device or file. A file or device which has been opened by one of these functions is called a "stream". If the device or file is successfully opened, these functions return a pointer, called a "file pointer to a structure of type FILE. This pointer is included in the list of parameters to buffered i/o functions, such as getc or putc, which the user's program calls to access the stream. ll fopen is the most basic of these functions: it simply opens the device or file specified by the filename parameter for access specified by the mode parameter. These parameters are described below. freopen substitutes the named device or file for the device or file which was previously associated with the specified stream. It closes the device or file which was originally associated with the stream and returns stream as its value. It is typically used to associate devices and files with the preopened streams stdin, stdout, and stderr. fdopen opens a device or file for buffered i/o which has been previously opened by one of the unbuffered open functions open and create It returns as it's value a FILE pointer. fdopen is passed the file descriptor which was returned when the device or file was opened by open or create It's also passed the mode parameter specifying the type of access desired. mode must agree with the mode of the open file. The parameter filename is a pointer to a character string which is the name of the device or file to be opened. For details, see the I/O overview section. Copyright (c) 1984 by Manx Software systems, Inc. lib.38 Standard I/O Functions POPER (c) FOPER mode points to a character string which specifies how the user's program intends to access the stream. The choices are as follows: mode meaning "r" Open for reading only. If a file is opened, i t is positioned at the first character in it. If the file or device does not exist, NULL is returned. "w" Open for writing only. If a file is opened which already exists, it is truncated to zero length. If the file does not exist, it is created. "a" Open for appending. The calling program is granted write-only access to the stream. The current file position is the character after the last character in the file. If the file does not exist, it is created. "x" Open for writing. The file must previously exist. This option is supported by Unix. "r+" Open for reading and writing. Same as "r", but the stream may also be written to. "w+" Open for writing and reading. Same as "w", but the stream may also be read; different from "r+" in the creation of a new file and loss of any previous one. lIa+" Open for appending and reading. Same as "a", but the stream may also be read; different from "r+" in file positioning and file creation. "X+" Open for writing and reading. Same as "x" but the file can also be read. not not On systems which don't keep track of the last character in a file (for example CPM and Apple DOS), not all files can be correctly positioned when opened in append mode. See the I/O overview section for details. SEE ALSO I/O (0), STANDARD I/O (0) DIAGNOSTICS If the file or device cannot be opened, NULL is returned and an error code is set in the global integer errno. Copyright (c) 1984 by Manx Software systems, Inc. lib.39 FOPER (e) FOPER Standard I/O Functions EXAMPLES The following example demonstrates how fopen can be used in a program. #include IIstdio.h ll main(argc,argv) char **argvi [ FILE *fopen(), *fPi if «fp = fopen(*argv[l], *argv[2])) == NULL) { printf(lIyoU asked me to open %s",*argv[l])i printf(lIin the %s mode", *argv[2])i printf("but I can ' tl\n")i else printf("%s is open\n", *argv[l])i 1 Here is a program which uses freopen: #include IIstdio.h" main ( ) { FILE *fPi fp = freopen ( "dskfile ", "W+", stdout); printf( "This message is going to dskfile\n") i 1 Here is a program which uses fdopen: #include "stdio.h ll dopen it(fd) int fd; /* value returned by previous call to open */ [ FILE *fPi if « fp = fdopen ( fd , r+ == NULL) printf(lIcan't open file for r+\n"); else return (fp) i II II ) ) 1 Copyright (c) 1984 by Manx Software Systems, Inc. lib.40 FREAD (C) standard I/O Function FREAD NAME fread, fwrite - buffered binary input/output SYNOPSIS 'include "stdio.h" int fread(buffer, size, count, stream) char *buffer; int size, count; FILE *stream; int fwrite(buffer, size, count, stream) char *buffer; int size, count; FILE *stream; DESCRIPTION fread performs a buffered input operation and fwrite a buffered write operation to the open stream specified by the parameter stream. buffer is the address of the user's buffer which will be used for the operation. The function reads or writes count items, each containing size bytes, from or to the stream. fread and fwrite perform i/o using the functions getc and putc: thus, no translations occur on the data being transferred. The function returns as actually read or written. its value the number of items SEE ALSO STANDARD I/O (0), FOPEN, ERRORS (0), FERROR DIAGNOSTICS fread and fwrite return 0 upon end of file or error. The functions feof and ferror can be used to distinguish between the two. In case of an error, the global integer errno contains a code defining the error. Copyright (c) 1984 by Manx Software Systems, Inc. lib.41 FREAD (C) standard I/O Function FREAD EXAMPLE This is the code for reading ten integers from file 1 and writing them again to file 2. It includes a simple check that there are enough two-byte items in the first file: #include IIstdio.h ll main () { FILE *fpl, *fp2, *fopen(); char *buf; int size = 2, count = 10; fpl = fopen(lIfilelll,lIrll); fp2 = fopen ( II file2 11 , "w ll ) ; if (fread(buf, size, count, fpl) != count) printf( IINot enough integers in filel \n ll ); fwrite(buf, size, count, fp2); } Copyright (c) 1984 by Manx Software systems, Inc. lib.42 Math Functions FREXP (M) FREXP NAME frexp, ldexp, modf - build and unbuild real numbers SYHOPSIS double frexp(value, eptr) double value: int *eptr: double ldexp(value, exp) double value: double modf(value, iptr) double value, *iptr: DESCRIPTIO:N frexp computes for its argument, arg, a double quantity x and an integer quantity n such that value = x*2**n. x is returned as the value of frexp, and n is returned in the integer field pointed at by eptr. ldexp returns the double quantity value*2**exp. modf returns as its value the positive fractional part of value and stores the integer part in the double field pointed at by iptr. Copyright (c) 1984 by Manx Software Systems, Inc. lib.43 FSEEK (c) Standard I/O Functions FSEEK NAME fseek, ftell - reposition a stream SYNOPSIS 'include ··stdio.h ll int fseek(stream, offset, origin) FILE *stream; long offset; int origin; long ftell(stream) FILE *stream; DESCRIPTION fseek sets the "current position" of a file which has been opened for buffered i/o. The current position is the byte location at which the next input or output operation will begin. stream is the stream identifier associated with the file, and was returned by fopen when the file was opened. offset and origin together specify the current position: the new position is at the signed distance offset bytes from the beginning, current position, or end of the file, depending on whether origin is 0, 1, or 2, respectively. offset can be positive or negative, to position after or before the specified origin, respectively, with the limitation that you can't seek before the beginning of the file. For some operating systems (for example, CP~l and Apple DOS) a file may not be able to be correctly positioned relative to its end. See the overview sections I/O and STANDARD I/O for details. If fseek is successful, it will return zero. ftell returns the number of bytes from the beginning to the current position of the file associated with stream. SEE ALSO STANDARD I/O (0), I/O (0), LSEEK DIAGNOSTICS fseek will return -1 for improper seeks. In this case, an error code is set in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.44 FSEEK Standard I/O Functions (c) FSEEK EXAMPLE The following routine "a+" mode: a plus(filename) char *filenamei is equivalent to opening a file in { FILE *fp, *fopen()i if «fp = fopen(filename, r+» == NULL) fp = fopen(filename, W+)i fseek(fp, OL, 2)i /* position 1 byte past last character */ } To set the current position back 5 characters before the present current position, the following call can be used: fseek(fp, -5L, 1) Copyright (c) 1984 by Manx Software Systems, Inc. lib.45 GE'l'C (c) Standard I/O Function GETC NAME getc, agetc, getchar, getw SYNOPSIS 'include "stdio.h " int getc(stream) FILE *stream: int agetc(stream) FILE *stream: /* non-Unix function */ int getchar() int getw(stream) FILE *stream: DESCRIPTION getc returns the next character from the specified input stream. agetc is used to access files of text. It generally behaves like getc and returns the next character from the named input stream. It differs from getc in the following ways: o it translates end-of-line sequences (eg, carriage return on Apple DOS; carriage return-line feed on CPM) to a single newline (I\n l ) character. o it translates an end-of-file sequence (eg, a null character on Apple DOS; a control-z character on CPM) to EOF; o it ignores null characters (1\0 1) on all systems except Apple DOS; o the most significant bit of each character returned is set to zero. agetc is not a Unix function. It is, however, provided with all Aztec C packages, and provides a convenient, systemindependent way for programs to read text. getchar returns text characters from the standard input stream (stdin). It is implemented as the call agetc(stdin). getw returns the next word from the specified input stream. It returns EOF (-1) upon end-of-file or error,- but since that is a good integer value, feof and ferror should be used to check the success of getw. It assumes no special alignment in the file. SEE ALSO I/O (0), STANDARD I/O (0), FOPEN, FCLOSE DIAGNOSTICS These functions return EOF (-1) at end of file or if an error occurs. The functions feof and ferror can be used to distinguish the two. In the latter case, an error code is Copyright (c) 1984 by Manx Software Systems, Inc. lib.46 GETC (c) Standard I/O Function GETC set in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.47 GETS (C) Standard I/O Functions GETS NAME gets, fgets - get a string from a stream SYNOPSIS t incl ude n stdio • h II char *gets(s) char *s; char *fgets(s. n, stream) char *s; FILE *stream: DESCRIPTION gets reads a string of characters from the standard input stream, stdin, into the buffer pointed by 5. The input operation terminates when either a newline character (\n) or end of file is encountered. fgets reads characters from the specified input stream into the buffer pointer at by s until either (1) n-l characters have been read, (2) a newline character (\n) is read, or (3) end of file or an error is detected on the stream. Both functions return 5, except as noted below. gets and fget5 differ in their handling of the newline character: gets doesn't put it in the caller's buffer, while fgets does. This is the behavior of these functions under UNIX. These functions get characters using agetc: thus they can only be used to get characters from devices and files which contain text characters. SEE ALSO I/O (0), STfu~DARD I/O (0), FERROR DIAGNOSTICS gets and fgets return the pointer NULL (0) upon reaching end of file or detecting an error. The functions feof and ferror can be used to distinguish the two. In the latter case, an error code is placed in the global integer errno.· Copyright (c) 1984 by Manx Software Systems, Inc. lib.48 IOCTL (c) I/O function IOCTL NAME ioctl, isatty - device i/o utilities SYNOPSIS 'include "sgtty.h" ioctl(fd, cmd, stty) struct sgttyb *stty: isatty(fd) DESCRIPTION ioctl sets and determines the mode of the -console. For more details on ioctl, I/O. see the overview section CONSOLE isatty returns non-zero if the file descriptor associated with the console, and zero otherwise. fd is SEE ALSO CONSOLE I/O (0) Copyright (c) 1984 by Manx Software Systems, Inc. lib.49 LSEEK (c) Unbuffered I/O Function LSEEK NAME lseek - change current position within file SYNOPSIS long int lseek(fd, offset, origin) int fd, origin; long offset; DESCRIPTION lseek sets the current position of a file which has been opened for unbuffered i/o. This position determines where the next character will be read or written. fd is the file descriptor associated with the file. The current position is set to the location specified by the offset and origin parameters, as follows: If origin is A, the current position is set to offset bytes from the beginning of the file. If origin is I, the current position is set to the current position plus offset. If origin is 2, the current position is set to the end of the file plus offset. The offset can be positive or negative, to position after or before the specified origin, respectively. positioning of a file relative to its end (that is, calling lseek with origin set to 2) cannot always be correctly done on all systems (for example, CPM and Apple DOS). See the section entitled I/O for details. If lseek is successful, it will return the new position in the file (in bytes from the beginning of the file). SEE ALSO UNBUFFERED I/O (0), I/O (0) DIAGNOSTICS If Iseek fails, it will return -1 as its value and set an error code in the global integer errno. errno is set to EBADF if the file descriptor is invalid. It will be set to EINVAL if the offset parameter is invalid or if the requested position is before the beginning of the file. EXAMPLES 1. To seek to the beginning of a file: 1 see k ( fd, aL , 0); Copyright (c) 1984 by Manx Software Systems, Inc. lib.50 (e) LSEEK Unbuffered I/O Function LSEEK lseek will return the value zero (O) since the current position in the file is character (or byte) number zero. 2. To seek to the character following the last character in the file: pos = Iseek(fd, OL, 2}: The variable, pos, will contain the current position of the end of file, plus one. 3. To seek backward five bytes: 1 see k ( fd, - 5 L , I ) : The parameter, 1, sets the origin at the current position in the file. The offset is -5. The new position will be the origin plus the offset. So the effect of this call is to move backward a total of five characters. 4. To skip five characters when reading in a file: read(fd, buf, count}: Iseek (fd, 5L, I): read(fd, buf, count}: Copyright (c) 1984 by Manx Software systems, Inc. lib.51 MALLOC (c) Memory Management Functions MALLOC NAME malloc, free, calloc, - memory allocation SYNOPSIS char *malloc(size) unsigned size: char *calloc(nelem, elemsize) unsigned nelem, elemsize; char *reaIloc(ptr, size) char *ptr; unsigned size: free(ptr) char *ptr: DESCRIPTION These functions are used to allocate memory from the "heap", that is, the section of memory available for dynamic storage allocation. malloc allocates a block of size bytes, pointer to it. and returns a calloc allocates a single block of memory which can contain nelem elements, each elemsize bytes big, and returns a pointer to the beginning of the block. Thus, the allocated block will contain (nelem * elemsize) bytes. The block is initialized to zeroes. realloc changes the size of the block pointed at by ptr to size bytes, returning a pointer to the block. If necessary, a new block will be allocated of the requested size, and the data from the original block moved into it. The block passed to realloc can have been freed, provided that no intervening calls to cailoc, malloe, or realloc have been made. free deal locates a block of memory which was previously allocated by malloe, calloe, or realloci this space is then available for reallocation. The argument ptr to free is a pointer to the block. maiioc and free maintain a circular list of free blocks. When called, malloc searches this list beginning with the last block freed or allocated coalescing adjacent free blocks as it searches. It allocates a buffer from the first large enough free block that it encounters. If this search fails, it calls sbrk to get more memory for use by these functions. SEE ALSO MEMORY USAGE (0), BREAK (S) Copyright (c) 1984 by Manx Software Systems, Inc. lib.52 MALLOC (c) Memory Management Functions MALLOC DIAGNOSTICS ma11oc, ca110c and rea110c return a null pointer (0) if there is no available block of memory. free returns -1 if it's passed an invalid pointer. Copyright (c) 1984 by Manx Software Systems, Inc. 1ib.53 MOVMEM (c) utility Functions MOVMEM movmem, setmem, swapmem SYNOPSIS movmem(src, dest, length) char *src, *dest; int length; setmem(area, char *area; length, value) swapmem(sl. s2. len) char *sl, *s2; /* non-unix function */ /* non-Unix function */ /* non-Unix function */ DESCRIPTION movmem copies length characters from the block of memory pointed at by src to that pointed at by dest. movmem copies in such a way that the resulting block of characters at dest equals the original block at src. setmem sets the character value in each byte of the block of memory which begins at area and continues for length bytes. swapmem swaps the blocks of memory pointed at by s1 and s2. The blocks are len bytes long. Copyright (c) 1984 by Manx Software systems, Inc. lib.54 OPEN (C) Unbuffered I/O Functions OPER open SYBOPSIS t inc1ude • fcnt1. h II open ( name. mode) char *name; DESCRIPTION This function will open a device or file for unbuffered i/o. It returns an integer value called a file descriptor which is used to identify the file or device in subsequent calls to unbuffered i/o functions. The parameter name is a pointer to a character string which is the name of the device or file to be opened. For details, see the overview section I/O. The parameter mode specifies how the user's program intends to access the file. The choices are as follows: mode o RDONLY O-WRONLY o RDWR O-CREAT o TRUNC O-EXCL o APPEND meaning read only write only read and write Create file, then open it Truncate file, then open it Cause open to fail if file already exists; used with 0 CREAT position file for appending data These open modes are integer constants defined in the files fcntl.h. Although the true values of these constants can be used in a given call to open, use of the symbolic names ensures compatibility with UNIX and other systems. The calling program must specify the type of access desired by including exactly one of 0 RDONLY, 0 WRONLY, and 0 RDWR in the mode parameter. The-three remaining values are optional. They may be included by adding them to the mode parameter, as in the examples below. By default, the open will fail if the file to be opened does not exist. To cause the file to be created when it does not already exist, specify the 0 CREAT option. If 0 EXCL is given in addition to 0 CREAT, the open will fail if-the file already exists; otherwise, the file is created. If the 0 TRUNC option is specified, the file will be truncated so that nothing is in it. The truncation is performed by simply erasing the file, if it exists, and then creating it. So it is not an error to use this option when the file does not exist. Copyright (c) 1984 by Manx Software Systems, Inc. 1ib.55 OPEN (C) Unbuffered I/O Functions OPER Note that when 0 TRUNC is used, O_CREAT is not needed. If O_APPEND is specified, the current position for the file (that is, the position at which the next data transfer will begin) is set to the end of the file. For systems which don't keep track of the last character written to a file (for example, CPM and Apple DOS), this positioning cannot always be correctly done. See the I/O overview section for details. Also, this option is not supported by UNIX. If open does not detect an error, it returns an integer called a ufile descriptor." This value is used to identify the open file during unbuffered i/o operations. The file descriptor is very different from the file pointer which is returned by fopen for use with buffered i/o functions. SEE ALSO I/O (O), UNBUFFERED I/O (O), ERRORS (O) DIAGNOSTICS If open encounters an error, it returns -1 and sets the global integer errno to a symbolic value which identifies the error. Copyright (c) 1984 by Manx Software Systems, Inc. lib.56 OPEN (C) Unbuffered I/O Functions OPEN EXAMPLES 1. To open the file, testfile, for read-only access: fd = open("testfile", O_RDONLY): If testfile does not exist open will just return -1 and set errno to ENOENT. 2. To open the file, fd = subl, open ( subl ll II , for read-write access: 0 RD\'JR+O CREAT): If the file does not exist, opened. 3. it will be created and then The following program opens a file whose name is given on the command line. The file must not already exist. main(argc, argv) char **argv: { int fd: fd = open(*++argv, 0 WRONLY+O CREAT+O_EXCL); if (fd = -1) { if (errno == EEXIST) printf("file already exists\n"): else if (errno == ENOENT) printf(" unable to open file\n else printf("open error\n"); ll ); } Copyright (c) 1984 by Manx Software Systems, Inc. lib.57 PRIN'l'F Standard I/O Functions ( C. M) PRIRTF NAME printf, fprintf, sprintf - formatted output conversion functions SYNOPSIS t include II stdio. h" printf(fmt [.arg] ••• ) char *fmt; fprintf(stream. fmt [.arg] ••• ) FILE * stream; char *fmt; sprintf(buffer, fmt [,arg] ••• ) char *buffer, *fmt; format(func, fmt. argptr) int (*func) (); char *fmt; unsigned *argptr; DESCRIPTION These functions convert and format their arguments (arg or argptr) according to the format specification fmt. They differ in what they do with the formatted result: printf outputs stream, stdout: the result to the standard output fprintf outputs the resul t to the stream specified in its first argument, stream: sprintf places the result in the buffer pointed at by its first argument, buffer, and terminates the result with the null character, '\0'. format calls the function func with each character of the result. These functions are in both c.lib and m.lib, the difference being that the c.lib versions don't support floating point conversions. Hence, if floating point conversion is required, the m.lib versions must be used. If floating point conversion isn't required, either version can be used. To use m.lib's version, m.lib must be specified before c.lib at the time the program is linked. The character string pointed at by the fmt parameter, which directs the print functions, contains two types of items: ordinary characters, which are simply output, and conversion specifications, each of which causes the conversion and output of the next successive arg. Copyright (c) 1984 by Manx software Systems, Inc. lib. 58 PRIH'l'F ( C. M) Standard I/O Functions PRINTF A conversion specification begins with the character % and continues with: o an optional minus sign (-) which specifies left adjustment of the converted value in the output field; o an optional digit string specifying the 'field width' for the conversion. If the converted value has fewer characters than this, enough blank characters will be output to make the total number of characters output equals the field width. If the converted value has more characters than the field width, it will be truncated. The blanks are output before or after the value, depending on the presence or absence of the leftadjustment indicator. If the field width digits have a leading 0, a is used as a pad character rather than blank. o an optional period, '.', which separates the field width from the following field; o an optional digit string specifying a precision: for floating point conversions, this specifies- the number of digits to appear after the decimal point; for character string conversions, this specifies the maximum number of characters to be printed from a string; o optionallYI the character 1, which specifies that a conversion which normally is performed on an int is to be performed on a long. This applies to the d, 0, and x conversions. o a character which specifies the type of conversion to be performed. A field width or precision may be * instead of a number, specifying that the next available arg, which must be an int, supplies the field width or precision. The conversion characters are: d, or x The int in the corresponding arg is converted to decimal, octal, or hexadecimal notation, respectively, and output; 0, u The unsigned integer arg is converted to decimal notation; c The character arg is output. ignored; s The characters in the string pointed at by arg are output until a null character or the number of Null characters are Copyright (c) 1984 by Manx Software Systems, Inc. lib.59 (e, M) PRIN'l'P Standard I/O Functions PRIBTP characters indicated by the precision is reached. If the precision is zero or missing, all characters in the string, up the terminating null, are output: f The float or double arg is converted to decimal notation in the style '[-Jddd.ddd ' . The number of dis after the decimal point is equal to the precision given in the conversion specification. If the precision is missing, i t defaults to six digits. If the precision is explicitly 0, the decimal point is also not printed. e The float or double arg is converted to the style '[-Jd.ddde[-Jdd ' , where there is one digit before the decimal point and the number after is equal to the precision given. If the precision is missing, i t defaults to six digits. 9 The float or double arg is printed in style d, f, or e, whichever gives full precision in minimum space. % output a %. No argument is converted. SEE ALSO STANDARD I/O (0) EXAMPLES 1. The following program fragment: char *name: float amt: printf("your total, %s, is $%f\n", name, amt): will print a message of the form your total, Alfred, is $3.120000 Since the precision of the %f conversion wasn't specified, i t defaulted to six digits to the right of the decimal point. 2. This example modifies example 1 so that the field width for the %s conversion is three characters, and the field width and precision of the %f conversion are 10 and 2, respectively. The %f conversion will also use 0 as a pad character, rather than blank. char *name: float amt: printf("your total, %3s, is $%10.2f\n", name, amt): 3. This example modifies example 2 so that the field width of the %s conversion and the precision of the %f conversion are taken from the variables nw and ap: char *name: float amt: int nw, api printf("your total %*s, is $%10.*f\n", nw, name, ap, amt)i Copyright (c) 1984 by Manx Software Systems, Inc. lib.60 PRIN'l'F ( C. M) Standard I/O Functions Copyright (c) 1984 by Manx Software Systems, Inc. PRIIITF 1ib.61 PUTC (c) Standard I/O Functions PU'1'C NAME putc, aputc, putchar, putw, puterr - put character or word to a stream SYNOPSIS linc1ude ·stdio.h" putc(c, stream) char c: FILE *stream: aputc(c, stream) char c: FILE *stream: /* non-Unix function */ putchar(c) char c: putw(w,stream) FILE *stream; puterr(c) char c: /* non-Unix function */ DESCRIPTION putc writes the character c to the named output stream. It returns c as its value. aputc is used to write text characters to files and devices. It generally behaves like putc, and writes a single character to a stream. It differs from putc as follows: o when a newline character is passed to aputc, an endof-line sequence (eg, carriage return followed by line feed on CPM, and carriage return only on Apple DOS) is written to the stream; o the most significant bit of a character is set to zero before being written to the stream. aputc is not a Unix function. It is, however, supported on all Aztec C systems, and provides a convenient, systemindependent way for a program to write text. putchar writes the character c to the standard output stream, stdout. It's 'identical to aputc(c, stdout). putw writes the word w to the specified stream. It returns w as its value. putw neither requires nor causes special alignment in the file. puterr writes the character c to the standard error stream, stderr. It's identical to aputc(c, stderr). It is not a Unix function. Copyright (c) 1984 by Manx Software Systems, Inc. lib.62 PUTC (c) Standard I/O Functions PU'l'C SEE ALSO STANDARD I/O DIAGNOSTICS These functions return EOF (-1) upon error. In this case, an error code is set in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.63 PUTS (C) Standard I/O Functions PUTS NAME puts, fputs - put a character string on a stream SYNOPSIS 'include ··stdio.h ll puts(s) char *s: fputs(s, stream) char *s: FILE *stream: DESCRIPTION puts writes the null-terminated string s to the standard output stream, stdout, and then an end-of-line sequence. It returns a non-negative value if no errors occur. fputs copies the null-terminated string s to the specified output stream. It returns 0 if no errors occur. Both functions wr i te to the stream using aputc. Thus, they can only be used to write text. See the PUTC section for more details on aputc. Note that puts and fputs differ in this way: On encountering a newline character, puts writes an end-of-line sequence and fputs doesn't. SEE ALSO STANDARD I/O (0), PUTC DIAGNOSTICS If an error occurs, these functions return EOF (-1) and set an error code in the global integer errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.64 QSOR'l' qsort utility Function QSORT sort an array of records in memory SYBOPSIS qsort (array, number, width, func) char *array: unsigned number: unsigned width: int (*func)(). DESCRIP'lIOH qsort sorts an array of elements using Hoare's Quicksort algorithm. array is a pointer to the array to be sorted; number is the number of record to be sorted; width is the size in bytes of each array element; func is a pointer to a function which is called for a comparison of two array elements. func is passed pointers to the two elements being compared. It must return an integer less than, equal to, or greater than zero, depending on whether the first argument is to be considered less than, equal to, or greater than the second. Copyright (c) 1984 by Manx Software Systems, Inc. lib.65 QSORT utiiity Function QSORT EXAMPLE The Aztec linker, LN, can generate a file of text containing a symbol table for a program. Each line of the file contains an address at which a symbol is located, followed by a space, followed by the symbol name. The following program reads such a symbol table from the standard input, sorts it by address, and writes it to standard output. #include "stdio.h" #define MAXLINES 2000 #define LINESIZE 16 char *lines[MAXLINES]: main ( ) { int i,numlines, cmp(): char buf[LINESIZE]: for (nurnlines=O; numlines XMAX abs(x) > XMAX abs(x) > XMAX O = XMAX abs(x) > 1.0 abs(x) > 1.0 x = y = a Copyright (c) 1984 by Manx Software Systems, Inc. lib.81 SINH (M) Math Functions SINH NAME sinh, cosh, tanh SYNOPSIS doub1e sinh(x) doub1e X·• doub1e cosh{x) doub1e X·• doub1e tanh(x) doub1e X·• DESCRIPTION These functions compute the hyperbolic functions of their arguments. SEE ALSO ERRORS DIAGNOSTICS If the absolute value of the argument to sinh or coshis to greater than 348.6, the function sets the symbolic value ERANGE in the global integer errno and returns a huge value. This code is defined in the file errno.h. If no error occurs, the function returns the computed value without modifying errno. Copyright (c) 1984 by Manx Software Systems, Inc. lib.82 STRING (e) utility Functions STRING NAME strcat, strncat, strcmp, strncmp, strcpy, rindex - string operations strlen, index, SYNOPSIS char *strcat(sl, s2} char *sl, *s2; char *strncat(sl, s2} char *sl, *s2; strcmp(sl, s2} char *sl, *s2; strncmp(sl, s2, n} char *sl, s2: char *strcpy(sl, s2) char *sl, *s2; char *strncpy(sl, 52, n} char *sl, *s2; strlen(s) char *s; char *index(s, c) char *s: char *rindex(s, c) char *s: DESCRIPTION These functions follows: operate on null-terminated strings, as strcat appends a copy of string s2 to string sl. strncat copies at most n characters. Both terminate the resulting string with the null character (\0) and return a pointer to the first character of the resulting string. strcmp compares its two arguments and returns an integer greater than, equal, or less than zero, according as sl is lexicographically greater than, equal to, or less than s2. strncmp makes the same comparison but looks at n characters at most. strcpy copies string s2 to sl stopping after the null character has been moved. strncpy copies exactly n characters: if s2 contains less than n characters, null characters will be appended to the resulting string until n characters have been moved; if s2 contains n or more characters, only the first n will be moved, and the resulting string will not be null terminated. Copyright (c) 1984 by Manx Software Systems, Inc. 1ib.83 STRING (C) utility Functions STRING strlen returns the number of characters which occur in s up to the first null character. index returns a pointer to the first occurrance of the character c in string s, or zero if c isn't in the string. rindex returns a pointer to the last occurrance of the character c in string s, or zero if c isn't in the string. Copyright (c) 1984 by Manx Software Systems, Inc. lib.84 TOUPPER (c) Utility Functions TOUPPER NAME toupper, tolower SYNOPSIS toupper(c) tolower(c) 'include Ilctype .h ll _toupper(c) _to lower (c) DESCRIPTION toupper converts a lower case character to upper case: if c is a lower case character, toupper returns its upper case equivalent as its value, otherwise c is returned. tolower converts an upper case character to lowr case: if c is an upper case character tolower returns its lower case equivalent, otherwise c is returned. toupper and tolower do not require the header file ctype.h. _toupper and tolower are macro versions of toupper and tolower, respectively. They are defined in ctype.h. The difference-between the two sets of functions is that the macro versions will sometimes translate non-alphabetic characters, whereas the function versions don't. Copyright (c) 1984 by Manx software Systems, Inc. lib.8S UNGETC (c) standard I/O Functions UBGETC NAME ungetc - push a character back into input stream SYNOPSIS 'include ··stdio.h" ungetc(c. stream) FILE *stream: DESCRIPTION ungetc pushes the character c back on an input stream. That character will be returned by the next getc calIon that stream. ungetc returns c as its value. only one character of pushback is guaranteed. pushed back. EOF cannot be SEE ALSO STANDARD I/O DIAGNOSTICS ungetc returns EOF (-1) if the character can't be pushed back. Copyright (c) 1984 by Manx Software Systems, Inc. lib.86 UNLINK (C) I/O Function UNLIRK NAME unlink SYNOPSIS unlink(name) char *name: DESCRIPTION unlink erases a file. name is a pointer to a character array containing the name of the file to be erased. unlink returns 0 if successful. DIAGNOSTICS unlink returns -1 if it couldn't erase the file and places a code in the global integer errno describing the error. Copyright (c) 1984 by Manx Software systems, Inc. lib.87 WRITE (e) unbuffered I/O Function WRITE NAME write SYNOPSIS write(fd,buf,bufsize) int fd, bufsize: char *buf; DESCRIPTION write writes characters to a device or disk which has been previously opened by a call to open or create The characters are written to the device or file directly from the caller's buffer. fd is the file descriptor which was returned to the caller when the device or file was opened. buf is a pointer to the buffer containing the characters to be written. bufsize is the number of characters to be written. If the operation is successful, write returns as its value the number of characters written. SEE ALSO UNBUFFERED r/o(o) , OPEN, CLOSE, READ DIAGNOSTICS If the operation is unsuccessful, write returns -1 and places a code in the global integer errno. Copyright (c) 1984 by Manx Software systems, Inc. lib.S8 CP/M Functions This subchapter describes functions which are available only to programs which are running on CP/M. As with the subchapter describing the system indendent functions, this subchapter is divided into sections, with each section describing a group of related functions. A section is divided into subsections; for a discussion of these subsections, see the introduction to the system independent functions. Following functions, and themselves. this introduction is an index to the CP/M then detailed descriptions of the functions Copyright (c) 1984 by Manx software Systems, Inc. lib.89 Index to CP/M Functions section functions bdos bdosh1 bios biosh1 exit exit fCbinit getusr in out rstusr rsvstk sbrk setusr · ........ ·........ ..... ..... · ...... .... ...... . . . . . ...... BDOS BDOS BIOS BIOS EXIT EXIT FCBINIT USER PORT PORT USER BREAK BREAK USER Copyright (c) 1984 by Manx Software Systems, Inc. lib.90 BOOS (C) CP/M System Calls BOOS NAME bdos, bdoshl - issue call to CP/M bdos SDlOPSIS bdos(bc, de) int be, de: bdoshl(bc, de) int be, de: DESCRIPTION These functions call the CP/M bdos with register pair BC set to be and DE set to de. bdos returns as its value the value which the CP/M bdos returned in register A. bdoshl returns as its value the value which the CP/M bdos returned in register pair HL. Copyright (c) 1984 by Manx Software Systems, Inc. lib.91 BIOS (C) CP/M System Calls BIOS NAME bios, bioshl - issue call to CP/M bios SYNOPSIS bios(n, be, de) int n, be, de: bioshl(n, be, de) int n, be, de: DESCRIPTION These functions call the n'th entry into the CP/M bios with register pair BC set to be and DE set to de. For example, bios(O) is a cold boot. bios returns as its value the value which the CP/ bios returned in register A. bioshl returns as its value the value which the CP/M bios returned in register pair HL. Copyright (c) 1984 by Manx Software Systems, Inc. lib.92 Heap management functions BREAK BREAK NAME sbrk, rsvstk SYNOPSIS sbrk(size) rsvstk{size) DESCRIPTION sbrk increments an internal pointer by size bytes, and returns the value the pointer had on entry. The pointer initially points to the base of the heap. rsvstk sets the heap-stack boundary size bytes below the current top of stack. The stack begins at the base of the CPM bdos. Unless rsvstk is called, the heap-stack boundary is 2048 bytes below the bdos base. SEE ALSO DYNAMIC BUFFER ALLOCATION (0), MALLOC DIAGNOSTICS sbrk returns -1 if the updated internal pointer would be above the heap-stack boundary. In this case, the internal pointer isn't modified. Copyright (c) 1984 by Manx Software systems, Inc. lib.93 EXEC System calls EXEC NAME execl, execv, execlp, execvp -'execute a program SYNOPSIS execl(name, argO, argl, ••• , argD, O} char *name, *argO, *argl, ••• , *argn; execv(name, argYl char *name, *argv[]; execlp(name, argO, argl, ••• , argD, O} char *name, *argO, *argl, ••• *argn; execvp(name, argv) char *name, *argv[]; DESCRIPTION The exec functions load another program from a disk file and transfer control to it. The new program is loaded over the currently executing program, so the exec functions never return to the caller. name specifies the file from which the program is to be loaded. It has the same format as that of a file being opened for i/o; see the I/O overview section for details. If the extent for the filename isn't specified, it's assumed to be that of an executable file; for example, on CPM it is assumed to be II.COMII and on TRSDOS it's II/CMD". The exec functions allow parameters to be passed to the called program. They do this by building a command line from the arguments passed to the exec function and then passing the command line to the new program. For execl and execlp the arguments are argl, argl, ... , argn. For execv and execvp the arguments are argv[l], argv[2], ... , argv[n]. Note that argO and argv[o] aren't passed to the new program: on Unix these strings are conventionally the name 'of the program being executed. There are really only two different exec functions: exec! and execv. execlp and execvp simply call execl and execv, respectively, and are provided for Unix compatibility. execl and execlp are useful when a program knows exactly how many arguments are to be passed to the new program. execv and execvp are useful when the number of arguments to be passed aren't known until the call is made. Copyright (c) 1984 by Manx Software systems, Inc. lib.94 EXIT (C) System Calls EXIT NAME exit, exit SYNOPSIS exit(n) exit(n) DESCRIPTION exit returns to the operating system, after closing any open files or devices. Buffered data for files and devices opened for standard i/o is written to disk, if necessary. If n is non-zero, the file A:$$$.SUB is deleted, thus preventing the continuation of the submit file, if any, which initiated the program. exit is the same as exit, except that devices and files opened for standard i/o are never flushed. Copyright (c) 1984 by Manx Software Systems, Inc. lib.95 FCBINIT (c) utility Function FCBINIT fcbinit - initialize file control block SYNOPSIS 'include -io.h ll fcbinit(name, fcbptr) char *namei struct fcb *fcbptri DESCRIPTION The file control block pointed at by fcbptr is initialized to zeroes and the file name pointed at by name is placed in it. If the file name specifies a user number, fcbinit returns it as its value: otherwise it returns 255. The file control block area pointed at by fcbptr must be at least 36 bytes long. The parameter name is a pointer to a character string which is the name of the file. The format of the name is described in the I/O overview section. Copyright (c) 1984 by Manx Software Systems, Inc. lib.96 PORT I/O Functions PORT NAME in, out port access functions SYNOPSIS in(port) out (port. val) DESCRIPTION in reads a character from port and returns it as its value. out writes the character in the least significant byte of val to port. copyright (c) 1984 by Manx Software Systems, Inc. lib.97 USER (C) uti1ity Functions USER NAME getusr, setusr, rstusr SYNOPSIS getusr( } setusr{user} rstusr(} DESCRIPTION getusr returns the current user number as its value. setusr sets the user number to user. The user number which was active on entry to setusr is saved for subsequent use by rstusr. rstusr resets the user number to the value which was saved during the last call to setusr. SEE ALSO I/O (0) Copyright (c) 1984 by Manx Software Systems, Inc. 1ib.98 SECTION VIII Technical Information Aztec C TECH INFO Data Formats 1. character Characters are 8 bit ASCII. Strings are terminated by a NULL (x'OO'). For computation characters are promoted to integers with value range from 0 to 255. a 2. pointer Pointers are two bytes (16 bits) long. The internal representation of the address FOAB stored in location 100 would be: location contents in hex format AB FO 100 101 3. int, short Integers are two bytes long. A negative value is stored in two's compliment format. A -2 stored at location 100 would look like: location contents in hex format 100 101 FE FF 4. long L~ng integers occupy four bytes. Negative values are in two's complement representation. Longs are sequentially with the least significant byte stored lowest memory addres and the most significant byte highest memory address. stored stored at the at the 5. float and double Floating point numbers are stored as 32 bits, and doubles are stored as 64 bits. The first bit is a sign bit. The next 7 bits are the exponent in excess 64 notation. The base for the exponent is 256. The remaining bytes are the fractional data stored in byte normalized format. A zero is a special case and is alIa bits. Copyright (c) 1984 by Manx Software Systems, Inc. tech. 1 Aztec C TECH IRFO The hexadecimal representation for a float with a value of 1.0 is: 41 01 00 00 A 255.0 would be: 41 FF 00 00 A 256.0 would be: 42 01 00 00 Copyright (c) 1984 by Manx software Systems, Inc. tech. 2 Aztec C TECH INFO Floati ng Poi nt Su pport Aztec C II supports floating point numbers of type float and double. All arithmetic operations (add, subtract, multiply, and divide) can be performed on floating point numbers, and conversions can be made from floating point representation to other other representations and vice versa. The common conversions are performed automatically, as specified in the K & R text. For example, automatic conversion occurs when a variable of type float is assigned to a variable of type int, or when a variable of type int is assigned to a variable of type float, or when a float variable is added to an int var iable. Other conversions can be expicitly requested, either by using a cast operator or by calling a function to perform the conversion. For example, if a function expects to be passed a value of type int, the (int) cast operator can be used to convert a variable of type float to a value of type int, which is then passed to the function. As another example, the function atof can be called to convert a character string to a value of type double. The following sections provide more detailed information of the floating point system. One section describes the internal representation of floating point numbers and another describes the handling of exceptional conditions by the floating point system. Floating Point Exceptions When a C program requests that a floating point arithmetic operation be performed, a call will be made to functions in the floating point support software. While performing the operation, these functions check for. the occurence of the floating point exception conditions: namely, overflow, underflow, and division by zero. On return to the caller, the global integer flterr indicates whether an exception has occurred. flterr o I 2 3 value returned meaning computed value no error has occurred underflow overflow division by zero +/- 2.ge-157 +/- 5.2e151 +/- 5.2e151 Copyright (c) 1984 by Manx Software Systems, Inc. tech. 3 Aztec C TECH INFO If the value of this integer is zero, no error occurred, and the value returned is the computed value of the operation. Otherwise, an error has occurred, and the value returned is arbitrary. The table lists the possible settings of flterr, and for each setting, the associated value returned and the meaning. When a floating point exception occurs, in addition to returning an indicator in 'flterr', the floating point support routines will either log an error message to the console or call a user-specified function. The error message logged by the support routines define the type of error that has occurred (overflow, underflow, or division by zero) and the address, in hex, of the instruction in the user's program which follows the call to the support routines. Following the error message or call to a user function, the floating point support routines return to the user's program which called the support routines. To determine whether to log an error message itself or to call a user's function, the support routines check the first pointer in Sysvec, the global array of function pointers. If it contains zero (which i t will, unless the u~er's program explicitly sets it), the support routines log a message: otherwise, the support routines call the function pointed at by this field. A user's function for handling floating point exceptions can be written in C. The function can be of any type, since the support routines don't use the value returned by the user's function. The function has two parameters: the first, which is of type int, is a code identifying the type of exception which has occurred. The value, 1, indicates underflow, 2 overflow, and 3 division by zero. The second parameter passed to the user's exception-handling routine is a pointer to the in~truction in the user's program which follows the call instruction to the floating point support routines. One way to use this parameter would be to declare it to be of type int. The user's routine could then convert it to a character string for printing in an error message. The example below demonstrates how floating point errors can be trapped and reported. In main, a pointer in the sysvec array is set to the routine, usertrap. If a floating point exception occurs during the execution of the program, this routine is called with the arguments described above. The error handling routine prints the appropriate error message, and returns to the floating point support routines. Copyright (c) 1984 by Manx Software Systems, Inc. tech. 4 Aztec C TECH IBFO Internal Representation of Floating Point Numbers Floats A variable of type 'float' is repesented internally by a sign flag, a base-256 exponent in excess-64 notation, and a three-character, base-256 fraction. All variables are normalized. #include "libc.lib" main () { sysvec[FLT_FAULT] = usertrap: } usertrap(errcode,addr) int errcode,addr: { char buff[4]: switch (errcode) case '1': printf("floating break: case '2': printf("floating break: case '3': printf( floating break: default: printf("invalid break: II point underflow at %x\n",buff): point overflow at %x\n",buff): point division by zero at %x\n", buff): code %d passed to usertrap\n",errcode): } The variable is stored in a sequence of four bytes. The most significant bit of byte a contains the sign flag: a means it's positive, 1 negative. The remaining seven bits of byte a contain the excess-64 exponent. Bytes 1,2, and 3 contain the three-character mantissa, with the most significant character in byte 1 and the least in byte 3. The 'decimal point' is to the left of the most significant byte. As an example, the internal representation of decimal 1.0 is 41 01 00 00. Copyright (c) 1984 by Manx Software Systems, Inc. tech. 5 Aztec C TECH INFO Doubles A floating point number of type double is represented internally by a sign flag, a base-256 exponent in excess-64 notation, and a seven-character, base-256 fraction. The variable is stored in a sequence of eight bytes. The most significant bit of byte 0 contains the sign flag: 0 means positive, 1 negative. The excess-64 exponent is stored in the remaining seven bits of byte O. The seven-character, base-256 mantissa is stored in bytes 1 through 7, with the most significant character in byte 1, and the least in byte 7. The "decimal point" is to the left of the most significant character. As an example, (256**3)*(1/256 + 2/256**2) is represented by the following bytes: 43 01 02 00 00 00 00 00. Floating point operations For accuracy, floating point operations are performed using mantissas which are 16 characters long. Before the value is returned to the user, it is rounded. Copyright (c) 1984 by Manx software Systems, Inc. tech. 6 Aztec C TECH INFO Assembly Language Interface A. Embedded Assembler SOurce Assembly language statements can be embedded in a "c" program between an tasm and an tendasm statement. The pound sign (#) must stand in column one of the line, and the letters must be lower case. No assumptions should be made concerning the contents of registers. The environment should be preserved and restored. Caution should be used in writing code that depends on the current code generating techniques of the compiler. There is no guarantee that future releases will generate the same or similar patterns. In general, it is safest to contain assembly code in a subroutine rather than embedding it in C source. This is the recommended approach where feasible. B. Assembler Subroutines The calling conventions used very simple. The arguments to a stack in reverse order, i.e. the and the last argument is pushed by the Aztec C II compiler are function are pushed onto the first argument is pushed last first. The function is then called using the 8080 CALL instruction. When the function returns, the arguments are removed from the stack. A function is required to return with the arguments still on the stack unless something is pushed back in place of them. Registers BC, IX, and IY must be preserved by routines called from C. The function's return value should be in HL and the Z flag set according to the value in HL. Copyright (c) 1984 by Manx Software Systems, Inc. tech. 7 Aztec C TECH IRFO Example: ; Copyright (C) 1981 Thomas Fenwick public isupper_ isupper : -lxi h,2 hI := stack pointer + 2 (arguement address) dad sp mov a,m load argument into accumulator via hI cpi 'A' jc false cpi 'Z'+l jnc false true: lxi h,l mov a,l ora a ret public islower islower lxi h,2 dad sp mov a,m cpi la l jc false cpi 'z'+l jc true false: lxi h,Q mov a,l ora a ret Copyright (c) 1984 by Manx software systems, Inc. tech. 8 SECTION IX Software Extensions Aztec C EXTENSIONS The Tiny Library This library reduces the overhead in code size when a program is linked with the standard library. This is accomplished through some basic tradeoffs, as detailed below. The linkage command when using the tiny library has this form: In module.o [program modules] t.lib c.lib what makes it so small? I/O redirection is not supported by the tiny library. Furthermore, I/O is restricted to files and the console. NO output to the printer is allowed. Thus, fopen can open only files. The console must be accessed with the functions: getchar, putchar, gets, puts, printf. Since stdin and stdout are not supported (see below), agetc(stdin) and aputc(stdout) cannot be used in place of getchar and putchar. The tiny library does not allow the use of any low-level I/O routines such as open and read. only buffered I/O is supported, with the limitations noted. A maximum of four files can be open simultaneously. One can be open for writing, three for reading. A file cannot be open for both reading and writing. Specifically, the tiny fopen supports the "r" option for read only; any other option is construed as a "w" for write only. Two buffers are maintained for disk file I/O to all the open files. One is used for writing and the other for reading. As long as input requests are being made to only one file, the buffer is refilled only when necessary. However, when reading from a new file, the buffer is refilled. This can be inefficient when two or three files are being read alternately, since the buffer is refilled every time the input file changes. The formatting performed by printf and related functions is also restricted. The special format characters supported are %c for a character, %d for a decimal integer, %x for hexadecimal, and %s for a string. One exception to this rule is when sscanf is called but printf is not. This will cause formatting to be done the standard way. An examination of the header file, "stdio.h", indicates some of the internal changes that have been made. A source module to be linked with the tiny library should be compiled with the -D option to define the symbol, TINY, as in the command: Copyright (c) 1984 by Manx Software Systems, Inc. ext.l Aztec C EXTENSIOHS cc -DTINY prog.c This excludes the definitions of stdin, stdout, stderr, getchar, putchar, feof, ferror, clearerr, fileno, and fflush. The functions, getchar and putchar, are provided as library functions rather than as macros. The remaining functions are not available with the tiny library. Note that since stdin and stdout do not exist with the tiny library, I/O to the console cannot use agetc or aputc. The following functions are not available when linking with the tiny library: clearerr fdopen feof ferror fflush fileno flush freopen fseek ftell scanf setbuf puterr ungetc Copyright (c) 1984 by Manx Software Systems, Inc. ext.2 Aztec C EXTENSIONS A Fast ·Linl dispfile cnm >lst: subl.o A filename can optionally specify multiple files, using the "wildcard" characters ? and *. These have their standard CP/M meanings: ? matches a single character: * matches zero or more characters. For example *.0 a'?'?lib specifies all files with extent '.0' specifies all files whose filename has three characters, the first of which is 'a', and whose extent is '.lib' cnm displays information about an program's 'named' symbols: that is, about the symbols whose first two characters are other than a period followed by a digit. For example, the symbol quad is named, so information about it would be displayed: the symbol .0123 is unnamed, so information about it would not be displayed. For each named symbol in a program, cnm displays its name, a code specifying its type, and an associated value. The value displayed depends on the type of the symbol. A type code is a single character, and can be either upper or lower case, specifying that the symbol is global or local to the Copyright (c) 1984 by Manx Software Systems, Inc. ext.17 CNM Aztec uti1ity program program, a respectively. The types codes are: The symbol was defined using the assembler's EQUATE directive. The value listed is the equated value of its symbol. The compiler doesn't generate symbols of this type. t The symbol is in the code segment. The value is the offset of the symbol within the code segment. The compiler generates this type symbol for function nameSi static functions are local to the function, and so have type ti all other functions are global, that is, callable from other programs, and hence have type T. d The symbol is in the data segment. The value is the offset of the symbol from the start of the data segment. The compiler generates symbols of this type for initialized variables which are declared outside any function. Static variables are local to the program and so have type di all other variables are global, that is, acces~able from other programs, and hence have type D. C The symbol is the name of a common block. The value is the size of the common block, in bytes. C is in upper case because common block names are always global. The compiler doesn't generate this type symbol. r The symbol is defined within a common block. The value is the offset of the symbol from the beginning of the common block. The compiler doesn't generate this type symbol. u The symbol is used but not defined within the program. The value has no meaning. The compiler generates U symbols for functions that are called but not defined within the program, for variables that are declared to be extern and which are actually used within the program, and for unitialized, global dimensionless arrays. variables which are declared to be extern but which are- not used within the program don't make it to the object file. The compiler generates u symbols for variables which are used but not defined within the program. b The symbol is in the uninitalized data segment. The value is the space reserved for the symbol. The compiler generates b symbols for static, Copyright (c) 1984 by Manx Software Systems, Inc. uninitialized ext.IS Aztec utility program variables which are declared outside all functions and which aren't dimensionless arrays. The assembler generates b symbols for symbols defined using the bss assembler directive. If the symbol also appears in the public directive, it's type is B instead of b. G The symbol is in the uninitialized data segment. The value is the space reserved for the symbol. The compiler generates G symbols for non-static, uninitialized variables which are declared outside all functions and which aren't dimensionless arrays. The assembler generates G symbols for variables declared using the global directive which have a non-zero size. Copyright (c) 1984 by Manx Software Systems, Inc. ext. 19 Aztec utility Program SQZ SQZ sqz - squeeze an object library SYNOPSIS sqz file [outfile] DESCRIPTION sqz compresses an object library which was created by LIBUTIL. The first parameter is the name of the file containing the library to be compressed. The second parameter, which is optional, is the name of the file to which the compressed library will be written. If the output file is specified, the original file isn't modified or erased. If the output file isn't specified, sqz creates the compressed library in a file having a temporary name, erases the original library file, and renames the output file to the name of the original file. The temporary name is derived from the input library name by changing it's extent to .sqzl. I If the output file isn't specified and an error occurs during the creation of the compressed library, the original library isn't erased or modified. Copyright (c) 1984 by Manx Software Systems, Inc. ext.20 SECTION X Style and Debugging Aztec C STYLE Style This section was written for the programmer who is new to the C language, to communicate the special character of C and the programming practices for which it is best suited. This material will ease the new user's entry into C. It gives meaning to the peculiarities of C syntax, in order to avoid the errors which will otherwise disappear only with experience. what·s in it for me? These are the benefits to be reaped by following the methods presented here: o reduced debugging times o increased program efficiency o reduced software maintenance burden The aim of the responsible programmer is to write straightforward code, which makes his programs more accessible to others. This section on style is meant to point out which programming habits are conducive to successful C programs and which are especially prone to cause trouble. The many advantages of C can be abused. Since C is a terse, subtle language, it is easy to write code which is unclear. This is contrary to the "philosophy" of C and other structured programming languages, according to which the structure of a program should be clearly defined and easily recognizable. keep it simple There are several elements of programming style which make C easier to use. One of these is simplicity. Simplicity means keep it simple. You should be able to see exactly what your code will do, so that when it doesn't you can figure out why. A little suspicion can also be useful. The particular "problem areas" which are discussed later in this section are points to check when code "looks right" but does not work. A small omission can cause many errors. learn the C idioms C becomes more valuable and more flexible with time. Obviously, elementary problems with syntax will disappear. But Copyright (c) 1984 by Manx Software systems, Inc. style.l Aztec C STYLE more importantly, C can be described as lIidiomatic. 1I This means that certain expressions become part of a standard vocabulary used over and over. For example, while «c = getchar(» 1= EOF) is readily recognized and written by any C programmer. This is often used as the beginning of a loop which gets a character at a time from a source of input. Moreover, the inside set of parentheses, often omitted by a new C programmer, is rarely forgotten after this construct has been used a few times. be flexible in using the library The standard library contains a choice of functions for performing the same task. Certain combinations offer advantages, so that they are used routinely. For instance, the standard library contains a function, scanf, which can be used to input data of a given format. In this example, the function "scans" input for a floating point number: scanf(lI%f", &flt_num)~ There are several disadvantages to this function. An important debit is that it requires a lot of code. Also, it is not always clear how this function handles certain strings of input. Much time could be spent researching the behavior of this function. However, the equivalent to the above is done by the following: This requires considerably less code, and is somewhat more straightforward. gets puts a line of input into the buffer, "inp buf,1I and atof converts it to a floating point value. There is no question about what the input function is IIlooking for ll and what it should find. Furthermore, there is greater flexibility in the second method of getting input. For instance, if the user of the program could enter either a special command (lle ll for exi t) or a floating point value, the following is possible: gets(inp buf); if (inp buf[O] == lei) exIt (0); flt_num = atof(inp_buf); Here, the first character of input is checked for an lIe ll , before the input is converted to a float. The relative length of the library description of the scanf function is an indication of the problems that can arise with that and related functions. Copyright (c) 1984 by Manx Software Systems, Inc. style.2 Aztec C' STYLE write readible code Readibility can be greatly enhanced by adhering to what common sense dictates. For instance, most lines can easily accommodate only one statement. Although the compiler will accept statements which are packed together indiscriminately, the logic behind the code will be lost. Therefore, it makes sense to write no more than one statement per line. In a similar vein, it is desirable to be generous with whitespace. A blank space should separate the arithmetic and assignment operators from other symbols, such as variable names. And when parentheses are nested, dividing them with spaces-is not being too prudent. For example, if ( ( fp=fopen ( filename II II , II r II ) ==NULL) ) is not the same as if ( (fp = fopen("filename ll , "r")) == NULL) The first line contains a misplaced pare-nthesis which changes the meaning of the statement entirely. (A file is opened but the file pointer will be null.) If the statement was expanded, as in the second line, the problem could be easily spotted, if not avoided altogther. use straightforward logical expressions Conditionals are apt to grow into long expressions. They should be kept short. Conditionals which extend into the next line should be divided so that the logic of the statement can be visualized at a glance. Another solution might be to reconsider the logic of the code itself. learn the rules for expression evaluation Keep in mind that the evaluation of an expression depends upon the order in which the operators are evaluated. This is determined from their relative precedence. Item 7 in the list of "things to watch out for below, gives an example of what may happen when the evaluation of a boolean expression stops "in the middle". The rule in C is that a boolean will be evaluated only until the value of the expression can be determined. ll , Item 8 gives a well known example of an "undefined" expression, one whose value is not strictly determined. In general, if an expression depends upon the order in which Copyright (c) 1984 by Manx Software systems, Inc. style.3 Aztec C STYLE it is evaluated, the results may be dubious. Though the result may be strictly defined, you must be certain you know what that definition is. a matter of taste There are several popular styles of indentation and placement of the braces enclosing compound statements. Whichever format you adopt, it is important to be consistent. Indentation is the accepted way of conveying the intended nesting of program statements to other programmers. However, the compiler understands only braces. Making them as visible as possible will help in tracking down nesting errors later. However much time is devoted to writing readible code, C is low-level enough to permit some very peculiar expressions. /* It is important to insert comments on a regular basis! */ comments are especially useful as brief introductions to function definition& In general, moderate observance of these suggestions will lessen the number of "tricks" C will play on you-- even after you have mastered its syntax. Copyright (c) 1984 by Manx Software Systems, Inc. sty1e.4 Aztec C STYLE Structured Programming IIStructured programming is an attempt to encourage programming characterized by method and clarity. It sterns from the theory that any programming task can be broken into simpler components. The three basic parts are statements, loops, and conditionals. In C, these parts are, respectively, anything enclosed by braces or ending wi th a semicolon: for, while and dowhi1e: if-else. ll modu1arity and block structure Central to structured programming is the concept of modularity. In one sense, any source file compiled by itself is a module. However, the term is used here with a more specific meaning. In this context, modularity refers to the independence or isolation of one routine from another. For example, a routine such as maine) can call a function to do a given task even though i t does not know how the task is accomplished or what intermediate values are used to reach the final re~ult. Sections of a program set aside by braces are called IIblocksli. The "privacy" of CiS block structure ensures that the variables of each block are not inadvertently shared by other blocks. Any left brace ({) signals the beginning of a block, such as the body of a function or a for loop. Since each block can have its own set of variables, a left brace marks an opportunity to declare a temporary variable. A function in C is a special block because it is called and is passed control of execution. A function is called, executes and returns. Essentially, a C program is just such a routine, namely, main. A function call represents a task to be accomplished. program statements which might otherwise appear as several obscure lines can be set aside in a function which satisfies a desired purpose. For instance, getchar is used to get a single character from standard input. When a section of code must be modified, it is simpler to replace a single modular block than it is to delete a section of an unstructured program whose boundaries may be unclear at best. In general, the more precisely a block of program is defined, the more easily it can be changed. Copyright (c) 1984 by Manx Software Systems, Inc. sty1e.5 Aztec C STYLE Top-down Programming "Top-down" programming is one method that takes advantage of structured programming features like those discussed above. It is a method of designing, writing, and testing a program from the most general function (i.e., (main()) to the most specific functions (such as getchar () ) . All C programs begin with a function called main(). main() can be thought of as a supervisor or manager which calls upon other functions to perform specific tasks, doing little of the work itself. If the overall goal of the program can be considered in four parts (for instance, input, processing, error checking and output), then main() should call at least four other functions. step one The first step in the design of a program is to identify what is to be done and how i t can be accomplished in a "programmable" way. The main routine should be greatly simplified. It needs to call a function to perform the crucial steps in the program. For example, it may call a function, init(), which takes care of all necessary startup initializations. At this point, the programmer does not even need to be certain of all the initializations that will take place in ini t(). All functions consist of three parts: a parameter list, body, and return value. The design of a function must focus on each of these three elements. During this first stage of design, each function can be considered a black box. We are concerned only with what goes in and what comes out, not with what goes on inside. Do not allow yourself to be distracted by the details of the implementation at this point. Flowcharts, pseudocode, decision tables and the like are useful at this stage of the implementation. A detailed list of the data which is passed back and forth between functions is important and should not be neglected. The interface between functions is crucial. Although all functions are written with a purpose in mind, it is easy to unwittingly merge two tasks into one. Sometimes, this may be done in the interests of producing a compact and efficient program function. However, the usual result is a bulky, unmanageable function. If a function grows very large or if its logic becomes difficult to comprehend, it should be Copyright (c) 1984 by M~nx Software Systems, Inc. style.6 Aztec C reduced by introducing additional function calls. step two There comes a time when a program must pass from the design stage into the coding stage. You may find the top-down approach to coding too restrictive. According to this scheme, the smallest and most specific functions would be coded last. It is our nature to tackle the most daunting problems first, which usually means coding the low-level functions. Whereas the top-down approach is the preferred method for designing software, the bottom-up approach is often the most practical method for writing software. Given a good design, either method of implementation should produce equally good results. One asset of top-down writing is the ability to provide immediate tests on upper level routines. Unresolved function calls can be satisfied by IIdummy" functions which return a range of test values. When new functions are added, they can operate in an environment that has already been tested. C functions are most effective when they are as mutually independent as is possible. This independence is encouraged by the fact that there is normally only one way into and one way out of a function: by calling it with specific arguments and returning a meaningful value. Any function can be modified or replaced so long as its entry and exit points are consistent with the calling function. Copyright (c) 1984 by Manx software Systems, Inc. style.7 Aztec C STYLE Defensive Programming "Defensive programming" obeys the same edict as defensive driving: trust no one to do what you expect. There are two sides to this rule of thumb. Defend against both the possibility of bad data or misuse of the program by the user, and the possibility of bad data generated by bad code. Pointers, for example, are a prime sour~e of variables gone astray. Even though the "theory" of pointers may be well understood, using them in new ways (or for the first time) requires careful consideration at each step. Pointers present the fewest problems when they appear in familiar settings. faced with the unknown When trying something new, first write a few test programs to make sure the syntax you are using is correct. For example, consider a buffer, str buf, filled with null-terminated strings. Suppose we want to print the string which begins at offset begin in the buffer. Is this the way to do it? printf("%s", str_buf[begin]): A little investigation shows that str buf[begin] is a character, not a pointer to a string, which 1s what is called for. The correct statement is printf("%s", str_buf + begin): This kind of error may not be obvious when you first see it. There are other topics which can be troublesome at first exposure. The promotion of data types within expressions is an example. Even if you are sure how a new construct behaves, it never hurts to doublecheck with a test program. Certain programming habits will ease the bite of syntax. Foremost among these is simplicity of style. Top-down programming is aimed at producing brief and consequently simple functions. This simplicity should not disappear when the design is coded. Code should appear as "idiomatic" as possible. pointers can again provide an example: it is a fact of C syntax that arrays and pointers are one and the same. That is, array[offset] is the same as *(array + offset) Copyright (c) 1984 by M"anx software Systems, Inc. style.S. Aztec C STYLE The only difference is that an array name is not an lvalue; it is fixed. But mixing the two ways of referencing an object can cause confusion, such as in the last example. Choosing a certain idiom, which is known to behave a certain way, can help avoid many errors in usage. when bugs strike The assumption must be that you will have to return to the source code to make changes, probably due to what is called a bug. Bugs are characterized by their persistence and their tendency to mUltiply rapidly. Errors can occur at either compile-time or run-time. Compile-time errors are somewhat easier to resolve since they are usually errors in syntax which the compiler will point out. from the compiler If the compiler does pick up an error in the source code, it will send an error code to the screen and try to· specify where the error occurred. There are several peculiarities about error reporting which should be brought up right away. The most noticeable of these peculiarities is the number of spurious errors which the compiler may report. This interval of inconsistency is referred to as the compiler's recovery. The safest way to deal with an unusually long list of errors is to correct the first error and then recompile before proceeding. The compiler will specify where it "noticed" something was wrong. This does not necessarily indicate where you must make a change in the code. The error number is a more accurate clue, since it shows what the compiler was looking for when the error occurred. if this ever happens to you A common example of this is error 69: "missing semicolon." This error code will be put out if the compiler is expecting a semicolon when it finds some other character. Since this error most often occurs at the end of a line, it may not be reported until the first character of the following line-- recall that whitespace, such as a newline character, is ignored. Such an error can be especially treacherous in certain situations. For example, a missing semicolon at the end of a linclude ' d file may be reported when the compiler returns to read input in the original file. In general, it is helpful to look at a syntax error from the Copyright (c) 1984 by Manx Software Systems, Inc. style.9 Aztec C STYLE compiler's point of view. Consider this error: struct structag char c: int i: } int j: This should generate an error 16: "data type conflict". The arrow in the error message should show that the error was detected right after the "int" in the declaration of j. This means that the error has to do with something before that line, since there is nothing illegal about the int keyword. By inspection, we may see that the semicolon is missing from the preceding line. If this fact escapes our notice, we still know that error 16 means this: the compiler found a declaration of the form [data type] [data type] [symbol name] where the two data types were incompatible. So while short int is a good data type, double int is not. A small intuitive leap leads us to assume that the compiler has read our source as a kind of "struct int" declaration: struct is the only keyword preceding the int which could have caused this error. Since the compiler is reading the two declarations as a single statement, we must be missing a delimiter. run-time errors It takes a bit more ingenuity to locate errors which occur at run-time. In numerical calculations, only the most anomalous results will draw attention to themselves. other bugs will generate output which will appear to have come from an entirely different program. A bug is most useful when it is repeatable. Bugs which show up only "sometimes" are merely vexing. They can be caused by a corrupted disk file or a bad command from the user. When an error can be consistently produced, its source can be more easily located. The nature of an error is a good clue as to its source. Much of your time and sanity will be preserved by setting aside a few minutes to reflect upon the problem. Which modules are involved in the computation or process? Many possibilities can be eliminated from the start, such as pieces of code which are unrelated to the error. The first goal is to determine, from Copyright (c) 1984 by Manx Software Systems, Inc. a number of style.lO Aztec C STYLE possibilities, which module might be the source of the bug. checking input data Input to the program can be checked at a low cost. Error checking of this sort should be included on a "routine" basis. For instance, "if «fp=fopen(lfilel,lr"))==NULL)" should be reflex when a file is opened. Any useful error handling can follow in the body of the if. It is easy to check your data when you first get your hands on it. If an error occurs after that, you have a bug in your program. printf it It is useful to know where the data goes awry. One brute force way of tracking down the bug is to insert printf statements wherever the data is referenced. When an unexpected value comes up, a single module can be chosen for further investigation. The printf search will be most effective when done with more refinement. Choose a suspect module. There are only two keys points to check: the entry and return of the function. printf the data in question just as soon as the function is entered. If the values are already incorrect, then you will want to make sure the correct data was passed in the function call. I f an incorrect value is returned, then the search is confined to the guilty function. Even if the function returns a good value, you may want to make sure it is handled correctly by the calling function. If everything seems to be working, jump to the next tricky module and perform another check. When you find a bad result, you will still have to backtrack to discover precisely where the data was spoiled. function ca11s Be aware that data can be garbled in a funtion call. Function parameters must be declared when they are not two byte integers. For instance, if a function is called: fseek(fp, 0, 0); in order to "seek" to the beginning of a file, but the function is defined this way: fseek(fp, offset, origin) FILE *fp; long offset; Copyright (c) 1984 by Manx Software Systems, Inc. sty1e.11 Aztec C STYLE int origin; there will be unfortunate consequences. The second parameter is expected to be a long integer (four bytes), but what is being passed is a short integer (two bytes). In a function call, the arguments are just being pushed onto the stack; when the function is entered, they are pulled off again. In the example, two bytes are being pushed on, but four bytes (wha tever four bytes are t_here) are be i 1'19 pu lled of f . The solution is just to make the second parameter a long, with a suffi~ (OL) or by the cast operator (as in (long)i). A similar problem occurs when a non-integer return value is not declared in the calling function. For example, if sqrt is being called, it must be declared as returning a double: double sqrt(); This method of debugging demonstrates the usefulness of having a solid design before a function is coded. If you know what should be going into a function and what should be coming out, the process of checking that data is made much simpler. found it When the guilty function is isolated, the difficulty of finding the bug is proportional to the simplicity of the code. However, the search can continue in a similar way. You should have a good notion of the purpose of each block, such as a loop. By inserting a printf in a loop, you can observe the effect of each pass on the data. printf' s can also point out which blocks are actually being executed. "Falling through" a test, such as an if or a switch, can be a subtle source of problems. Conditionals should not leave cases untested. An else, or a default in a switch, can rescue the code from unexpected input. And if you are uncertain how a piece of code will work, it is usually worthwhile to set up small test programs and observe what happens. This is instructional and may reveal a bug or two. Copyright (c) 1984 by Manx Software Systems, Inc. style.l2 Aztec C STYLE Things to Watch lOut for Some errors arise again and again. Not all of them go away with experience. The following list will give you an idea of the kinds of things that can go wrong. 1. missing semicolon or brace The compiler will tell you when a missing semicolon or brace has introduced bad syntax into the code. However, often such an error will affect only the logical structure of the program: the code may compile and even execute. When this error is not revealed by inspection, it is usually brought out by a test printf which is executed too often or not enough. See compiler error 69. 2. assignment (=) vs comparison (==) Since variables are assigned values more often than they are tested for equality, the former operator was given the single keystroke: =. Notice that all the comparison tests with equality are two characters: <=, >= and --. 3. misplaced semicolon When typing in a program, keep in mind that all source lines do not automatically end with a semicolon. Control lines are especially susceptible to an unwanted semicolon: for (i=Oi i = la l && c <= IZI && (c = getchar(» >= III && c <= 19 1 ) printf("good input\n"); if «c = getchar(» 1= EOF) if (c >= la l && c <= IZI) if «c = getchar(» >= 10 1 && c <= 19 1 ) printf("good input\n"); 10. badly formed comments The theory of comment syntax is simply that everything occurring between a left /* and a right */ is ignored by the compiler. Non~theless, a missing */ should not be overlooked as a possible error. Note that comments cannot be nested, that is /* /* this will cause an error */ */ And this could happen to you too: /* the rest of this file is ignored until another comment /* 11. nesting error Remember that nesting is d'etermined by braces and not by indentations in the text of the source. Nested if statements merit particular care since they are often paired with an else. 12. usage of else Every else must pair up with an if. When an else has inexplicably remained unpaired, the cause is often related to the first error in this list. 13. falling through the cases in a switch To maintain the most control over the cases in a switch statement, it is advisable to end each case with a break, Copyright (c) 1984 by Manx Software Systems, Inc. style.lS Aztec C ! STYLE including the last case in the switch. 14. strange loops The behavior of loops can be explored by inserting printf statements in the body of the loop. Obviously, this will indicate if the loop has even been entered at all in course of a run. A counter will show just how many times the loop was executed; a small slip-up will cause a loop to be run through once too often or seldom. The condition for leaving the loop should be doublechecked for accuracy. 15. use of strings All strings must be terminated by a null character in memory. Thus, the string, "hello", will occupy a six-element array; the sixth element is 1\0 This convention is essential when passing a string to a standard library function. The compiler will append the null character to string constants automatically. 1 16. • pointer vs object of a pointer The greatest difficulty in using pointers is being sure of what is needed and what is being used. Functions which take a pointer argument require an address in memory. The best way to ensure that the correct value is being passed is to keep track of what is being pointed to by which pointer. 17. array subscripting The first element in a C array has a subscript of zero. The array name without a subscript is actually a pointer to this element. Obviously, many problems can develop from an incorrect subscript. The most damaging can be subscripting out of bounds, since this will access memory aboye the array and overwrite any data there. If array elements or data stored with arrays are being lost, this error is a good candidate. 18. function interface During the design stage, the components of a program should be associated with functions. It is important that the data which is passed among or shared by these functions be explicitly defined in the preliminary design of the program. This will greatly facilitate the coding of the program since the interface between functions must be precise in several respects. First of all, if the parameters of a function are established, a call can be made without the reservation that it Copyright (c) 1984 by Manx Software Systems, Inc. style.16 Aztec C STYLE will be changed later. There is less chance that the arguments will be of the wrong type or specified in the wrong order. A function is given only a private copy of the variables it is passed. This is a good reason to decide while designing the program how functions should access the data they require. You will be able to detail the arguments to be passed in a function call, the global data which the function will alter, the value which the function will return and what declarations will be appropriate-- all without concern for how the function will be coded. Argument declarations should be a fairly simple matter once these things are known. Note that this declaration list must stand before the left brace of the function body. The type of the function is the same as the type of the value it returns. Functions must be declared just like any variable. And just like variables, functions will default to type int, that is, the compiler will assume that a function returns an integer if you do not tell it otherwise with a declaration. Thus if function f calls function g which returns a variable of type double, the following declaration is needed: function f ( ) { double g(), bigfloat; g(bigfloat)i } double g(arg) double { return(arg); } 19. be sure of what a function returns You will probably know very well what is returned by a function you have written yourself. But care should be taken when using functions coded by someone else. This is especially true of the standard library functions. Most of the supplied library functions will return an int or a char pointer where you might expect a char. For instance, getchar() returns an int, not a char. The functions supplied by Manx adhere to the UNIX model in all but a few cases. Of course, the above applies to a function's arguments as well. 20. shared data Variables that are declared globally can be accessed by all Copyright (c) 1984 by Manx Software Systems, Inc. style.17 Aztec C STYLE functions in the file. This is not a very safe way to pass data to functions since once a global variable is altered, there is no returning it to its former state without an elaborate method of saving data. Moreover, global data must be carefully managed; a function may process the wrong variable and consequently inhibit any other function which depends on that data. Since C provides for and even encourages private data, definitely should not be a common bug. Copyright (c) 1984 by Manx Software Systems, Inc. this style.I8 SECTION XI ERROR MESSAGES Aztec C CC ERRORS COMPILER ERROR CODES No. Interpretation 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: bad digit in octal constant string space exhausted unterminated string internal error illegal type for function inappropriate arguments bad declaration syntax syntax error in typecast array dimension must be constant array size must be positive integer data type too complex illegal pointer reference unimplemented type internal internal data type conflict internal data type conflict obsolete structure redeclaration missing} syntax error in structure declaration obsolete need right parenthesis or comma in arg list structure member name expected here must be structure/union member illegal typecast incompatible structures illegal use of structure missing: in ? conditional expression call of non-function illegal pointer calculation. illegal type undefined symbol typedef not allowed here no more expression space invalid expression for unary operator no auto. aggregate initialization allowed obsolete internal initializer not a constant too many initializers initialization of undefined structure obsolete bad declaration syntax missing closing brace open failure on include file illegal symbol name Copyright (c) 1984 by Manx Software Systems, Inc. err.1 Aztec C 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: CC ERRORS multiply defined symbol missing bracket lvalue required obsolete mUltiply defined label too many labels missing quote missing apostrophe line too long illegal # encountered macro too long obsolete reference of member of undefined structure function body must be compound statement undefined label inappropriate arguments illegal argument name expected comma invalid else syntax error missing semicolon goto needs a label statement syntax error in do-while statement syntax error in for statement syntax error in for body case value must integer constant missing colon on case too many cases in switch case outside of switch missing colon on default duplicate default default outside of switch break/continue error illegal character too many nested includes too many array dimensions not an argument null dimension in array invalid character constant not a structure invalid use of register storage class symbol redeclared illegal use of floating point type illegal type conversion illegal expression type for switch invalid identifier in macro definition macro needs argument list missing argument to macro obsolete not enough arguments in macro reference internal internal missing close parenthesis on macro reference macro arguments too long #else with no #if Copyright (c) 1984 by Manx Software Systems, Inc. err.2 Aztec C 104: 105: 106: 107: 108: 109: 110: Ill: 112: 113: 114: 115: CC ERRORS #endif with no #if #endasm with no #asm #asm within #asm block missing #endif missing #endasm #if value must be integer constant invalid use of : operator invalid use of void expression invalid use function pointer duplicate case in switch macro redefined keyword redefined Copyright (c) 1984 by Manx Software Systems, Inc. err.3 Aztec C CC ERRORS Explanations 1: bad digit in octal constant The only numerals permitted in the base 8 (octal) counting system are zero through seven. In order to distinguish between octal, hexadecimal, and decimal constants, octal constants are preceded by a zero. Any number beginning with a zero must not contain a digit greater than seven. Octal constants look like this: 01, 027, 003. Hexadecimal constants begin with Ox (e.g., Oxl, OxAAO, OxFFF). 2: string space exhausted The compiler maintains an internal table of the strings appearing in the source code. Since this table has a finite size, it may overflow during compilation and cause this error code. The table default size is about one or two thousand characters depending on the operating system." The size can be changed using the compiler option -Z. Through simple guesswork, it is possible to arrive at a table size sufficient for compiling your program. The following example illustrates the use of this option: cc -Z3000 bigexmpl.c The new table size allows the strings in the file to total 3000 bytes in length. This is equal to 3000 characters. 3: unterminated string All strings must begin and end with double quotes ("). This message indicates that a double quote has remained unpaired. 4: internal error This error message should not occur. It is a check on the internal workings of the compiler and is not known to be caused by any particular piece of code. However, if this error code appears, please bring it to the attention of MANX. It could be a bug in the compiler. The release documentation enclosed with the product contains fur~her information. Copyright (c) 1984 by Manx Software systems, Inc. err.4 Aztec C 5: CC ERRORS illegal type for function The type of a function refers to the type of the value which it returns. Functions return an int by default unless they are declared otherwise. However, functions are not allowed to return aggregates (arrays or structures). An attempt to write a function such as struct sam func() will generate this error code. The legal function types are char, int, float, double, unsigned, long, void and a pointer to any type (including structures). 6: error in argument declaration The declaration list for the formal parameters of a function stands immediately before the left brace of the function body, as shown below. Undeclared arguments default to int, though it is usually better practice to declare everything. Naturally, this declaration list may be empty, whether or not the function takes any arguments at all. No other inappropriate symbols should appear before the left (open) brace. badfunction(argl, arg2) shrt arg 1: /* misspelled or invalid keyword */ double arg 2; { /* function body */ } goodfunction(argl,arg2) float argl: int arg2; /* this line is not required */ { /* function body */ } 7: bad declaration syntax A common cause of this error is the absence of a semicolon at the end of a declaration. The compiler expects a semicolon to follow a variable declaration unless commas appear between variable names in multiple declarations. int i, j: char c d: char *sl, *s2 float k: /* correct */ /* error 7 */ /* error 7 detected here */ sometimes the compiler may not detect the error until the next program line. A missing semicolon at the end of a 'include'd file will be detected back in the file being compiled or in another ,include file. This is a good example of why it is important to examine the context of the error rather than to rely solely on the information provided by the compiler error message(s). Copyright (c) 1984 by Manx Software systems, Inc. err.5 Aztec C 8: CC ERRORS syntax error in type cast The syntax of the cast operator must be carefully observed. A common error is to omit a parenthesis: i i 9: = = 3 * (int number): 3 * «int)number): /* incorrect usage */ /* correct usage */ array dimension must be constant The dimension given an array must be a constant fo type char, int, or unsigned. This value is specified in the declaration of the array. See error 10. 10: array size must be positive integer The dimension of an array is required to be greater than zero. A dimension less than or equal to zero becomes 1 by default. As can be seen from the following example, specifying a dimension of zero is not the same as leaving the brackets empty. char badarray[O]: /* meaningless */ extern char goodarray[]: /* good */ Empty brackets are used when declaring an array that has been defined (given a size and storage in memory) somewhere else (that is, outside the current function or file). In the above example, goodarray is external. Function arguments should be declared with a null dimension: func{sl,s2) char sl[], s2[]: { } 11: data type too complex This message is best explained by example: char ******£00: The form of this declaration implies five pointers-topointers. The sixth asterisk indicates a pointer to a char. The compiler is unable to keep track of so many "levels". Removing just one of the asterisks will cure the error: all that is being declared in any case is a single two-byte pointer. However it is to be hoped that such a construct will never be needed. Copyright (c) 1984 by Manx Software Systems, Inc. err.6 Aztec C 12: CC ERRORS illegal pointer reference The type of a pointer must be either int or unsigned. This is why you might get away with not declaring pointer arguments and functions like fopen which return a pointer: they default to int. When this error is generated, an expression used as a pointer is of an invalid type: char c: int var: /* any variable */ int varaddress: varaddress = &var: /* valid since addresses */ *(varaddress) = 'e l : /* can fit in an inti */ *(expression) = 10: /* in general, expression must be an int or unsigned * / *c = 'c': /* error 12 */ 13: internal [see error 4J 14: internal [see error 4J 15: storage class conflict Only automatic variables and function parameters can be specified as register. This error can be caused by declaring a static register variable. While structure members cannot be given a storage class at all, function arguments can be specified only as register. A register int i declaration is not allowed outside a function--it will generate error 89 (see below). 16: data type conflict The basic data types are not numerous, and there are not many ways to use them in declarations. The possibilities are listed below. This error code indicates that two incompatible data types were used in conjunction with one another. For example, while it is valid to say long int i, and unsigned int j, it is meaningless to use double int k or float char c. In this respect, the compiler checks to make sure that int, char, float and double are used correctly. Copyright (c) 1984 by Manx Software Systems, Inc. err.7 Aztec C CC ERRORS interpretation character integer unsigned integer integer long integer floating point number double precision float data ~ char int unsigned/unsigned int short long/long integer float long float/double 17: internal error 18: data type conflict size(bytes) 1 2 2 2 4 4 8 [see error 4J This message indicates an error in the use of the long or unsigned data type. long can be applied as a qualifier to int and float. unsigned can be used with char, int and long. long i; long float d; unsigned u; unsigned char c; unsigned long I; unsigned float f; 19: /* a long int */ /* a double */ /* an unsigned int */ /* error 18 */ obsolete Error codes interpreted as obsolete do not occur in release 1.06 of the compiler. Some simply no longer apply due to the increased adaptibility of the compiler. Other error codes have been translated into full messages sent directly to the screen. If you are using an older version of the product and have need of these codes, please contact MANX for information. 20: structure redeclaration The compiler is able to tell you if a structure has already been defined. This message informs you that you have tried to redefine a structure. 21: missing} The compiler expects to find a comma after each member in the list of fields for a structure initialization. After the last field, it expects a right (close) brace. struct sam { int bone: char license[lO]; Copyright (c) 1984 by Manx Software Systems, Inc. err.8 Aztec C CC ERRORS } harry = ( 1. 123-4-1984: 22: syntax error in structure declaration The compiler was unable to find the left (open) brace which follows the tag in a structure declaration. In the example for error 21, "sam" is the structure tag. A left brace must follow the keyword struct if no structure tag is specified. 23: obsolete 24: need right parenthesis or comma [see error 19J The right parenthesis is missing from a function call. Every function call must have an argument list enclosed by parentheses even if the list is empty. A right parenthesis is required to terminate the argument list. In the following example, the parentheses indicate that getchar is a function rather than a variable. getchar(); This is the equivalent of CALL getchar which might be found in a more explicit programming language. In general, a function is recognized as a name followed by a left parenthesis. With the exception of reserved words, any name can be made a function by the addition of parenthes~s. However, if a previously defined variable is used as a function name, a compilation error will result. Moreover, a comma must separate each argument in the list. For example, error 24 will also result from this statement: funccall(argl. arg2 arg3}. 25: structure member name expected here The symbol name following the dot operator or the arrow must be valid. A valid name is a string of alphanumerics and underscores. It must begin with an alphabetic (a letter of the alphabet or an underscore). In the last line of the following example, "(salary)" is not valid because 1(1 is not an Copyright (c) 1984 by Manx Software Systems, Inc. err.9 Aztec C CC ERRORS alphanumeric. empptr = &anderson: empptr->salary = 12000: (*empptr).salary = 12000: anderson. salary = 12000: empptr = &anderson.: empptr-> = 12000: anderson.(salary) = 12000: /* these three lines */ /* are */ /* equivalent */ /* error 25 */ /* error 25 */ /* error 25 */ 26: must be structure/union member The defined structure or union has no member with the name specified. If the -S option was specified, no previously defined structure or union has such a member either. Structure members cannot be created at will during a program. Like other variables, they must be fully defined in the appropriate declaration list. Unions provide for variably typed fields, but the full range of desired types must be anticipated in the union declaration. 27: illegal type cast It is not possible to cast an expression to a function, a structure, or an array. This message may also appear if a syntax error occurs in the expression to be cast. structure sam { ••• } thom: thom = (struct sam)(expression): 28: /* error 27 */ incompatible structures C permits the assignment of one structure to another. The compiler will ensure that the two structures are identical. However,that both structures must have the same st~ucture tag. For example: struct sam harry: struct sam thom; harry 29: = thom; illegal use of structure Not all operators can accept a structure as an operand. Also, structures cannot be passed as arguments. However , it is possible to take the address of a structure using the ampersand (&), to assign structures, and to reference a member of a structure using the dot operator. Copyright (c) 1984 by Manx Software Systems, Inc. err.IO Aztec C 30: CC ERRORS missing: in ? conditional expression The standard syntax for this operator is: expression ? statementl : statement2 It is not desirable to use ?: for extremely complicated expressions; its purpose lies in brevity and clarity. 31: call of non-function The following represents a function call: symbol (argl, arg2, ••• , argn): where "symbol is not a reserved word and the expression stands in the body of a function. Error 31, in re ference to the expression above, indicates that IIsymbol has been previously declared as something other than a function. ll li A missing operator may also cause this error: a(b + c): a * (b + c): /* error 31 */ /* intended */ The missing '*' makes the compiler view "a()" as a function call. 32: illegal pointer calculation Pointers may be involved in three calculations. An integral value can be added to or subtracted from a pointer. Pointers to objects of the same type can be subtracted from one another and compared to one another. (For a formal definition, see Kernighan and Ritchie pp. 188-189.) Since the comparison and subtraction of two pointers is dependent upon pointer size, both operands must be the same size. 33: illegal type The unary minus (-) and bit complement (-) operators cannot be applied to structures, pointers, arrays and functions. There is no reasonable interpretation for the following: int function ( ) : char array[12]: struct sam { } harry: a = -array: b = -harry: c = -function & WRONG: /* ? */ Copyright (c) 1984 by Manx Software Systems, Inc. err.ll Aztec C CC ERRORS 34: undefined symbol The compiler will recognize only reserved words and names which have been previously defined. This error is often the result of a typographical error or due to an omitted declaration. 35: typedef not allowed here Symbols which have been defined as types are not allowed within expressions. The exception to this rule is the use of sizeof(expression) and the cast operator. Compare the accompanying examples: struct sam { int i; } harry: typedef double bigfloat: typedef struct sam foo; j k x y = = = = 4 * big float. f-• &foo; sizeof(bigfloat); sizeof ( foo) : /* error 35 */ /* error 35 */ /* good */ The compiler will detect two errors in this code. In the first assignment, a typecast was probably intended; compare error 8. The second assignment makes reference to the address of a structure type. However, the structure type is just a template for instances of the structure (such as "harry"). It is no more meaningful to take the address of a structure type than any other data type, as in &int 36: no more expression space This message indicates that the expression table is not large enough for the compiler to process the source code. It is necessary to recompile the file using the -E option to increase the number of available entries in the expression table. See the description of the compiler in the manual. The command sequence should look like this: cc -E500 filename.c 37: invalid expression This error occurs in the evaluation of an expression containing a unary operator. The operand either is not given or is itself an invalid expression. Unary operators take just one operand: they work on just one variable or expression. If the operand is not simply missing, as Copyright (c) 1984 by Manx Software Systems, Inc. err.12 Aztec C CC ERRORS in the example below, it fails to evaluate to anything its operator can accept. The unary operators are logical not {I}, bit complement {~}, increment {++}, decrement {--}, unary minus {-}, typecast, pointer-to (*), address-of (&), and sizeof. if (1) ., 38: no auto. aggregate initialization It is not permitted to initialize automatic arrays and structures. Static and external aggregates may be initialized, but by default their members are set to zero. char array[S] function ( ) = { la l , 'b l , IC I , Id l , }_ { static struct sam { int bone: char license[10]: } harry = { 1, -123-4-1984" }: char autoarray[2] = { If I, Igi }: extern char array[]: /* no good */ } There are three variables in the above example, only two of which are correctly initialized. The variable "array" may be initialized because it is external. Its first four members will be given the characters as shown. The fifth member will be set to zero. The structure "harry" is static and may be initialized. Notice that "license" cannot be initialized without first giving a value to "bone". There are no provisions in C for setting a value in the middle of an aggregate. The variable "autoarrayll is an automatic array. That is, it is local to a function and it is not declared to be static. Automatic variables reappear automatically every time a function is called, and they are guaranteed to contain garbage. Automatic aggregates cannot be initialized. 39: obsolete [see error 19J 40: internal [see error 4J 41: initializer not a constant In certain initializations, the expression to the right of Copyright {c} 1984 by Manx Software Systems, Inc. err.I3 Aztec C CC ERRORS the equals sign (=) must be a constant. Indeed, only automatic and register variables may be initialized to an expression. Such initializations are meant as a convenient shorthand to eliminate assignment statements. The initialization of statics and globals actiually occurs at link-time, and not at run-time. { int i = 3: static int j = (2 + i): /* il1egal */ } 42: too many initializers There were more values found in an initialization than array or structure members exist to hold them. Either too many values were specified or there should have been more members declared in the aggregate definition. In the initialization of a complex data structure, it is possible to enclose the initializer in a single set of braces and simply list the members, separated by commas. If more than one set of braces is used, as in the case of a structure within a structure, the initializer must be entirely braced. struct { struct { char arraY[]i } substruct: } superstruct = version 1: { "abcde£ghij}: version 2: { { { ' a l,i b i , IC I , } ..., IJ.-I , I )"I} }: In version 1, the initializers are copied byte-for-byte onto the structure, superstruct. Another likely source of this error is in the initialization of arrays with strings, as in: char array[10]= "abcdefghij-: This will generate error 42 because the string constant on the right is null-terminated. The null terminator ('\0' or axao) brings the size of the initializer to 11 bytes, which overflows the ten-byte array. Copyright (c) 1984 by Manx Software Systems, Inc. err. 14 Aztec C 43: CC ERRORS undefined structure initialization An attempt has been made to assign values to a structure which has not yet been defined. struct sam { ••• }: struct dog sam = { 1. 2. 3}: /* error 43 */ [see error 19J 44: obsolete 45: bad declaration syntax This error code is an all purpose means for catching errors in declaration statements. It indicates that the compiler is unable to interpret a word in an external declaration list. 46: missing closing brace All the braces did not pair up at the end of compilation. If all the preceding code is correct, this message indicates that the final closing brace to a function is missing. However, it can also result from a brace missing from an inner block. Keep in mind that the compiler accepts or rejects code on the basis of syntax, so that an error is detected only when the rulei of grammar are violated. This can be misleading. For example, the program below will generate error 46 at the end even though the human error probably occurred in the while loop several lines earlier. As the code appears here, every statement after the left brace in line 6 belongs to the body of the while loop_ The compilation error vanishes when a right brace is appended to the end of the program, but the results during run time will be indecipherable because the brace should be placed at the end of the loop. It is usually best to match braces visually before running the compiler. A C-oriented text editor makes this task easier. main ( ) { int i. j: char array[80]; gets ( array) : i = 0: while (array[i]) { putchar(array[i]): i++: for ( i=O: array[i];i++) { for (j=i + 1; array[j]; j++) Copyright (c) 1984 by Manx Software Systems, Inc. { err.IS Aztec C CC ERRORS printf( Delements %d and %d are if (array[i] == array[j]) printf( lithe same\n-): else printf(-different\n a ) : II, i, } putchar( I \n·); } } 47: open failure on include file When a file is 'included, the compiler will look for it in a default area (see the manual description of the compiler). This message will be generated if the file could not be opened. An open failure usually occurs when the included file does not exist where the compiler is searching for it. Note that a drive specification is allowed in an include statement, but this diminishes flexibility somewhat. 48: illegal symbol name This message is produced by the preprocessor, which is that part of the compiler which handles lines which begin with a pound sign (#). The source for the error is on such a line. A legal name is a string whose first character is an alphabetic (a letter of the alphabet or an underscore). The succeeding characters may be any combination of alphanumerics (alphabetics and numerals). The following symbols will produce this error code: 2nd time, dont do this! 49: multiply defined symbol This message warns that a . symbol has already been declared and that it is illegal to redeclare it. The following is a representative example: int i, j, k, i: 50: /* illegal */ missing bracket This error code is used to indicate the need for parenthesis, bracket or brace in a variety of circumstances. 51: a lvalue required only lvalues are are allowed to stand on the left-hand side of an assignment. For example: Copyright (c) 1984 by Manx Software Systems, Inc. err.16 Aztec C CC ERRORS int num: num = 7: They are distinguished from rva1ues, which can never stand on the left of an assignment, by the fact that they refer to a unique location in memory where a value can be stored. An Iva1ue may be thought of as a bucket into which an rva1ue can be dropped. Just as the contents of one bucket can be passed to another, so can an lvalue y be assigned to another lvalue, x: 'define NUMBER 512 x = y: /* wrong: 1/rvalues are reversed */ 1024 = z·, /* wrong: NUMBER is sti11 an rva1ue */ NUMBER = x: Some operators which require Iva1ues as operands are increment (++), decrement (--), and address-of (&). It is not possible to take the address of a register variable as was attempted in the following example: register int i, j: i = 3: j = &i; [see error 16] 52: obso1ete 53: mu1tip1y defined 1abe1 On occasions when the goto statement is used, it is important that the specified label be unique. There is no criterion by which the computer can choose between identical labels. If you have trouble finding the duplicate label, use your text editor to search for all occurrences of the string. 54: too many 1abe1s The compiler maint~ins an internal table of labels which will support up to several dozen labels. Although this table is fixed in size, i t should satisfy the requirements of any reasonable C program. C was structured to discourage extravagance in the use of goto's. Strictly speaking, goto statements are not required by any procedure in Ci they are primarily recommended as a quick and simple means of exiting from a nested structure. This error indicates that you should significantly reduce the number of goto's in your program. 55: missing quote Copyright (c) 1984 by Manx software Systems, Inc. err.17 Aztec C CC ERRORS The compiler found a mismatched double quote (") in a 'define preprocessor command. unlike brackets, quotes are not paired innermost to outermost, but sequentially. So the first quote is associated with the second, the third with the fourth, and so on. Single quotes (I) and double quotes (") are entirely different characters and should not be confused. The latter are used to delimit string constants. A double quote can be included in a string by use of a backslash, as in this example: "this is a string" "this is a string with an embedded quote: \". 56: II missing apostrophe The compiler found a mismatched single quote or apostrophe in a 'define preprocessor command. Single quotes are paired sequentially (see error 55). Although quotes can not be nested, a quote can be represented in a character constant wi th a backslash: (I) char c = 1\11; /* c is initialized to single quote 57: */ 1ine too 10ng Lines are restricted in length by the size of the buffer used to hold them. This restriction varies from system to system. However, logical lines can be infinitely long by continuing a line with a backslash-newline sequence. These characters will be ignored. 58: i11egal t encountered The pound sign (#) begins each command for the preprocessor: 'include, ,define, 'if, 'ifdef, 'ifndef, .else, .endif, .asm, 'endasm. 'line and iundef. These symbols are strictly defined. The pound sign (#) must be in column one and lower case letters are required. Copyright (c) 1984 by Manx Software Systems, Inc. err.I8 Aztec C 59: CC ERRORS macro too long Macros can be defined with a preprocessor command of the following form: 'define [identifier] [substitution text] The compiler then proceeds to replace all instances of "identifier" with the substitution text that was specified by the ,define. This error code refers to the substitution text of a macro. Whereas ideally a macro definition may be extended for an arbitrary number of lines by ending each line with a backslash (\), for practical purposes the size of a macro has been limited to 255 characters. 60 : obsolete [see error 19J 61: reference of member of undefined structure Occurs only under compilation without the Consider the following example: int bone: struct cat { int toy; } manx; struct dog *samptr; manx. toy = 1: bone = samptr->toy: -s option. /* error 61 *1 This error code appears most often in conjunction with this kind of mistake. It is possible to define a pointer to a structure without having already defined the structure itself. In the example, samptr is a structure pointer, but what form that structure ("dog ll ) may take is still unknown. So when reference is made to a member of the structure to which samptr points, the compiler replies that it does not even known what the structure looks like. The -8 compiler option is provided to duplicate the manner in which earlier versions of UNIX treated structures. Given the example above, it would make the compiler search all previously defined structures for the member in question. In particular, the value of the member IItoyll found in the structure "manx" would be assigned to the variable IIbone The -s option is not recommended as a short cut for defining structures. li • 62: function body must be compound statement The body of a function must be enclosed by braces, Copyright (c) 1984 by Manx Software Systems, Inc. even err.19 Aztec C though it may consist of only one statement: function{) { return 1; } 63: undefined label A goto statement is meaningless if the corresponding label does not appear somewhere in the code. The compiler disallows ~his since it must be able to specify a destination to the computer. It is not possible to goto a label outside the present function (labels are local to the function in which they appear). Thus, if a label does not exist in the same procedure as its corresponding goto, this message will be generated. 64: inappropriate arguments When, a function is declared (as opposed to defined), it is poor syntax to specify an argument list: function{string) char *string; ( char *funcl(); double func2(x,y); /* correct */ /* wrong */ } In this example, function() is being defined, but funcl() and func2() are being declared. 65: illegal or missing argument name The compiler has found an illegal name in a function argument list. An argument name must conform to the same rules as variable names, beginning with an alphabetic (letter or underscore) and continuing with any sequence of alphanumerics and underscores. Names must not coincide with reserved words. 66: expected comma In an argument list, arguments must be separated by commas. 67: invalid else An else was found which is not associated with an , Copyright (c) 1984,by Manx Software Systems, Inc. if err.20 Aztec C CC ERRORS statement. else is bound to the nearest if at its own level o·f nesting. So if-else pairings are determined by their relative placement in the code and their grouping by braces. if( ••• ) { if ( ••• ) { .} else if ( ••• ) } else { ... } The indentation of the source text should indicate the intended structure of the code. Note that the indentation of the if and else-if means only that the programmer wanted both conditionals to be nested at the same level, in particular one step down from the presiding if statement. But it is the placement of braces that determines this for the compiler. The example above is correct, but probably does not conform to the expectations revealed by the indentation of the else statement. As shown here, the else is paired with the first if, not the second. 68: syntax error The keywords used in declaring a variable, which specify storage class and data type, must not appear in an executable statement. In particular, all local declarations must appear at the beginning of a block, that is, directly following the left brace which delimits the body of a loop, conditional or function. Once the compiler has reached a non-declaration, a keyword such as char or int must not lead a statement; compare the use of the casting operator: func{ ) { int ii char array[12]i float k = 2.03: i = 0: int m: j = i /* error 68 */ + 5: = (int)k: if (i) { int i = 3: j = i: printf( a%d ll , i); 1 /* correct */ } printf(a%d%d\n",i,j): } This trivial function prints the values 3, Copyright (c) 1984 by Manx Software systems, Inc. 2 and 3. The err.21 Aztec C CC ERRORS variable i which is declared in the body of the conditional (if) lives only until the next right brace; then it dies, and the original i regains its identity. 69: missing semicolon A semicolon is missing from the end of an executable statement. This error code is subject to the same vagaries as its cousin, error 7. It will remain undetected until the following line and is often spuriously caused by a previous error. 70: bad goto syntax Compare your use of goto with an example. This message says that you did not specify where you wanted to goto with a label: goto label; label: It is not possible to goto just any identifier in the source code; labels are special because they are followed by a colon. 71: statement syntax error in do-while The body of a do-while may consist of one statement or several statements enclosed in braces. A while conditional is required after the body of the loop. This is true even if the loop is infinite, as it is required by the rules of syntax. Af~er typing in a long body, don't forget the while conditional. 72: statement syntax error in for This error focuses on another control flow statement, the for. The keyword, for, must be followed by parentheses. In the parentheses belong three expressions, any or all of which may be null. For the sake of clarity, C requires that the two semicolons which separate the expressions be retained, even if all three expressions are empty. for (;;) , . 73: /* an infinite loop which does */ /* absolutely nothing */ statement syntax error in for See error 72. Copyright (c) 1984 by Manx Software systems, Inc. err.22 Aztec C CC ERRORS 74: case value must be integer constant Strictly speaking, each value in a case statement must be a constant of one of three types: char, int or unsigned. This is similar to the rule for a switched variable. In the following example, a float must be cast to an int in order to be switched: however, notice that the programmer did not check his case statements. The second case value is invalid, and the code will not compile. float k = 5.0: switch«int)k) { case 4: printf(ngood case value\nn): break: case 5.0: printf("bad case value\n U ) : break: } The programmer must replace "case 5.0:" with "case 5". 75: missing colon on case This should be straightforward. case value, a colon should follow it. accidently entered in its place. 76: If the compiler accepts a A semi-colon must not be too many cases in switch The compiler reserves a limited number of spaces in an internal table for case statements. If a program requires more cases than the table initially allows, it becomes necessary to tell the compiler what the table value should be changed to. It is not necessary to know exactly how many are needed: an approximation is sufficient, depending on the requirements of the situation. The following command line will change the size of the case table to 200 entries for the compilation of the file, switchit.c: cc -Y200 switchit.c 77: case outside of switch The keyword, case, belongs to just one syntactic structure, the switch. If "case" appears outside the braces which contain a switch statement, this error is generated. Remember that all keywords are reserved, so that they cannot be used as variable names. Copyright (c) 1984 by Manx Software Systems, Inc. err.23 Aztec C CC ERRORS 78: missing colon This message indicates that a colon is missing after the keyword, default. Compare error 75. 79: duplicate default The compiler has found more than one default in a switch. Switch will compare a variable to a given list of values. But it is not always possible to anticipate the full range of values which the variable may take. Nor is it feasible to specify a large number of cases in which the program is not particularly interested. So C provides for a default case. The default will handle all those values not specified by a case statement. It is analogous to the else companion to the conditional, if. Just as there is one else for every if, only one default case is allowed in a switch statement. However, unlike the else statement, the position of a default is not crucial; a default can appear anywhere in a list of cases. 80: default outside of switch The keyword, "default", is used just like "case It must appear within the brackets which delimit the switch statement. ll • 81: break/continue error Break and continue are used to skip the remainder of a loop in order to exit or repeat the loop. Break will also end a switch statement. But when the keywords, break or continue, are used outside of these contexts, this message results. 82: illegal character Some characters simply do not make sense in a C program, such as 1$1 and '@'. Others, for instance the pound sign (#), may be valid only in particular contexts. 83: too many nested includes #includes can be nested, but this capacity is limited. The compiler will balk if required to descend more than three levels into a nest. In the example given, file D is not allowed to have a #include in the compilation of file A. file A #include "B" file B #include "C" file C #include liD file D II Copyright (c) 1984 by Manx Software Systems, Inc. err.24 Aztec C 84: CC ERRORS too many array dimensions An array is declared with too many dimensions. should appear in conjunction with error 11. 85: This error not an argument The compiler has found a name in the declaration list that was not in the argument 1 ist. Only the converse case is valid, i.e., an argument can be passed and not subsequently declared. 86: null dimension in array In certain cases, the compiler knows how to treat multidimensional arrays whose left-most dimensions are not given in its declaration. Specifically, this is true for an extern declaration and an array ini tialization. The value of any dimension which is not the left-most must be given. extern char array[][l2]: extern char badarray[5][]i 87: /* correct */ /* wrong '*/ invalid character constant Character constants may consist of one or two characters enclosed in single quotes, as la l or 'ab ' . There is no analog to a null string, so .. (two single quotes with no intervening white space) is not allowed. Recall that the special backslash characters (\b, \n, \ t etc.) are singular, so that the following are valid: I\n ' , I\na ' , la\n ' ; laaa l is invalid. 88: not a structure Occurs only under compilation without the -S option. A name used as a structure does not refer to a structure, but to some other data type. int i; i.member = 3; /* error 88 */ 89: invalid storage class A globally defined variable cannot be specified as register. Register variables are required to be local. 90: symbol redeclared A function argument has been declared more than once. Copyright (c) 1984 by Manx Software Systems, Inc. err.25 Aztec C 91: CC ERRORS illegal use of floating point type Floating point numbers can be negated (unary minus), added, subtracted, multiplied, divided and compared; any other operator will produce this error message. 92: illegal type conversion This error code indicates that a data type conversion, implicit in the code, is not allowed, as in the following piece of code: int i; float j: char *ptr; i = j + ptr; The diagram shows how variables are converted to different types in the evaluation of expressions. Initially, variables of type char and short become int, and float becomes double. Then all variables are promoted to the highest type present in the expression. The result of the expression will have this type also. Thus, an expression containing a float will evaluate to a double. hierarchy of types: double <-- float long unsigned int <-- short, char 93: illegal expression type for switch Only a char, int or unsigned variable can be switched. the example for error 74. See 94: bad argument to define An illegal name was used for an argument in the definition of a macro. For a description of legal names, see error 65. 95: no argument list When a macro is defined with arguments, any invocation of that macro is expected to have arguments of corresponding form. This error code is generated when no parenthesized argument list was found in a macro reference. Copyright (c) 1984 by Manx Software Systems, Inc. err.26 Aztec C CC ERRORS getchar( ) 'define c = getc(stdin) getchari /* error 95 */ 96: missing argument to macro Not enough arguments were found in an invocation of a macro. Specifically, a IIdouble comma" will produce this error: 'define reverse(x.y.z) (z,y,x) func(reverse(i •• k»i 97: obsolete 98: not enough args in macro reference [see error 19J The incorrect number of arguments was found in an invocation of a previously defined macro. As the examples -show, this error is not identical to error 96. 'define exchange (x.y) func(exchange(i»; 99: internal [see error 4J 100: internal [see error 4J (y,x) /* error 98 */ 101: missing close parenthesis on macro reference A right (close) parenthesis is expected in a macro reference with arguments. In a sense, this is the complement of error 95; a macro argument list is checked for both a beginning and an ending. 102: macro arguments too long The combined length of a macro's arguments is limited. This error can be resolved by simply shortening the arguments with which the macro is invoked. 103: .else with no lif Correspondence between lif and lelse is analogous to that which exists between the control flow statements, if and else. Copyright (c)J 1984 by Manx Software Systems, Inc. err.27 Aztec C CC ERRORS Obviously, much depends upon the relative placement of the statements in the code. However, #if blocks must always be terminated by #endif, and the #else statement must be included in the block of the #if with which it is associated. For example: lif ERROR > 0 printf( "there was an error\n-): telse printf(-no error this time\n-): tendif #if statements can be nested, as below. The range of each #if is determined by a #endif. This also excludes #else from #if blocks to which it does not belong: lifdef lif JAN! printf(-happy new yearl\n-): sick printf(Hi think ilil go home now\n-): 'else printf(-i think ilil have another\n-): 'endif 'else printf("i wonder what day it is\n-): 'endif If the first #endif was missing, error 103 would result. And without the second #endif, the compiler would generate error 107. 104: tendif with no tif #endif is paired with the nearest #if, #ifdef or #ifndef which precedes it. (See error 1 03.) 105: 'endasm with no 'asm #endasm must appear after an associated #asm. These compiler-control lines are used to begin and end embedded assembly code. This error code indicates that the compiler has reached a #endasm without having found a previous #asm. If the #asm was simply missing, the error list should begin with the assembly co~e (which are undefined symbols to the compiler). 106: 'asm within lasm block There is no meaningful sense in which in-line assembly code can be nested, so the #asm keyword must not appear between a paired #asm/ #endasm. When a piece of in-line ass~mbly is augmented for temporary purposes, the old #asm and #endasm can be enclosed in comments as place-holders. 'asm Copyright (c) 1984 by Manx Software Systems, Inc. err.28 Aztec C CC ERRORS /* temporary asm code * / /* 'asm old beginning /* more asm code */ */ lendasm 107: missing lendif A #endif is required for every #if, #ifdef and #ifndef, even if the entire source file is subject to a single conditional dompilation. Try to assign pairs beginning with the first #endif. Backtrack to the previous #if and form the pair. Assign the next #endif with the nearest unpaired #if. When this process becomes greatly complicated, you might consider rethinking the logic of your program. 108: missing lendasm In-line assembly code must be terminated by a #endasm in all cases. #asm must always be paired with a #endasm. 109: lif value must be integer constant iif requires an integral constant expression. This allows both integer and character constants, the arithmetic operators, bitwise operators, the unary minus (-) and bit complement, and comparison tests. Assuming all the macro constants (in capitals) are integers, lif DIFF >= IAI-Ia l lif (WORD &= -MASK) » lif MAR I APR I MAY 8 are all legal expressions for use with #if. 110: invalid use of colon operator The colon operator occurs in two places: 1. following a question mark as part of a conditional, as in (flag? 1 : 0); 2. following a label inserted by the programmer or following one of the reserved labels, case and default. Ill: illegal use of a void expression This error can be caused by assigning a void expression to a variable, as in this example: void func(); int h; h Copyright (c~ = func(arg); 1984 by Manx Software Systems, Inc. err.29 Aztec C CC ERRORS 112: illegal use of function pointer For example, int (*funcptr) (): ... funcptr++: funcptr is a pointer to a function which returns an integer. Although it is like other pointers in that it contains the address of its object, it is not suject to the rules of pointer arithmetic. otherwise, the offending statement in the example would be interpreted as adding to the pointer the size of the function, which is not a defined value. 113: duplicate case in switch This simply means that, in a switch statement, there are two case values which are the same. Either the two cases must be combined into one, or one of them must be" discarded. For instance: switch (c) { case HOOP: return (0) : case MULT: return (x * y): case DIV: return (x / y) : case ADD: return (x + y): case HOOP: default: return: } The case of NOOP is duplicated, and will generate an error. 114: macro redefined For example, 'define ... 'define islow(n) (n>=0&&n<5) islow(n) (n>=0&&n<=5) The macro, islow, is being used to classify a numerical value. When a second definition of it is found, the compiler will compare the new substitution string with the previous one. If they are found to be different, the second definition will become current, and this error code will be produced. Copyright (d) 1984 by Manx Software Systems, Inc. err.30 Aztec C CC ERRORS In the example, the second definition differs from the first in a single character, 1 = 1 . The second definition is also different from this one: 'define islow(n) n>=O&&n<=5 since the parentheses are missing. The following lines will not generate this error: ,define NULL 0 'define NULL 0 ... But these are different from: ,define In practice, this error message does not affect the compilation of the 'source code. The most recent "revision" of the substitution string is used for the macro. But relying upon this fact may not be a wise habit. 115: keyword redefined Keywords cannot be defined as macros, as in: 'define int foo If you have a variable which may be either, for instance, a short or a long integer, there ar'e alternative methods for switching between the two. If you want to compile the variable as either type of integer, consider the following: tifdef LOBGIHT long i: 'else short i: lendif Another possibility is through a typedef: 'ifdef LONGIRT typedef long 'else typede£ short ,endif VARTYPE: VARTYPE: VARTYPE i: Copyright (0) 1984 by Manx Software Systems, Inc. err.3l Aztec C CC ERRORS Fata1 Error Messages I f the compiler encouters a II fatal ll error, one which makes further operation impossible, it will send a message to the screen and end the compilation immediately. 1. Out of disk space1 There is no room on the disk for the output file of the compiler. previous disk files will not be overwritten by the compiler's assembly language output. To make room on the disk, it is usually sufficient to remove unneeded files from the disk. 2. unknown option: The compiler has been invoked with an option letter which it does not recognize. The manual explicitly states which options the compiler will accept. The compiler will specify the invalid option letter. 3. duplicate output file If an output file name has been specified with the -0 option and that file already exists on the disk, the compiler will not overwrite it. -0 must specify a new file. 4. too few arguments for Usage of the -0 -0 option option is as follows: cii -0 newfile.asm oldfile.c The new file name must follow the option letter and the name of the file to be compiled must occur last in the command line. 5. Open failure on input The input file specified in the command line does not exist on the disk or cannot be opened. A path or drive specification can be included with a filename according to the operating system in use. 6. No input 1 While the compiler was able to open the input file given in the command line, that file was found to be empty. 7. Open failure on output 8. Local table full1 The compiler Copyright (c 1 ) (use -L) maintains an internal table of the 1984 by Manx Software Systems, Inc. local err.32 Aztec C CC ERRORS variables in the source code. If the number of local symbols in use exceeds the available entries in the table at any time during compilation, the compiler will print this message and quit. The default size of the local symbol table (40 entries) can be changed with the -L option for the compiler: cii -LlOO filename.c Local variables function body or variable is the defined until the 9. are those defined within braces, i.e., in a in a compound statement. The scope of a local body in which it is defined, that is, it is next right brace at its own nesting level. out of memory 1 Since the compiler must maintain various tables in memory as well as manipulate source code, it may run out of memory during operation. The more immediate solution is to vary the sizes of the internal tables using the appropriate compiler options. Often, a compilation will require fewer than the default number of entries in a particular table. By reducing the size of that table, memory space is freed up during compile time. The amount of memory used while compiling does not affect the size or content of the assembly or object file output. If this stategy fails to squeeze the compilation into the available memory, the only solution is to divide the source file into modules which can be compiled separately. These modules can then be linked together to produce a single executable file. I copyright (e) 1984 by Manx Software Systems, Inc. err.33 Aztec C AS ERRORS ASSEMBLER ERROR 'CODES Most errors during assembly are caused by assembly language code written by the programmer. The assembler supplied by Manx is tailored to accept code generated by the Aztec compiler. However, the programmer is free to write his own assembler code either in-.line or as separate modules, and to modify the output of the compiler. 1. No space for expression work areall or No symbol table space leftlll Both of these messages essentially mean lIout of memory. II 2. is undefined The message will specify an undefined symbol name. 3. invalid character in number A digit is not within the range of valid numerals for the particular base. For example, IFI is invalid in an octal or decimal number. 4. Invalid expression for block allocation The operand given a define storage opcode must be an absolute expression, i.e., all symbols in it must have been previously defined. 5. Multiply defined symbol A symbol has been defined more than once. 6. Cannot redefine symbol The left hand side of an lIequ ll is a symbol which cannot be redefined, such as a code label. 7. Cannot open file An included file cannot be opened. 8. Too many nested includes Included files have been nested too deeply. Copyright (c) 1984 by Manx Software Systems, Inc. err.34 Aztec C 9. AS ERRORS Operand out of range The operand does not fall within the possible range of values for the given opcode, e.g., RST 8. 10. Operand must be even register For example, register pair. 11. L was referenced instead of H in the HL Global size must be absolute or BSS size must be absolute The second operand given the global or BSS opcode must be an absolute expression. 12. Location counter must always increase I.e., the location counter cannot be reset backward. 13. can't change type of location counter For example, equ 14. dseg_symbol Cannot equ a common block name The left-hand symbol of an equ cannot be the name of a common block. 15. Null string not allowed here A null string (II) is not allowed in an expression. 16. Too many chars in CHAR constant A character constant may consist of up to two characters. Any more will be ignored by the assembler. 17. invalid operator in evaluate This is an internal assembler error. Try reassembling with new copies of the assembler and your file to ensure that neither is bad. If this error is produced consistently, please contact Manx with the problem. Copyright (0) 1984 by Manx Software Systems, Inc. err.35 Aztec C AS ERRORS Linker Errors Command line errors: 1. 2. 3. 4. 5. 6. unknown option ' ' too few arguments in command line. No input given1 Cannot have nested - f options. too few arguments in - f file: multiple declarations, last one used. I/O errors: 7. 8. 9. 10. 11. 12. 13. can't open , err= Cannot open -f file: I/O error ( Cannot create symbol table output Cannot create overlay symbol table output Corrupted object files: 14. 15. 16. 17. 18. object file is bad1 invalid operator in evaluate library format is invalid1 Cannot read module from on pass2 can't find symbol, , on pass two is not a reI filel Errors in use of Memory: 19. 20. 21. 22. Insufficient memory 1 TOO many symbols 1 -C or -D value less than base address Code and data regions overlap Errors arising from source code: 23. 24. 25. 26. 27. Undefined symbol: mUltiply defined passl{ org out of range in Object file undefined COMMON Copyright (d) 1984 by Manx Software Systems, Inc. err.36 'Aztec C LR ERRORS LINKER ERROR CODES When invoked by a command line beginning with LN, the linker will process the arguments given i~, perform the linkage request~d and generate an executable output file on the disk. The first line to ~ppear on the screen is a banner which indicates' that the linker has been loaded and is run~ing. If everything goes well, the base address message will follow and the linker will' finish. The linker may encounter an error while it is run'hing, in which case it will send a verbal message to the screen. ;. . Error~ may be reported at a variety of points during the linking process. LN consists of two stages, known as pass land pass 2. The base address message is printed at the end of pass I, so any errors occurring after that have been detected during pass 2 of the linker. Following is a·list of the messages which the linker will generate in response to an error. The messages are grouped aC90rding to the source of the errors which cause them. Elements which: 'are variable are enclosed by angled brackets: .< > • Command line errors: 1. unknown option ' ' An option letter has been specified which the linker does not recognize. Only the letter will be ignored: everything else on the command line has been preserved, and the linker will try to exectite what it has interpreted. S~e page [J for a list of options which are supported. J 2. too few arguments in command line. It Several of the linker options have an associated value or name, such as -B 2000. If a needed value is missing, the linker will give this message and die. 3. No input given1 The linker will quit immediately if not given any input to process. 4. Cannot have nested -f options. A file which is given as a -f argument can contain any option lett~r except -f itself. However, more than one -f is allowed on a command line. 5. too few arguments in -f file: An option letter specified in the file, "filename," requires Copyright (c) 1984 by Manx Software Systems, Inc. err.37 Aztec C La ERRORS a value or name to follow it. If an option appears at the end of the file, its associated value may not appear back on the command line. 6. multiple declarations, last one used. The message will specify that one of the following option letters was specified more than once in the command line: -:,C -D -u -B code org data org udata org base origin of code in memory origin of data origin of uninitialized global/static data base address of memory The linker will consider only the last use of an option letter when it runs. I/O errors: 7. can't open , err= If any file in the command line cannot·be opened, this message will be sent to the screen, specifying the 'filename and the current value of errno. 8. Cannot open -f file: A file given with the -f option cannot be opened. 9. I/O error «errno» reading/writing output file An error reading or writing the output file probably means there is no more disk space available. In particular, a block of the output file was written to disk and then could not be read back. The current value of errno is given in these messages. 10. Cannot write output file See error 9. 11. Cannot create output file: This message usually indicates that all available directory space on the disk has been exhausted. 12. Cannot create symbol table output The -T option was given in the command line, but the file containing the linkage symbol table cannot be written to disk. It is possible that there is no more space on the disk. 13. Cannot create overlay symbol table output Occurs when using the -R option. The file containing the Copyright (c) 1984 by Manx Software Systems, Inc. err. 38 Aztec C LR ERRORS overlay symbol table cannot be written to disk. Corrupted object files: 14. object file is badl This is the most explicit indication that an object file in the linkage has been corrupted. The solution is simply to recompile and assemble the source file. A bad object file will not be discovered until the second pass of the linker. 15. invalid operator in evaluate This is really the same as error 14. Unless you have changed the object code by hand, the file has been corrupted. 16. library format is invalidl A library in the linkage has been corrupted. 17. Cannot read module from on pass2 or can't find symbol, , on pass two Either message indicates that a module has been corrupted between pass 1 and pass 2. On a multiuser system, it is possible that another user changed the file while the linker was running. Otherwise, the error was probably due to a hardware failure. 18. is not a rel file! A file given to the linker does not contain relocatable object code which LN can process. For instance, a source file may have been included in the link. Errors in use of memory: 19. Insufficient memory! The linkage process needs memory space for LN, global and local symbol tables, and approximately 5K for buffers. Just as with compilation, most memory use is devoted to the program software and symbol tables. Since LN is not especially large, only an extremely complicated linkage might run out of memory. 20. Too many symbols! This is another way of saying that not enough memory was available for the symbol tables needed for the linkage. 21. -C or -D value less than base address It is not possible for the starting address of the code or Copyright (c) 1984 by Manx Software Systems, Inc. err.39 Aztec C LB ERRORS data to be less than the base address of the specified by the option, -B. progr~m, which is 22. By default, data resides above the code area in memory. The starting addresses of both areas must be spaced far enough apart to accommodate all the code. If the -D option is used to begin the data area in the middle of the code, this error message will be put out. Errors arising from source code: 23. Undefined symbol: A global symbol name has remained undefined. This is commonly a function which has been referenced in the source code but not included anywhere in the link. 24. m~ltiply defined A global symbol has been defined more than once. For instance, if two functions are accidentally given the same name, this message will be generated. 25. passl«hex value» and pass2«hex value» values differ: or symbol type differs on pass two: Either of these errors may be generated during pass 2 when error 24 appeared in pass 1. They may be considered a confirmation of what was discovered in pass 1 of the linker. 26. Org out of range in object file On the source code level, this means that a globai symbol was defined in the root of an overlay and then initialized in an overlay module. For example, root: overlay: int i; extern int i = 3; The problem arises because the initialization is performed by the linker, but the variable to be initialized is in an entirely different file. Copyright (c) 1984 by Manx Software Systems, Inc. err.40 Aztec C IB JlRRORS The situation which follows is valid because the asstgnment statement is evaluated at run time: root: overlay: int i; extern int i: function() { } 27. extern it.t i; i = 3; undefined COMMON This error now occurs only in reference to the use~'s own assembly language routines. It is generated by a COMMON b~ock of size zero. Copyright (c) 1984 by Manx Software Systems, Inc. err.41
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.3 Linearized : No XMP Toolkit : Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 Create Date : 2013:04:07 09:56:11-08:00 Modify Date : 2013:04:07 09:58:26-08:00 Metadata Date : 2013:04:07 09:58:26-08:00 Producer : Adobe Acrobat 9.52 Paper Capture Plug-in Format : application/pdf Document ID : uuid:316224b3-fe53-4c80-a418-a7a4ead748ae Instance ID : uuid:4bb4a6b1-5e63-4928-b9e1-b337e97092bb Page Layout : SinglePage Page Mode : UseOutlines Page Count : 242EXIF Metadata provided by EXIF.tools