Dear CUJ:While running the program floath.C on various machines which perform arithmetic on other than IEEE style, I have found a few improvements to be made. The most serious problem occurs in the first loop, labeled in the comment "find smallest power of 2 . . "where the relational >= should be changed to ==. The expression to the left of == evaluates as 1 until the last time through the loop, when it becomes 0 on most machines, including those which have IEEE style rounding. With DEC style rounding, the expression rounds up to 2 at the end of the loop. If the loop is continued, with either rounding behavior, the expression evaluates to 0 until an overflow occurs. The loop as published ran one time too often on DEC-like machines, causing the erroneous report of a radix of 4. The change will enable the loop to work also with interval arithmetic rounding modes.
The expression for division rounding is not reliable on a machine where subtraction is not properly guarded. As far as I know, there are no such machines remaining on the market. The problem can be cured by setting
v = l - z;and replacing l-z-z by v-z, 1-z by v, and -1+z by -v. One of the problems with 68881 machines is to avoid using so many registers that the compiler decides to store a register to memory, resulting in a mixture of precisions and causing some of these tests to fail.Ecosoft's 8-bit software floating point subtraction arbitrarily sets the result to 0 when evaluating expression such as
1 - (1 - DBL_EPSILON*.5)even though the evaluation is performed in the correct order. Correcting this enables the division rounding test to work as published and passes the subgrd test. One of the four tests for addition rounding still fails, since numbers between 1 - DBL_EPSILON*65/256 and 1 - DBL_EPSILON/4 round up to 1 when they should round down to 1 when they should round down to 1 - DBL_ EPSILON/2. This discrepancy, which was shared by early Apollo models, is of no practical consequence, so one might conclude that this rounding test is too severe. The double rounding of double arithmetic on 68881 and 8087 processors is not much more of a problem, and I have tried to avoid it by testing long double rather than double arithmetic.I apologize for inconvenience which may have been caused by the lack of claimed generality in the code, and appreciate any information which may be turned up by running it on other systems, even museum pieces.
Sincerely yours,
Tim Prince
39 Harbor Hill Rd.
Grosse Pte Farms, MI 48236Dear Mr. Ward,
I would like to congratulate Mr. Frost on his excellent article describing the use of files as semaphores ("Using Files as Semaphores", CUJ, April 1990). This is a topic which has long been neglected and I was quite pleased to see your magazine's coverage of the topic. Having implemented a mechanism very similar to the one described by Mr. Frost, I feel a few points require rebuttal.
When the existence of a file is used for resource locking, there are two primary problems, the first revolves around the performance of constantly creating and deleting files. Although operating system performance vis-a-vis the file system is being enhanced on many platforms, it is still one of the slower parts of the environment. Thus, repeated file creation and deletion can result in unacceptable performance degradation. Secondly, while operating systems such as UNIX will automatically remove a semaphore file, other systems (DOS for example) will not do so. Thus, on a system without autodeletion of semaphore files, if your program terminates abnormally for any reason, any locked resources may remain inaccessible to other processes.
When I began designing a semaphore mechanism for my employer, the following requirements were outlined: 1) access to a fixed number of shareable resources were to be managed independently by the mechanism (a total of 19 resources eventually), 2) multiple, simultaneous "read" operations were to be permitted on any resource, 3) a single "append" operation was to be permitted to occur on a resource while "reads" were occurring, 4) a single "write" operation could commence only after all active "append" and "read" operations were completed for a resource. In this context, a "write" operation entailed overwriting data which already existed in the resource. Finally, the software being developed was to be ported from the original Xenix system, to UNIX, DOS (3.1 +), VAX/VMS and the Macintosh.
It was obvious early in the design state that a file-based resource sharing mechanism would be maximally portable since DOS and the Mac do not offer shared memory or in-memory semaphores as Xenix and UNIX do. As outlined previously, creating and deleting semaphore files was not an acceptable solution for performance reasons. The following scheme was eventually settled upon and is now in use on three platforms.
A single file is used and contains 3 bytes for each of the resources (3*19=57 bytes). Each byte has a special purpose for the resource. Byte 1 is the "write" semaphore, byte 2 is the "read" semaphore and byte 3 is the "append" semaphore. In order to gain access to a resource, a process locks these bytes. Using file locks as the following benefit: abnormal program terminations (power failure, control-c, kill signal,...) do not block further access to the resource because the operating system guarantees that all locks held by the process are removed when the file is closed (i.e. at process termination).
In order to access the "semaphore" set contained in the file, a process merely opens the file. This is generally done as part of the program startup with the file being closed at termination. Once access is gained to the file, the following steps are required in order to gain access to a particular resource.
READ ACCESS
1) lock the resource's "write" byte for exclusive access2) lock the resource's "read" byte for shared access (if the op.sys. permits shared locks otherwise, use an exclusive lock)
3) unlock the resource's "write" byte
4) read the data from the resource
5) unlock the resource's "read" byte
APPEND ACCESS
1) lock the resource's "append" byte for exclusive access2) lock the resource's "write" byte for exclusive access
3) unlock the resource's "write" byte
4) extend the resource by appending new data to the end
5) unlock the resource's "append" byte
WRITE ACCESS
1) lock the resource's "append" byte for exclusive access2) lock the resource's "write" byte for exclusive access
3) lock the resource's "read" byte for exclusive access
4) write a non-zero value to the resource's "write" byte
5) write data to the resource
6) write a zero value to the resource's "write" byte
7) unlock the resource's "read" byte
8) unlock the resource's "write" byte
9) unlock the resource's "append" byte
Whenever the "write" byte is locked, a test is made whether a previous transaction has failed before completion. If failure has occurred, the resource in question may be corrupted and a "rollback" of the transaction is executed. A failed transaction is indicated by the value stored in the "write" byte being non-zero. This can only occur if step 4 was executed without the complementary step 6 occuring. This mechanism is quite similar to the "readers and writers" mechanism Mr. Frost describes. However, it is important to remember that the count variable used to track the number of concurrent reads MUST be accessible to every user of the resource. The operating system's file locking mechanism is used for this purpose.
Russell Cook
Software Engineer
ZyLAB Corpoation
3105-T North Wilke
Arlington Heights, IL 60004I think it's great to get this kind of exchange between programmers who have implemented separate solutions to a similar problem. Thanks for contributing. rlw
Dear Editor:
First let me say thank you for providing an excellent magazine. It's the only one that I make time to read cover to cover. I've even gone back and re-read articles several times to squeeze all the good parts out.
I would like to recommend to anyone who is programming computers who is not using UNIX, should try it at least once. Talk about heaven. I thought C was wonderful coming from a background of BASIC and assembly. UNIX is to MS-DOS as C is to BASIC.
Do you have any suggestions for good basic UNIX books that don't get stuck in low gear? I'm having trouble finding basic information about UNIX. It appears as though I find something new every day, and really could have used that information yesterday.
In Sydney Weinstein's article "Games and Tongues" (vol. 8, no. 2), he mentioned a game called Conquer. He also said it is available from archive sites for comp.sources.games, including uunet. I would like to know how to get this or other UNIX programs from somewhere, either disk or modem. If it is through the modem, could you give some hints or instructions on how to do this? I am familiar with downloading programs using MS-DOS type environments.
Thank you for all the support
Kenneth J. Suda
P.O. Box 507
Canton, GA 30114UNIX software is usually exchanged via uucp facilities i.e. you must be "attached" to USENET. You can find fundamental information about USENET in UNIX Communications by The Waite Group. UNIX System Administration by David Fiedler and Bruce Hunter includes quite a bit of very useful information about how to get attached to USENET and how to configure your system.
Some books that don't get "stuck":
Advanced Programmer's Guide to UNIX System V by Thomas, Rogers and Yates. Tricks of the UNIX Masters by Sage. UNIX for Super-Users by Foxley. The UNIX System V Environment by Bourne. And just for fun, Writing A UNIX Device Driver by Egan and Teixeira. rlw
The following discrepancies have been noted in the source code for cstr. c which appeared in The C Users Journal, February 1989, page 28-29:
1. The header file blstr. h was not included with the code.
2. The macro error() was not defined.
3. The error message when the output file can not be opened stated that "Can't open %s for input \n". "output" should be substituted for "input".
4. String functions are included in the header file <string.h>. This file was not included in the source code.
5. The string function strbreak does not appear to be a standard function. The string function strpbrk which I believe serves the same purpose is a standard function and is contained in Turbo C, Microsoft C, Lattice C at least.
6. The arguments of strcmp are character pointers. The source code for function makeout contains *in, which contains the value of the character pointed to by in.
7. The accompanying documentation for cstr.c does not point out how cstruse.c is to be obtained. In usage (), I commented out the two lines of code dealing with cstruse[], and then compiled, linked and ran the program with the text file cstruse.str identified on the command line. Once cstruse[] was created by cstr.exe and contained in cstruse.c, I uncommented the cstruse[] code lines in usage (), appended cstruse.c to cstr.c, recompiled, linked and then successfully ran the program.
Please find enclosed a copy of the revised program for cstr.c (see Listing 1) .
I found the article "Scaffolding for C and C+ +", by Burk and Custer very interesting and potentially very beneficial. I did find several discrepancies in the source code for cstr.c. (I have not investigated the other programs as of this date.)
Very sincerely yours,
R. Craig Olson
6306 Huntover Lane
Rockville, MD 20852To the Editor:
In the letters section of your March 1990 (v8n3) issue Bob Barrett writes:
[....] On most (if not all) UNIX systems that use 'termcap', the database can only be modified by the system administrator (or super user) and rightly so. If you, yourself, are not the super user, experimental (trial and error) modifications to terminal descriptions are impractical to say the least. With 'terminfo', the user is free to experiment with a terminal description that only he or she will use (at least until it's fully tested)
I disagree. On most BSB based UNIX systems that I have been on, it is just as easy to experiment with TERMCAP entries:
Normally, the following sequence (possibly in a .profile) can be used to set up the TERMCAP environment variable:
TERM=foo eval 'tset -sQ $TERM'This would look up terminal type foo in /etc/TERMCAP and put the possibly expanded (tc=...) termcap entry in the TERMCAP environment variable (tset - sQ will return comands of the form:
export TERM TERMCAP; TERM=foo; TERMCAP = '--TERMCAP entry--')Which you would then eval to set them in your current shell.If instead you had your own termcap entry for terminal type foo, say in $HOME/foo.TERMCAP, you can do the following:
export TERMCAP TERMCAP=$HOME/foo.TERMCAP eval 'tset -sQ foo'tset(1) calls tgetent (3X) to get the terminal capabilities.From the man page for tgetent (3X):
tgetent (bp, name) char *bp, *name;[. . .] tgetent begins searching for a termcap entry for name by looking in the environment for a TERMCAP variable; if one does not exist, tgetent searches for name in the /etc/termcap file. If TERMCAP does exist, tgetent interprets its value as follows: if the first character is a /, the string is interpreted as the pathname of an alternate file of termcap entries; this file is read instead of /etc/termcap. If the first character is not a /, the string is interpreted as a termcap entry. If name matches one of the names in the first field, the string is stored in bp; otherwise, 0 is returned. If the TERMCAP value refers to another terminal with the capability tc, tgetent searches /etc/TERMCAP file; 0 if the terminal name given does not have an entry; and 1 if all goes well.In other words, it is even easier to experiment with termcap than it is to use terminfo, which apparently requires compilation with tic(1M) according to Mr. Barrett.
Sincerely,
Fuat Baran
Columbia University
712 Watson Labs
612 W 115th St.
New York, NY 10025
fuat@columbia.edu. . . . rutgers!columbia!fuat
Of course you are correct. What you describe is the standard mechanism for testing TERMCAP entries (described in several sources). Thanks for the extra information.rlw
Dear Editor:
In the May 1990 issue of The C Users Journal, Mr. Murphy asked why his BASIC files have different float and double values from what C requires. Since I had to deal with this problem, I thought I might be able to help.
The original Microsoft BASIC and Pascal (the versions IBM distributed) used a floating point format refered to by Microsoft as MSBIN. This format has the exponent in the ms 8 bits, followed by a sign bit, followed by a 23-bit mantissa. Note that this is not 8x87 format, which is IEEE-compatible. Thus, these languages could not take advantage of a numeric coprocessor without conversion to/from the MSBIN format.
When C was implemented, they decided to use IEEE format. If you have a copy of the Microsoft C compiler, there are 4 functions in the standard library: dieeetomsbin, dmsbintoieee, fieeetomsbin and fmsbintoieee. These allow you to convert to and from the MSBIN format.
If you don't have a copy of the Microsoft C compiler, a short routine can be written to convert the values, such as the function read_MSBIN_float in Listing 2.
Note that this routine has not been tested at all. In fact, I may have the array indices the wrong way around. The best way to test the results is to run some known values through the routine and see if you get the results you expect. The casts in the mantissa generation to long are required to avoid integer arithmetic overflow. It is only really required for the conversion of the ms 7 bits, but I kept the same format for consistency.
The extension to double should be trivial. Just increase the size of the array to 8, add 4 more terms to the mantissa generation code and change the number 23 in the normalization to 55. You also will have to find out how bit the exponent is. I think it is 11 bits, but I'm not really sure.
The above routine is not very efficient, but should be easy to debug. It will also work on any architecture, not just architectures that use IEEE format floating point. If you're interested in efficiency, a direct binary conversion can be coded. If you want to do this, you will need to look up the 8x87 format and roll your own.
There are some range questions in the conversions, but if your numbers are not already pushing the precision of double or float, you shouldn't have too much problem. Note that the MSC library routines will return you an error if you overflow/underflow the result.
If you have any questions or comments, please contact me. My phone number (408)988-3818. My fax number is (408)727-9891.
Jim Schimandle
Primary Syncretics
473 Sapena Court, Unit #6
Santa Clara, CA 95054Thanks for the information. I nominate these names for Ken Pugh's Dumb Name contest. rlw
Dear Mr. Ward:
All in all, I quite like the new format of The C Users Journal. But those titles do you think we could tone them down just a tad?
When I first saw "WHA GANG AGLEY" in 96 point type, I thought not of Bobbie Burns, but of some bizarre ac- cident at the printers.
Except for this minor indictment, I think you have an excellent magazine. I scan many, but I READ few. The C Users Journal is always worth reading.
Patrick Conroy
Euless, TXWe could tone them down, but typesetters and graphic artists need to have fun too. I figure if they have their fun in big type, they can't get too far out of line without my noticing.rlw
Dear Mr. Ward,
I have subscribed to your journal for several years and have found it very informative and useful. Which is why I was shocked to read "Executable Strings" by James A. Kuzdrall (May 1990).
In order to save ourselves from "learning the details of (our) C Compiler's assembler and linker" we should have "a knowledge of machine language"? Why is this method better than the common industry practice of writing a separate assembly routine? Not only do I fail to see any advantage to this technique, I see many disadvantages. Not the least of which Mr. Kuzdrall alludes to himself when he writes: "For those who wish to believe C is inscrutable, this function call may serve as the final proof."
It is possible to write readable C code! But, the programmer must understand and use the rules of good programming practice. Please tell me that this article was really an entry in the International Obfuscated C Code Contest that got misplaced by the layout artist.
Sincerely,
William J. McMahon
106 Oceanside Drive
Scituate, MA 02066I'm the last to suggest the "executable strings" are a better method for anything. I just thought the story showed an interesting perversion of power. Didn't you notice the skull and crossbones worked into the art on that page? rlw
Having resolved our change of address problem, I enclose my subscription renewal. Perhaps I should add that I had nearly decided to allow the subscription to lapse due to dissatisfaction with recent issues.
In explanation, I have noted that increasing space is being given in the Journal to reviews of commercially available packages. My interest lies in producing my own programs and I most often have little interest in and/or cannot afford such products particularly when exchange is taken into account. It was Leor Zolman's article (page 69) which swung the tide in your favour for a further 12 months. While appreciating that your editorial policy may be in favour of professional programmers, please also keep in mind the "roll your own" C user.
Yours faithfully,
D. J. Omond
27 Kildare Avenue
Athelstone. SA 5076
AustraliaI won't promise that we won't devote space to commercial products that look useful to developers, but I will promise that we'll always include material like Leor's series. (By the way the conclusion is in this issue.) Thanks for sticking with us. Let us know how we're doing. rlw
Dear Mr. Ward,
You guys are gettin' to me...
Last month (April 1990) on the cover it said "Obfuscated C Code Contest," much as one might advertise "Fortified with 10 essential vitamins." But it was not to be; we had to wait another month for "The REAL Obfuscated Code Contest".
I could handle that. But only because I knew the bad pun contest was on the way. Alas, it was not to be.
And what's with the duplicate Publisher's Forum? Please tell us it was all a mistake, that the old pages got mixed in at the printers.
Your readers are getting ANSI.
Sincerely,
Steven G. Isaacson
22815 Lakeview Drive #G211
Mountlake Terrace, WA 98043It was all a mistake. But, the pages got mixed up here, not at the printers. See last month's letters for the ugly details. The puns were in last month's publisher's forum. rlw