home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
BDSC
/
BDSC-3
/
V145.DQC
/
V145.DOC
Wrap
Text File
|
2000-06-30
|
23KB
|
406 lines
BDS C User's Guide Addenda
v1.45 Edition -- December, 1981
Leor Zolman
BD Software
33 Lothrop st.
Brighton, Massachussetts 02135
Here are the bug fixes and extensions for BDS C version 1.45.
Note: If you are running under MP/M II, be sure to see item 10 below!
0. Expressions of the form
!(expr || expr)
or !(expr && expr)
may not have worked correctly when a VALUE was required for the
expression; i.e., when used in some way other than in a flow control test.
For example,
x = !(a || b);
might have failed, but
if (!(a || b)) return 7;
would have worked, since the expression was used for flow control.
1. Declarations of pointer-to-function variables for functions returning a
CHARACTER value caused only one byte of storage to be reserved for the
pointer, instead of two bytes (all pointers-to-functions require two bytes
of storage, by virtue of being pointers). For example, in the sequence:
char c1, (*ptrfn)(), c2;
...
ptrfn = &getc;
the assignment to `ptrfn' would have incorrectly overwritten the `c2'
character variable, since only one byte would have been reserved on the
stack for the `ptrfn' variable while the assignment operation would have
assumed there were two bytes reserved.
2. A bug in the ternary operator evaluator (?: expressions) caused the
high-order byte of a 16-bit result to be incorrectly zeroed in the
following situation: given a ternary expression of the form
e1 ? e2 : e3
where `e2' evaluated to a 16-bit value (int, unsigned or pointer) and `e3'
evaluated to a character value (type char only), the entire expression was
treated as having type char...so if `e1' was true and `e2' was bigger than
255, then the value of the expression ended up as only the low-order byte
of the value of `e2'. For version 1.45, whenever `e2' and `e3' do not BOTH
evaluate to character values the type of the overall expression is
guaranteed not to be char.
3. A sequence of two `!' (logical `not') operators in a row did not always
produce the correct result in an expression. For example,
x = !!n; /* convert n to a logical (0 or 1) value */
might have produced the wrong result (0 instead of 1, or vice-versa).
4. A stack-handling bug in CC2 caused problems at run time when a
sufficiently complex sub-expression appeared in any but the final position
of an expression involving the comma operator (","). For example, the
following statement would not have worked correctly:
for (i = 0; i < 10; x += y, i++) ...
5. CC1 has not been recognizing illegal octal character constants as such;
digits such as `8' and `9' within an octal constant will now draw an error
in cases where they would have been ignored before. Also, certain other
forms of illegal constants (aside from character constants) are now better
diagnosed than before.
6. I found one more case where an internal table overflow during code
generation was not detected, causing the final command file to bomb as
soon as it was executed (either by crashing the machine or immediately
re-booting.) This occurred when a single large function containing many
string constants was compiled. All fixed now.
7. An extension to the linker: CLINK now recognizes "DEFF3.CRL" as an
automatic library file, similar to DEFF.CRL and DEFF2.CRL. Note that there
is NO DEFF3.CRL file included with the BDS C package; this feature has
been added to allow you to fit more custom functions into your library
than just what fits in DEFF.CRL and DEFF2.CRL (which are getting rather
full.)
Also, CLINK will now search ALL default library files (DEFF.CRL, DEFF2.CRL
and DEFF3.CRL [if it exists]) when a carriage-return is typed in
interactive mode. Previously, only the file DEFF.CRL was searched in
response to carriage-return.
8. It has been brought to my attention that the ^Q-CR sequence required by
CLINK in interactive mode (to abort the linkage in progress) cannot be
typed in under MP/M systems, since ^Q is used to detach a process. If you
are running MP/M, then just type control-C instead of ^Q-CR; this will
also work for CP/M systems...the only difference is that when ^Q-CR is
used, then any currently active "submit file" processing is automatically
aborted by CLINK before returning to command level, as a convenience (I
assume that if you abort the linkage, you don't want to continue with your
submit file...). Under MP/M, you'll have to type characters quickly at the
keyboard (after ^C-ing CLINK) to abort any pending submit file activity.
9. A slight bug in CLIB.COM (The C Library manager program) made it hard to
exit CLIB from within a submit file (assuming XSUB is in use). The
problem was that CLIB requires a confirmation character, `y', to be typed
after the `quit' command is given. CLIB was getting the confirmation
character by doing a single direct BDOS console input call, which required
the user to manually type in the letter before any pending submit file
processing could continue. This has been fixed by having CLIB get an
entire line of input (using BDOS call 10) when seeking a confirmation;
now the `y' may be inserted into submit files. Note that the `quit'
command and the `y' confirmation must be placed on separate consecutive
lines in the submit file. If not using a submit file, the only difference
is that now a carriage-return is required after typing the `y'.
Another minor problem with CLIB: function names longer than 8 characters
were not being truncated when entered for operations such as renaming,
resulting in too-long CRL file directory entries. All names are now
properly limited to 8 characters.
10. A problem with file I/O under MP/M Version II has come up: The run-time
package routine "vclose", called by the library function "close" whenever
a file needs to be closed, has been optimizing for files open only for
reading by NOT actually performing a "close" operation through the BDOS.
This worked fine under CP/M, because CP/M didn't care whether or not a
file that has had no changes made to it was ever closed; MP/M II, on the
other hand, DOES seem to want such files to be explicitly closed...so by
running many programs that didn't close their Read-only files, BDS C
programs eventually caused MP/M to not allow any more files to be opened.
This problem has been fixed by adding a conditional assembly symbol,
called "MPM2", to the CCC.ASM source file. If you are running under MP/M
II, you should set the "MPM2" equate to true (1) and reassemble CCC.ASM,
yielding a new C.CCC after loading and renaming (you should only need
ASM.COM for this, although MAC.COM works also). The change does NOT affect
the size of C.CCC, so the libraries do not have to be reassembled as is
usually the case when the run-time package is customized. The change
simply causes a single conditional jump to be turned into three nop's, so
that ALL files are always closed, instead of only the ones open for
writing. My apologies to MP/M users who may have had confusing troubles
because of this bug.
11. A bug was found in the `_scn' library function (affecting `scanf'): when a
lone carriage-return (newline) was typed in response to a "%s" format
conversion, the format conversion was totally ignored. This caused the
target string to remain unchanged from its previous contents, instead of
correctly having a null string (consisting of a single zero byte) assigned
to it.
12. A bug was found in the `_spr' library function (affecting `printf',
`sprintf', and `fprintf'): The default field width value was 1, causing a
null string to be printed as a single space when the standard "%s" format
conversion was used. For example, the statement:
printf("Here is a null string: \"%s\"\n","");
would have produced the output:
Here is a null string: " "
instead of:
Here is a null string: ""
The default field width value has been changed to 0, so null strings will
now print correctly. An explicit field width may always be given in any
format conversion, of course.
13. When the library function "sprintf" (formatted output directly into a
memory buffer) is used, a null byte is appended onto the end of the output
text. I'm not absolutely sure whether or not this is a "desired"
characteristic; at least one user has complained about it, but it turns
out that "sprintf" on the large-scale Unix system I have access to does
the same thing and I can think of applications where the trailing null is
useful. So, the null stays in.
14. In several library functions, as well as at one point in the run-time
package, calls were made to BDOS function number 11 (interrogate console
status) followed by an "ani 1" instruction to test bit 0 of the value
returned by BDOS. I've been told that on some systems, testing bit 0 is
not sufficient since sometimes values other than 0 and 1 (or 0 and 255)
are returned. SO, all such sequences have been changed to do an "ora a"
instead of an "ani 1", so that a return value of exactly 00h is
interpreted as "no character ready" and any other value is interpreted as
"yes, there is a character ready". The library functions that were
modified this way are: `kbhit', `putchar', `srand1', `nrand', `sleep' and
`pause'. The sequence to clear console status in the run-time package
(CCC.ASM), near the label "init:", has likewise been changed (but a "nop"
instruction was added to keep all addresses consistent with earlier
versions of the run-time package.)
15. When customizing the run-time package (CCC.ASM) with the "cpm" symbol
equated to zero, several symbols (named "SETNM" and "SETNM3", at the
routine labeled "PATCHNM") were undefined; this has been fixed by adding
some conditional assembly directives to insure that the labels in question
are not referenced under non-"cpm" implementations, while the total code
size remains constant so that the addresses of later run-time package
utility subroutines stay exactly the same for all implementations.
16. A problem with the "bdos" library function has come up that is rather
tricky, since it is system-dependent: A program that runs correctly under
a normal Digital Research CP/M system might NOT run under MP/M or SDOS (or
who knows how many other systems) if the "bdos" function is used. A
typical symptom of this problem is that upon character output, a character
on the keyboard needs to be hit once in order to make each character of
output appear.
To understand the problem, we must first understand exactly how the CPU
registers are supposed to be set after an operating system BDOS call.
Normal CP/M behavior (which the C library function "bdos" had always
assumed) is for registers A and L to contain the low-order byte of the
return value, and for registers B and H to contain the high order byte of
a return value (which is zero if the return value is only one byte). The
CP/M interface guide explicitly states that "A == L and B == H upon return
in all cases", and I figured that just in case CP/M 1.4 or some other
system didn't put the values in H and L from B and A, I'd have the "bdos"
function copy register A into register L and copy register B into register
H, to make SURE the value is in HL (where the return value must always be
placed by a C library function.)
Not all systems actually FOLLOW this convention. Under MP/M, H and L
always contain the correct value but B does not! So when B is copied into
H, the wrong value results. So, the way to make "bdos" work under both
CP/M 2.2 and MP/M was to discontinue copying B and A into H and L, and
just assume the value will always be correctly left in HL by the system.
This was done for v1.45, so at least CP/M and MP/M are taken care of,
but...
Under SDOS (and perhaps other systems), register A is sometimes the ONLY
register to contain a meaningful return value. For example, upon return
from a function 11 call (interrogate console status), the B, H and L
registers were all found to contain garbage. So if no copying is done in
this case, the return value never gets from A to L and the result is
wrong; but if B is copied into H along with A getting copied into L, the
result is still wrong because B contains garbage. Evidently the only way
to get function 11 to work right under SDOS is to have the "bdos" function
copy register A into L and ZERO OUT the H register before returning...but
then many other system calls which return values in H wouldn't work
anymore. And that is the problem: You can please SOME systems ALL the
time, but not ALL systems all the time with only one standard "bdos"
function!
The way I left "bdos" for version 1.45 was so that it works with CP/M and
MP/M (i.e., no register copying is done at all...HL is assumed to contain
the correct value). You might want to make a note in the User's Guide
library section (page 30) to the effect that A and B are now ignored.
This, of course, won't work in all cases under SDOS and perhaps other
systems...in those cases, you need to either use the "call" and "calla"
functions to perform the BDOS call, or create your own assembly-coded
version(s) of the "bdos" function (with MAC.COM, CMAC.LIB and BDS.LIB) to
perform the correct register manipulation sequences for your system. Note
that it may take more than one such function to cover all possible return
value register configurations.
17. The "creat" library function had been creating new files and opening them
for writing ONLY; this caused some confusion, so `creat' has been modified
to open files for both reading AND writing following creation. PLEASE
MAKE A NOTE OF THIS UNDER THE `CREAT' ENTRY IN THE STANDARD LIBRARY
SECTION OF THE BDS C USER'S GUIDE.
18. The "execv" function has been changed to return ERROR (-1) on error,
instead of forcing an error message ("Broken pipe") to be printed to the
standard error device. The reason I originally had it printing "Broken
Pipe" was because I was too lazy to figure out how to fix the stack after
passing all the arguments; following some justified bitching from Scott
Layson I went in there and fixed it so it does something reasonable.
PLEASE MAKE A NOTE OF THIS UNDER THE `EXECV' ENTRY IN THE STANDARD LIBRARY
SECTION OF THE BDS C USER'S GUIDE.
19. The DIO (directed I/O and pipes) package contained an obscure bug: if a
pipe operation was aborted before completion, leaving a "TEMPIN.$$$" file
in the directory, then the next pipe operation performed had gotten its
own output mixed up with the output of the aborted pipe....the old output
was used as input to the new next command, and the new output was lost.
The new DIO.C has been fixed. (Note: DIO.C has also been slightly changed
to properly interact with the new version of the "execv" library
function.)
20. Another change has been made to the DIO package: the "getchar" function,
when used without input redirection to read characters directly from the
console, had not allowed for line editing in previous versions. I.e., each
character was obtained by a direct BDOS call and none of the special line
editing characters (delete, ^R, ^U, etc.) were recognized. For version
1.45, an optional line buffer mechanism has been added to the DIO package
so lines of console input can be fetched at one time by using the "read
console buffer" BDOS call and all editing characters now function as
expected. Operation of the package using buffered console input is still
the same as before, except for one thing: to enter an end-of-file
character (control-Z), it is now necessary to also type a carriage-return
after the control-Z.
To enable console input buffering when using the DIO library, it is
necessary to un-comment a line in the DIO.H file and re-compile DIO.C. See
the comments in DIO.C for more information.
21. The special case handler for the code generator has been improved to more
efficiently handle relational binary operations where exactly one of the
operands is a constant. The operators affected are: "<", ">", "<=",
">=","==" and "!=", for both signed and unsigned data types. The
improvement is mainly in the speed of execution of such comparisons;
statements such as:
if (i < 1234) ...
execute much faster. This results in speedier execution of programs such
as the Seive of Eratosthenes benchmark in the September '81 issue of BYTE:
the current version of BDS C, using the -e and -o compiler options with
variables made external, does it in 15.2 seconds (see SIEVE.C on the
distribution disk.)
Also, multiplication by a constant that is a low power of 2 (2,4,8,16) is
now done by DAD H sequences instead of calls to the run-time package
multiply routine [so that expressions such as (i * 8) and (i << 3) each
compile to the same code].
22. Two new functions have been added to the standard library:
int setjmp(buffer)
char buffer[JBUFSIZE];
longjmp(buffer,val)
char buffer[JBUFSIZE];
When "setjump" is called, the current processor state is saved in the
JBUFSIZE-byte buffer area whose address is passed as the argument
("JBUFSIZE" is defined in BDSCIO.H), and a value of zero is returned.
Whenever a subsequent "longjump" call is performed (from ANYWHERE in the
current function or any lower-level function) with the same buffer
argument, the CPU state is restored to that which it was during the
"setjmp" call, and the program behaves as if control were just returning
from the "setjmp" function, except that the return value this time is
"val" as passed to "longjmp". A typical use of setjmp/longjmp is to exit
up through several levels of function nesting without having to return
through EACH level in sequence, to make sure that a particular exit
routine (e.g., the directed I/O "dioflush" function) is always performed.
It is a nifty facility that should have been available long ago. THESE
FUNCTIONS ARE NOT DOCUMENTED IN THE BDS C USER'S GUIDE; PLEASE MAKE A
NOTE OF THEM IN THE STANDARD LIBRARY SECTION OF THE GUIDE.
23. A new linker for BDS C called "L2" (a substitute for CLINK.COM) is now
available from the BDS C User's Group. L2, written by Scott Layson (of
Mark of the Unicorn) in BDS C, has several interesting features:
1. L2 can link programs that are up to about 8K larger than CLINK:
if there isn't enough room in memory to hold the entire program
while building an image in memory, L2 performs a disk-buffering
second pass. This means that the resulting COM files can be as
large as the entire available TPA on the target machine.
2. The number of functions per program is no longer limited to 255.
3. While CLINK uses jump tables at the beginning of functions to
resolve references to other functions, L2 totally eliminates the
jump tables and instead generates direct external calls. This
shortens programs by anywhere from 3% to 10%, and also speeds
them up a little.
4. Since L2 is written in C, you can customize it yourself.
The L2 package comes with source code, a special overlay generator program
and documentation. It is available to BDSCUG members for the nominal cost
of media and shipping (currently $8). See the next note for information on
joining the BDSCUG.
24. The BDS C User's Group membership forms should now be included with the
BDS C package...this makes life easier for everyone, since it is no longer
necessary to write to the Group first just to ask for forms before being
able to order library disks. BDS C User's Group members receive the Group
newsletter approximately 6 times per year, and are entitled to compiler
updates and library disks for low prices (typically $8 per disk).