home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
c
/
cnews004.arc
/
CNEWS004.NWS
next >
Wrap
Text File
|
1988-02-21
|
60KB
|
1,484 lines
Volume 1, Number 4 21 February 1988
+---------------------------------------------------------------+
| |
| - C News - |
| |
| International |
| C Programming & Compiler Review |
| Newsletter |
| |
+---------------------------------------------------------------+
US Office:
Editor at large Barry Lynch
Assistant Editor Ami Dworkin
Technical Editor Marshall Presnell
Australian Office:
Editor David Nugent
C News is published bi-weekly by the C BBS as its official
newsletter. You are encouraged to submit articles for publication
in C News. Articles should be related to C programming and can be
Tutorials, reviews or articles of interest to the C programming
community. All Operating systems are fairly represented and this
newsletter shows no favoritism to any one in particular. Instruct-
ions on how to submit articles for publication is included on the
last page.
C News is the property of the C BBS and is Copyright 1988 by the
the C BBS. All rights are reserved and distribution is limited to
electronic distribution and personal printed copies. C News cannot
be resold at any profit, by any organization. All material enclosed
within the newsletter is the opinions of the writers and not the
C BBS or it's Sysop.
DISTRIBUTION POINTS:
EASTERN US - C BBS 109/713 (703)998-8377
CANADA - Another BBS
AUSTRALIA - Alpha Centuri BBS
EUROPE - 150/1 - Sysop: Henk Wevers
New distribution points are always welcome, if you are interested
send me a netmail message at the above address.
C News 1-04 21 Feb 1988
=================================================================
TABLE OF CONTENTS
=================================================================
1. EDITORIAL
The Heap: messages from the editor.................... 1
New Column, User requests
2. PATCHES/MITE REPORTS
MSC Version 5.0 Bug Listings ............................. 2
3. SHORT SNIPS
Magazine Review's
by Barry Lynch ...................................... 6
4. BOOK REVIEWS
MS-DOS Developer's Guide ................................ 7
by Barry Lynch
5. SOFTWARE REVIEWS
Public Domain: .......................................... 8
SETPRGMS.ARC, SHIFT_C.ARC, SYSACT11.ARC, XENIXARC.ARC,
CDATE.ARC, C_DATES.ARC, C-SUBR.ARC, JCL-SRC.ARC, and
NDMAKE41.ARC
by David Nugent
6. FEATURE ARTICLE
Filename Wildcard Expansion in Microsoft C ............... 15
7. /Usr/Bin
by Marshall Presnell ................................. 26
8. NOTES
Article Submission Standards ............................. 28
Address's ............................................... 29
USER Response Form ....................................... 30
9. INDEX ................................................... 31
C News 1-04 Page 1 21 Feb 1988
=================================================================
EDITORIAL
=================================================================
The HEAP: Messages from the Editor.
With this issue of C News we start a new column, and begin
<hopefully> a new tradition. First, Marshall Presnell joins us
with his column the "/usr/bin". Dedicated to technical questions
and answers relating to C programming. Marshall has a BS in
Electrical Engineering and is quite a accomplished programmer in
C and ASM. Marshall's column will be a regular feature, and I
know that he will provide a valuable service to all of us in the
future.
The next feature of C News that I am proud of, and hope becomes
a regular feature. Is an article by Bill Mayne on Expanding
arguments from the command line and some other goodies. Mr. Mayne
has done an excellent job and should be congratulated by all. It
is hoped that articles like his will be forthcoming in future issues
of C News as well.
Last Issue, I included a user response form for users to fill
and send back if they had the chance. Well, quite a few users did
and I thank you for the support. Most of the suggestions dealt
with more beginner oriented tutorials and a technical question
and answer column. Both of these requests have been satisfied
in this issue, and we will attempt to keep up the quality of work
that we have been able to produce for this issue in future issues.
B C'ng U
Barry Lynch
C News 1-04 Page 2 21 Feb 1988
=================================================================
PATCHES/MITE REPORTS
=================================================================
MSC Version 5.0
Be VERY careful when using the MSC5 compiler. The optimizer is
generating a LOT of bad code in places. In some cases you can disable
enough of the optimizer to force it to generate good code, but in
other cases one must simply rewrite code to trick the compiler into
doing the write thing. The problems appear to be with large memory
models. All C code was compiler with "Alfu" memory model.
In the next two messages I will show two code samples that
generated bad code. The samples are simplified extracts that
demonstrate a compiler bug..
This demonstrates a bug in the loop optimizer. The cast to a CHAR *
is what confused the optimizer... The code is large memory model
compiled with "Alfu". The bug is correctable by disabling the loop
optimizer.
#include<stdio.h>
#define GETSEGPTR(xseg,xoff) ((char *) (((long) xseg <<16) | xoff))
#define WHATEVER 20
void
fortran
badcode(buffer,unpointer)
char *buffer;
unsigned *unpointer;
{
char *ptr;
unsigned segval, get_a_segval();
int i;
segval=get_a_segval();
for(i=0; i< WHATEVER ; i++)
{
do_something( GETSEGPTR(segval,0));
segval+=16;
}
}
It does not matter what the called routines do, The compiler does
not generate the code to add 16 (seg size) to the variable SEGVAL..
Below is the asm that the compiler generates....
C News 1-04 Page 3 21 Feb 1988
=================================================================
PATCHES/MITE REPORTS
=================================================================
MSC Version 5.0
*** 000024 be 14 00 mov si,20
*** 000027 81 46 fe 40 01 add WORD PTR [bp-2],320
;segval
$L20000:
;|*** {
; Line 20
;|*** do_something(GETSEGPTR(segval,0));
; Line 21
*** 00002c ff 76 f6 push WORD PTR [bp-10]
*** 00002f ff 76 f4 push WORD PTR [bp-12]
*** 000032 9a 00 call FAR PTR _do_something
*** 000037 83 c4 04 add sp,4
;|*** segval+=16;
;|*** }
; Line 23
*** 00003a 4e dec si
*** 00003b 75 ef jne $L20000
;|*** }
In this above loop, segval is never changes at all... Nice huh?
The code sample below is even more terrifying since the compiler is
not generating badly optimized code so much as it is just generating
BAD code. Below is a sample of a C routine that the compiler will kill
you on. This code was compiled with "Alfu". The only way to correct
the compiler was to disable intrinsics, any other optimizer flag made
no difference.
#include<stdio.h>
void
fortran
badcode(buffer,unpointer)
char *buffer;
unsigned *unpointer;
{
char *ptr, *getaptr();
ptr=getaptr();
C News 1-04 Page 4 21 Feb 1988
=================================================================
PATCHES/MITE REPORTS
=================================================================
MSC Version 5.0
*unpointer = strlen(ptr);
}
The assignment of strlen() to *numpointer will generate bad code.
It does not really matter if numptr is an unsigned int or an int by
the way. Below is the asm that the compiler will generate...
;|***
;|*** *unpointer = strlen(ptr);
; Line 13
*** 000018 c4 5e 06 les bx,DWORD PTR [bp+6] ;unpointer
*** 00001b c4 7e fc les di,DWORD PTR [bp-4] ;ptr
*** 00001e b9 ff mov cx,-1
*** 000021 33 c0 xor ax,ax
*** 000023 f2 repnz
*** 000024 ae scasb
*** 000025 f7 d1 not cx
*** 000027 49 dec cx
*** 000028 26 89 0f mov WORD PTR es:[bx],cx
;|*** }
In the asm above, you will note that it generates an LES twice in a
row. The value loaded into ES by the first LES is clobbered by the
second LES. The last instruction to load CX into ES:[BX] is invalid
since ES does not NECESSARILY point to the correct data segment. If
the segment value of the pointer happens to be equal to SS, the code
will work, but the compiler should not assume this, especially since
the code was generated with "Alfu" - which means among other things,
ES!=DS....
No combination of optimizer switches could get the compiler to
generate the right code for this. The routine had to be modified
to load the strlen() value into an intermediate location, and from
there into the final target.
Under OS/2 bugs like this make themselves know fairly quickly,
A bad segment value is trapped instantly by the kernel. Such Bugs are
are much more difficult to locate under MS-DOS. The above bugs in the
MSC 5.0 compiler can be reproduced in the OS/2 SDK compiler
as well.............
The 5.0 compiler is nice, and some of the new features are very
handy. When the optimizer works, it generates wonderful code, but
C News 1-05 Page 5 21 Feb 1988
=================================================================
PATCHES/MITE REPORTS
=================================================================
MSC Version 5.0
when its bad - its VERY bad. It appears as though MSC5.0 was rushed
to market before it was completely debugged.
Daniel Doman
*** Editors Note: An arc file is included with this newsletter.
C News 1-04 Page 6 21 Feb 1988
================================================================
SHORT SNIPS - MAGAZINE REVIEWS by Barry Lynch
================================================================
Magazine: The C Users Journal
Publisher: R&D Publications
Published: 8 times a year.
Subject Matter: C
Issue: Vol 6 No 2 - February 88.
The C Users Journal is the result of a merger between the C Users
Group Newsletter and The C Journal. This is the first time that
I have had a chance to review - C Users Journal, and here are my
impressions.
The subject covered by the articles included: Revision Control
Systems, An article on Compiler rounding of floating numbers,
Standard (ANSI) C, as well as an article on Null Pointer Errors
in MSC. (I for one, needed this article to answer a few pointing
questions.)
Overall, the magazine covered quite alot of territory for one issue.
At US $3.95 I found it to be a bargain, this compared to the amount
of C issues covered in Computer Language as reviewed in Issue 3 of
C News. I hope that the magazine's staff will continue to produce
the same amount of coverage that they did in this issue. I have a
real problem with magazines that get carried away with the gloss, and
advertising, and forget the reason for being to begin with.
The C Users Journal is recommended as a supplement to every C
programmer's monthly reading regime, as long as it produces quality
issues such as this one.
C News 1-04 Page 7 21 Feb 1988
================================================================
BOOK REVIEWS
================================================================
________________________________________________________________
MS DOS Developer's Guide
Author : John Angermeyer & Kevin Jaeger
Publisher : Howard W. Sams & Company. Indianapolis. 1987.
Cost : $24.95 (US$)
This book is aimed at serious software developer's on the IBM PC
and related clones. Topics covered include: 1) Program and Memory
Management in MS-DOS, 2) Real-Time Programming Under MS-DOS, 3)
Installable Device Drivers, 4) LANS and MS-DOS and much more.
As with all books that I have purchased from this publisher, I was
not disappointed. The authors have taken the time to write a clear and
concise book on very technical subject matter. Prior exposure to the
architecture of the IBM PC is recommended, as the authors assume a
basic working knowledge of how a PC operates. In regards to memory
management, and CPU management. Most of the code listed in the book is
in Assembler, so a little prior knowledge there would be of benefit.
Overall, I enjoyed the book, and consider one of my better buys in
the PC software/reference book arena.
Barry Lynch - Alexandria, VA
C News 1-04 Page 8 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
*** Editor's Note: This section is brought to us by the users
of the Alpha Centuri BBS in Melbourne, Australia.
<< Thanks, David >>
________________________________________________________________
Filename: SETPRGMS.ARC
Finding this file was quite a surprise; and its contents are
both instructive and useful - even to the veteran programmer.
These programs are specific to MS-DOS. SET PRGMS refer to
programs which manipulate the environment from within a program.
No - not the program's environment, but THE environment: the one
maintained by COMMAND.COM.
The theory on how to do this has been known for some time. But
this is the first set of programs I have found which actually
make use of the technique.
When a program is loaded, any references to the environment
usually refer to the environment of THAT program, which is
initially only a copy of it's parent's (usually). These programs
implement the technique of chaining back to the master
environment and altering that, so that when you drop back to DOS
the environment remains changed.
The usefulness of this ability is best shown by the examples
presented in the ARC. These include: the ability to assign to an
environment variable the path name of the current directory, read
a line from the console into a variable, and sets for current
date and time variables. Great stuff for fancy batches, and an
excellent teacher of the technique.
The file also comes with a system logging utility implemented in
quite a practical fashion via batch files.
Source included: Complete ASM source, including .COM executables
and program documentation. Very well commented and quite robust
code.
Assembler: Very little use is made of assembler macros, and no
special include files are assumed. From what I can tell,
anything from way back v1.0 of IBM's ASM.EXE would do. I dare
say that Eric Issacson's blindingly fast PD A86 assembler
(available on this board) would make short work of it.
C News 1-04 Page 9 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
________________________________________________________________
Filename: SHIFT_C.ARC
Shift is a handy routine to add to your super-quick screen I/O
library. It is an ASM routine which may be used to shift a line
of text on the video screen one column left or right.
Source included: Yes
Assembler: Originally compiled under MASM 5.0, but I can't find
too much in it that earlier versions would dislike. Assembles ok
under MASM 4.0 (for example).
Compiler: This is a C subroutine. Calling conventions are for
MSC or Turbo C (preceding underline), but you can call _shift()
from other compilers.
Notes: This routine is VERY hardware specific, and only applies
to a machine which is 100% IBM compatible. On the other hand, it
would be easily adapted to other environments, if you knew the
various machine specific addresses.
_________________________________________________________________
Filename: SYSACT11.ARC
This little nugget contains a utility to log "execute" DOS calls
to a log file, with start and execution timings and the number of
read/write and other DOS calls made by the program.
If you are familiar with Xenix or Unix, this should ring a bell.
Something like acctcom available there. This program takes the
form of a mighty small .ASM TSR used for intercepting DOS calls
loaded on boot up, together with two programs and a batch file
used to produce reports and summaries.
Its these last two programs that make the .ARC so interesting.
The reports can summarize activity in a number of interesting
ways, and can merge the file to produce excellent summaries.
After all, who out there who uses a hard drive (floppies not
supported) can tell you which program is used the most often,
makes the most disk & device I/O calls or takes the longest to
execute. A very interesting statistic which can change your
habits remarkably for the better.
This is not a simple activity logger. Its a work analysis tool
useful to professionals and serious hobbyists. It comes with
C News 1-04 Page 10 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
full source (.ASM and .PAS), so it can teach a good deal about
intercepting the DOS interrupt.
Source included: Yes
Language: Turbo Pascal, Assembler.
Compiler/Assembler: Not specifically stated, but probably
requires TP 3.0 or above. Version of MASM or other assembler is
not critical.
_________________________________________________________________
Filename: XENIXARC.ARC
This is SEA's original ARC utility ported to SCO Xenix. Its the
first time I've seen a successful port, and I've tried a few!
Other Unix ports have memory/model problems and slight
incompatibilities when compiled under Xenix.
The beauty of this program is that it is 100% PC compatible.
It can read PC ARCs and the ARCs it creates can be ported to DOS.
It does not, of coarse, do the newline/carriage return
translation! One minor differences is that file names ARE case
sensitive, like Xenix. Causes no problems when swapping with DOS
though.
Wildcards "*" and "?" are fully supported in the same way as
under DOS. However, because most Xenix/Unix shells expand
wildcards before a program sees them, you must quote them (using
quotes) to prevent this when EXTRACTING files. When updating or
adding files though, you can have your choice as to who expands
the wildcards.
Source Included: Yes - no executables.
Language: C, SCO/IBM Implementation (MicroSoft Xenix compiler)
Version: Minimum compiler version is the 2.1 (IBM 2.0)
C News 1-04 Page 11 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
Filename: CDATE.ARC
This is a handy utility for batch files which is capable of
testing the current system time and date, returning a "truth" to
the caller via DOS errorlevel. The flexibility of this program
and the parsing technique used for examining the command line are
instructive.
As a utility, CDATE can be quite invaluable; especially those of
use running bulletin boards. The current day of the month, day
of the week, month of the year or any combination of these can be
tested and acted upon. The program is quite "intelligent" in
examining the command line and understands a range of common
abbreviations.
Source: Yes.
Language: C
Compiler: Turbo C, but a trivial port to other MS-DOS compilers.
__________________________________________________________________
Filename: C_DATES.ARC
At last a group of routines which handles dates! This ARC
contains a number of routines used for converting dates to and
from "long", allowing dates to be manipulated and operated on
mathematically.
These routines view a date as one day in a continuing series of
days, converting day, month a year to long integer and back.
This is invaluable for business applications.
Both 'long' (4 digit year) and 'short' date format are implicitly
supported.
Source: Yes.
Language: C
Compiler: Quite portable, K & R standard.
Notes: Two demonstration programs also provided, including
source.
C News 1-04 Page 12 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
Filename: C-SUBR.ARC
This file contains a variety of handy routines for a beginner or
intermediate C programmer. It includes all the common practice
algorithms and is well coded to provide both a high degree of
readability (and understandability) and efficiency. These are a
good learning tool.
For the more experienced programmers, it may also save time in
providing a library of reliable, short routines which are easily
incorporated into a project, even at the object (link) level.
Many common requirements of C programmers are met, from
displaying error messages, parsing a line for information, de- and
en-tabbing text, right/left text justification to block CRC checking
and copying files.
Source: Yes
Language: C
Compiler: Written for Turbo C, but easily ported. Some routines
include inline assembler not supported by some compilers. (If you
are using MSC, see the entry in this area for CASM.ARC).
_____________________________________________________________________
Filename: JCL-SRC.ARC
This program represents the source code for an extended batch
command language provided for operation with MS-DOS called "JCL",
written (and uploaded) by Ian Rutherford.
JCL in its executable form has been available in the public
domain for some time. It allows special "JCL" files to be
executed providing a great deal more flexibility and control for
batch files, including support for variables and full screen
control.
The program is very instructive in a number of areas, especially to
intermediate C programmers: those familiar with the language
looking
to do something useful with it.
Source: Yes - no executables.
Language: C
Compiler: Turbo C, but can be ported to most MS-DOS compilers. Notes:
Executables may be found in the DOS utilities file area, called
C News 1-04 Page 13 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
JCL.ARC. Another version may be found in the 286/386 area,
compiled to use the extended instruction set of those
microprocessors.
________________________________________________________________
Filename: NDMAKE41.ARC
For any programming project, the classic, Unix-style 'make'
utility is an absolute *must*. This little program I have been
looking for some time. Ever since I first hacked into the source
code for Binkley Term to see all of Opus' file transfer secrets. Bob
Hartman, the author of Binkley (and many other Fido/Opus utilities,
AND part of the Opus development team, and one of the developers
of the FOSSIL communications drivers, and ... [need I say more?])
recommended it in his program documentation, due to some of its
unique abilities.
I was eager to unARC it once I had it on the system. I have used a
number of MAKE utilities; one received with MicroSoft's C
compiler (average to useless), POLYTRON's PMAKE (very powerful,
allows multiple directories for development but has some
incompatible but very powerful extensions) and a number of public
domain implementations. I certainly wasn't disappointed. It had
more facilities than I had bargained for, and all using make syntax
compatible with Unix make.
Before discussing the features of this make, I should mention
what a MAKE program does. MAKEs are used for medium to large
scale program development; particularly in modular programming
languages such as C, Pascal, Fortran and Assembler. It is
historically attached to C (under Unix), but can be easily
adapted to basically any modular programming language. It takes
the place of multiple batch files and compiles, assembles and
links modules only if they are 'out of date'. Complete
applications can be assembled simply by entering the command
'make'. If this has you interested, then download it and read the
docs.
NDMAKE version 4.1 is the most powerful I have ever seen. Its
major feature is the ability to create a LINK and LIB response
file whenever the command line would exceed DOS's 128 byte limit. If
that's not enough, it also has the ability to maintain
multiple versions of the same application from one set of source
files (via environment variables), use environment variables as
macros (an absolute MUST for ANY make, in my books), and have a
single file called MAKE.INI for definition of MAKE's built-in
rules which may exist in your current directory or anywhere in
C News 1-04 Page 14 21 Feb 1988
================================================================
PUBLIC DOMAIN SOFTWARE REVIEWS:
================================================================
your executable search path.
If you're after a MAKE utility that has all the edge, look no
further. It comes in executable form only, but is well worth the
effort of downloading.
Source code: No
Notes: Generic application to all compiler/assembler based modular
programming languages. Especially useful for medium to large
project development. Comes with excellent documentation (50K), and
has excellent background information for first time make users.C News 1-04 Page 15 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
Audience: Beginning to intermediate programmers using Microsoft C.
Some methods are also applicable to other versions of C.
Topics: (1) Use of SETARGV.OBJ to expand command line arguments.
(2) Use of DOS calls (with "intdos()" and "intdosx()") to
expand wildcards from within programs. Covers use of
disk transfer area (DTA) and DOS functions 4E and 4F.
(3) Source code for demonstration programs and C functions
to perform the DOS calls.
(4) Use of recursion to traverse directories.
Filename Wildcard Expansion in Microsoft C
The power of many DOS commands is enhanced by the wildcard expansion
feature, enabling you to specify a group of files by including the
wildcard characters '*' (match anything) and '?' (match any character)
in the filename or extent part of a path. For example, "DIR
C:\INCLUDE\*.H" shows you a list of all C header files in the
directory "C:\INCLUDE'. "ERASE *.BAK" erases all files in the current
directory which have the extension "BAK". "COPY SUB\PROG1.*" copies
all files with a filename of "PROG1" (and any extent, or none) from
the subdirectory "SUB" to the current directory. Including this very
useful feature into your own C programs is easier than you might
think.
This article will first show how to expand wildcards in the command
line by means of an object (.OBJ) file provided by Microsoft C. Then
it will demonstrate a more powerful technique of doing your own
wildcard expansion inside a program, using a few simple DOS calls by
means of the "intdos()" and intdosx()" functions. The latter
technique is portable to any implementation of C under MS/DOS or
PC/DOS providing functions for issuing DOS calls. Each technique will
be demonstrated by simple programs which are also useful utilities.
Using SETARGV.OBJ to Expand Command Line Wildcards
Normally, the startup library routines linked with a C program parse
the command line arguments into words and pass the result to the
"main()" function as the arguments "argc" and "argv[]", where "argc"
is the number of words and "argv[]" is an array of argc char pointers
to '\0' terminated strings containing one argument each. A useful
alternative is to substitute startup code which will not only parse
the arguments into words, but expand those which represent wildcards
for filenames into a list of matching files. To do this under release
4.0 include the file xSETARGV.OBJ in the link step, where 'x' is the
memory model in use, "SSETARGV" for small, "LSETARGV" for large, etc.
For the program "ARGS.C", shown in figure 1, compiled with the default
small memory model, the command to link is:
C News 1-04 Page 16 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
LINK ARGS+SSETARGV
(Using release 5.0, you no longer need to specify the memory model,
but you must specify the "/NOE" link option to avoid an error message
since "setargv" is a duplicate name. The command to compile and link
would be "CL ARGS.C \BIN\SETARGV.OBJ /link /NOE.)
The resulting ARGS.EXE simply writes its arguments to the standard
output file, one per line, surrounded by double quotation marks. This
enables you to see exactly what is being done with the arguments you
enter by SETARGV. To get rid of the double quotes around each
argument, compile with the option "/DNOQUOTES".
A little experimentation with ARGS will show the following:
(1) Arguments which do not contain wildcard characters are passed as
is to "main()", in the normal way.
(2) Wildcard arguments are expanded into the list of files which match
the pattern, each matching file being appearing as a separate
argument. If no files match a pattern the pattern is passed as is to
"main()".
(3) If a drive and directory is specified along with filename.ext, and
filename.ext contains a wildcard, each of the resulting actual
filenames will include the drive and directory. As with DOS,
wildcards are allowed only in the filename and extent, not in the
directory part.
(4) If null extents are allowed, and any subdirectory names match the
filename part, the names of these subdirectories are also passed to
"main()". The program must use other means to distinguish between
directories and files. The simplest, when you expect a file, is to
try to open it and check the return code.
(5) Any string in the command line surrounded by double quotation
marks is passed to "main()" as is. You can use this to disable
wildcard expansion for a given argument, or to pass strings containing
blanks without splitting them into separate words. If you mean to
pass "*" as an argument, and you don't want it to be replaced by the
names of all the files in the current directory which have no extents,
include the quote marks in the command line.
(6) "main()" cannot distinguish between a list of files actually given
on the command line and a list resulting from matching a wildcard, nor
can it see the original wildcard argument. If it is necessary to do
that, you must look at the unparsed command line arguments stored in
the program segment prefix. Since that area is also used as a disk
transfer area, your program should make a copy of the string before
C News 1-04 Page 17 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
doing anything else.
(7) Wildcards are not only expanded, the list resulting from each
wildcard is sorted. Filenames matching a wildcard are passed to
"main()" in alphabetical order.
Obviously just linking with SETARGV.OBJ does a lot for you, most of it
useful. In fact, the simple ARGS program, written just to test this
option, is a nice file listing utility in own right, displaying a
sorted list of files in one or more directories. For this use, you
probably don't want the double quote marks around each filename, so
try compiling with the "/DNOQUOTES" option. The final .EXE file might
be named something like "SFILES.EXE" to give a better indication of
its function.
Expanding Wildcards With DOS Calls In Programs
As useful as wildcard expansion in command line arguments can be,
there are times when it is necessary to perform the same function
inside a program. This can be easily accomplished using a few DOS
calls, which is much easier than you might think. The source code for
a simple file find utility using this technique is shown in figure 2.
All the required DOS function calls are performed in the functions
"findentr()" and "findnext()" (figure 3) and its subroutines
"get_DTA()" and "set_DTA()" (figure 4).
DOS functions are called by executing interrupt 0x21, with the AH
register containing the number of the function to be performed and
other registers used to pass other arguments. The registers contain
either the arguments for a specific function or the addresses of
blocks of memory to be used by the function. Filenames are
conveniently passed as ASCII strings terminated by '\0', which is
exactly the way strings are stored in C. You need to know about the
registers and understand the segment:offset addressing scheme used by
the PC, but assembly language is generally not required.
In Microsoft C, the functions "intdos()" and "intdosx()" are used.
The header file "DOS.H" defines the union REGS and structure SREGS
used to hold register values passed to and from the software interrupt
handler. The SREGS structure is used with "intdosx()" to pass values
for the segment registers. The REGS union is used for the other
registers. When segment registers are not needed "intdos()" is used.
Main memory addresses must be given by segment and offset. Microsoft
C programs can use the macros FP_SEG and FP_OFF to extract the segment
and offset components of far pointers. Other implementations of C
usually provide similar functions, so it should be easy to port the
routines shown here to other versions of C.
C News 1-04 Page 18 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
Microsoft C also provides a few other functions for executing low
level functions. They are not used by the routines shown here, but
may used in other cases. For DOS functions which take no arguments,
or only arguments in the DX and AL registers, the simpler "bdos()"
function will do. It has the advantage of taking only integer
arguments and returning the result as an integer return value. Many
of the low level keyboard and console functions can use this. On the
other end of the scale, "int86()" and "int86x()" work like "intdos()"
and "intdosx()", except that they accept an interrupt number so any
interrupt can be executed, not just 0x21.
The DOS functions used to expand wildcards in file names are 0x4E
(Find Match File) and 0x4F (Find Next File). The process is started
by calling 0x4E, which finds the first file matching the given name
and initializes a data structure used by 0x4F to find successive
matches. As with many DOS functions, these two indicate failure by
setting the carry flag and placing an error code in the AX register,
both of which are returned to the C program in the REGS union.
The data structure initialized by "findentr()" and used by
"findnext()" is located in an area called the disk transfer area
(DTA). This is not explicitly passed to DOS functions, but is kept
track of by DOS. When a program starts, the DTA occupies the last
half of the program segment prefix, overlaying the unparsed command
line arguments. This means that programs which look at the unparsed
command line arguments should make a copy of this area as soon as they
begin, before the DTA is used for anything else. Programs can get the
current value of the DTA address by executing the DOS function 0x2F
and can change it by function 0x1A. These DOS functions are performed
by "get_DTA()" and "set_DTA()", respectively.
The header file "DOSTYPE.H" (figure 5) gives the format of the DTA
used by "findentr()" and "findnext()", as well as defining the bit
values used for file attributes. In order to find directories,
hidden, and system files you must specify those attributes when
calling "findentr()". Besides the file name and extent (ready to use
as a C string) and attributes, the DTA contains the date and time the
file was last written in a coded binary form and the size of the file
as a long integer. The declarations in "DOSTYPE.H" include the bit
fields in the date and time stamps, even though they are not needed by
the sample programs shown here.
To avoid any conflict in the different uses of the DTA, it is a good
idea for each routine using a DTA to save the current address with
"get_DTA()", set their own using "set_DTA()", and restore the old
address with another call to "set_DTA()" when done. Both "findentr()"
and "findnext()" take the address of a DTA in the caller's local
storage as an argument and call "get_DTA()" and "set_DTA()" to
C News 1-04 Page 19 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
temporarily set the DTA to that address. They return zero to indicate
that a file was found and 18 to indicate no (or no more) files.
"findentr()" returns two to indicate an invalid pathname.
The program FF (figure 2) is a simple file find utility similar to the
Norton Utilities FF.COM. FF searches an entire disk or the subtree
starting with a specified directory for files matching a filename and
extent which may contain wildcards. This is useful when you either
want to find all occurrences of a file which exists in many
directories, or if you forget what directory contains a given file.
The "main()" function simply checks to see that an argument was given
and separates it into a path and filename part. If no path
(directory) was specified, the root directory on the default drive is
used. This initial path and filename is then passed to "trav()". The
most interesting function is "trav()" (for traverse). Traversing a
subtree means to somehow reference or do something at each node. The
specialized function "trav()" first uses "findentr()" and "findnext()"
to find the matching files in the directory specified and then
finds all the subdirectories by the same method, this time specifying
that files with the DIRECTORY attribute, any file name, and no extent
be returned. Unless attributes are specified, only normal files which
are not hidden would be found. It is not possible to exclude regular
files when calling "findentr()", so "trav()" has to check the
DIRECTORY bit in DTA.attr itself. It would have been useful here to
declare bit fields within the attribute byte, but unfortunately bit
fields cannot be defined within a single byte. The next best thing is
to use "#define" to give symbolic names to the values of the bits for
each attribute and then use bitwise and operations to test them.
For each subdirectory, "trav()" calls itself recursively, specifying
the subdirectory found and the same filename and extent from the
original argument. It is because of this recursion that each
invocation of "trav()" must have its own DTA and other local
variables. This is accomplished by simply declaring them with the
default auto storage class within "trav()".
Recursion is often illustrated by value returning numerical functions,
such as factorials, but is also useful for subroutines (or void
functions in C). Actually, the usual numerical examples are not
really very practical. Mathematicians like to work with recursive
definitions of functions not because that is a necessarily a practical
method of computation, but because the recursive definitions are
sometimes simpler and easier to use in inductive proofs.
The example of recursion provided by "trav()" is a more practical one.
Since directories may contain other directories, the natural
definition is recursive, and the traversal implemented by "trav()" is
the most natural way to find all the directories in the tree. Compare
C News 1-04 Page 20 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
the simplicity of the method used with any nonrecursive implementation
you can devise (and there are many) and you should get an appreciation
for the little used (but sometimes misused) technique of recursion.
Summary
The examples given here are simplified, but are still useful programs.
They illustrate the use of "SETARGV.OBJ" and the functions
"findentr()", "findnext()", "get_DTA()", and "set_DTA()", any or all
of which can be incorporated into your own programs. Using them, your
programs can expand wildcards without direct reference to the DOS
functions. More importantly, I hope that you can see from these
examples that it is easy to use DOS functions, even if you do not know
assembly language, and that you will be encouraged to learn about and
use other DOS functions to extend the power of C programs operating in
the DOS environment.
Figure 1 - ARGS.C
/* Display command line arguements */
/* Link with SSETARGV.OBJ. */
#include <stdio.h>
main(argc, argv) int argc; char *argv[];
{
int i;
for (i=1; i<argc; ++i)
{
#ifdef NOQUOTES
puts(argv[i]);
#else
/*
Use of lower level output routines saves space if "printf()"
is not needed elsewhere, though "printf()" would be a little
less cumbersome at the source level.
*/
putchar('"');
fputs(argv[i],stdout);
putchar('"');
putchar('\n');
#endif
}
}
Figure 2 - FF.C
#include <stdio.h>
#include <string.h>
#include "dostype.h"
C News 1-04 Page 21 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
main(argc,argv) int argc; char *argv[];
{
char st_dir[128];
char *namepart;
int i, j;
if (argc<2) exit(1);
i=strlen(argv[1])-1;
while (i>=0 && argv[1][i]!='\\' && argv[1][i]!=':') --i;
if (i>=0)
{
if (argv[1][i]==':')
{
st_dir[i+1]='\\';
st_dir[i+2]='\0';
}
else
st_dir[i+1]='\0';
namepart=argv[1]+i+1;
while (i>=0)
{
st_dir[i]=argv[1][i];
--i;
}
}
else
{
st_dir[0]='\\';
st_dir[1]='\0';
namepart=argv[1];
}
trav(st_dir,namepart);
}
trav(st_dir,filename_ext)
char st_dir[];
char filename_ext[];
{
char matchname[128];
struct DTA_STRUCT DTA;
unsigned char end_byte;
/* Show matching files in this directory */
strcpy(matchname,st_dir);
strcat(matchname,filename_ext);
if (findentr(&DTA,matchname,0)==0)
do
if (!(DTA.attr & DIRECTORY))
C News 1-04 Page 22 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
{
fputs(st_dir,stdout);
puts(DTA.name);
}
while (findnext(&DTA)==0);
/* Recursively search subdirectories */
end_byte=strlen(st_dir);
matchname[end_byte]='*';
matchname[end_byte+1]='\0';
if (findentr(&DTA,matchname,DIRECTORY)==0)
do
if ((DTA.attr & DIRECTORY) && (DTA.name[0]!='.'))
{
strcpy(matchname+end_byte,DTA.name);
strcat(matchname,"\\");
trav(matchname,filename_ext);
}
while (findnext(&DTA)==0);
}
Figure 3 - FINDENTR.C
#include <dos.h>
#include "dostype.h"
findentr(DTA, search_name, s_attr)
struct DTA_STRUCT *DTA; /* NULL to use current DTA */
char *search_name;
int s_attr; /* permitted attributes (use for H,S,D) */
{
char far *far_sn=search_name;
/* convert DTA to far rather than place burden on caller */
/* (only needed by small or medium memory models) */
struct DTA_STRUCT far *far_DTA=DTA;
union REGS inregs;
struct SREGS segregs;
unsigned save_DTA_SEG;
unsigned save_DTA_OFF;
if (DTA)
{
/* save current DTA address */
get_DTA(&save_DTA_SEG,&save_DTA_OFF);
/* set DTA address to argument structure */
set_DTA(FP_SEG(far_DTA),FP_OFF(far_DTA));
}
/* Find first match file */
inregs.h.ah=0x4e;
C News 1-04 Page 23 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
inregs.x.cx=s_attr;
segregs.ds=FP_SEG(far_sn);
inregs.x.dx=FP_OFF(far_sn);
intdosx(&inregs,&inregs,&segregs);
if (DTA)
/* restore DTA address */
set_DTA(save_DTA_SEG,save_DTA_OFF);
/* return result */
if (inregs.x.cflag) return (inregs.x.ax);
else return 0;
}
findnext(DTA)
struct DTA_STRUCT *DTA; /* NULL for current DTA */
{
struct DTA_STRUCT far *far_DTA=DTA;
union REGS inregs;
struct SREGS segregs;
unsigned save_DTA_SEG;
unsigned save_DTA_OFF;
if (DTA)
{
/* save current DTA address */
get_DTA(&save_DTA_SEG,&save_DTA_OFF);
/* set DTA address to argument structure */
set_DTA(FP_SEG(far_DTA),FP_OFF(far_DTA));
}
/* Find next entry */
inregs.h.ah=0x4f;
intdos(&inregs,&inregs);
if (DTA)
/* restore DTA address */
set_DTA(save_DTA_SEG,save_DTA_OFF);
/* return result */
if (inregs.x.cflag) return (inregs.x.ax);
else return 0;
}
Figure 4 - DTA.C
#include <dos.h>
/* Set DTA address */
set_DTA(seg,off)
C News 1-04 Page 24 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
unsigned seg, off;
{
union REGS inregs;
struct SREGS segregs;
inregs.h.ah=0x1a;
segregs.ds=seg;
inregs.x.dx=off;
intdosx(&inregs,&inregs,&segregs);
}
/* Get current DTA address */
get_DTA(seg,off)
unsigned *seg, *off;
{
union REGS inregs;
struct SREGS segregs;
inregs.h.ah=0x2f;
intdosx(&inregs,&inregs,&segregs);
*seg=segregs.es;
*off=inregs.x.bx;
}
Figure 5 - DOSTYPE.H
/* FCB_DATE:
*/
/* Date/time fields of FCB (also DTA_STRUCT, defined below)
*/
struct FCB_DATE
{
struct
{
unsigned seconds:5;
unsigned minutes:6;
unsigned hours:5;
} time;
struct
{
unsigned day:5;
unsigned month:4;
unsigned year:7; /* 1980=0 */
} date;
};
/* DTA.STRUCT:
*/
/* Data block returned by DOS functions 0x4E and 0x4F, which find
*/
C News 1-04 Page 25 21 Feb 1988
================================================================
Title: Filename Wildcard Expansion in Microsoft C
================================================================
/* files and directories matching a pathname, with wildcards.
*/
#define ARCHIVE 0x20
#define DIRECTORY 0x10
#define SYSTEM 0x04
#define HIDDEN 0x02
#define READONLY 0x01
struct DTA_STRUCT
{
char reserved[21];
char attr;
union
{
struct FCB_DATE field;
unsigned long date_time; /* For comparing the combination */
} timestamp;
unsigned long size;
char name[13];
};
C News 1-04 Page 26 21 Feb 1988
================================================================
/Usr/Bin by Marshall Presnell
================================================================
The Great Compiler War Myth
If you have ever read the C Echo Conference on FidoNet,
I'm sure that you've witnessed the advent of "Compiler Wars".
Not that it's a new topic, I'm sure that people have been
arguing the merits of their personal favorite compiler since
the second compiler was written. It's not the purpose of
this author or C News to say "This is the best compiler".
There are over 30 (and that's a LOW estimate) currently
available C compilers for the PC. How does one go about
determining which is "best". It simply can't be done. One
compiler may excel in code optimization but have a limited
library, another may have a robust library but be terrible
as far as compiler features, yet another will have features
out the wazoo, but produce poor code. It goes on to include
ANSI compatibility, preprocessor capabilities, unused code
detection and elimination, diagnostic messages, clean user
interfaces, pointer optimization, register usage
optimization, etc, etc, ad nauseam.
"But which compiler is the best?"
All of them are, and none of them are. If they get the job
done efficiently for your purposes, it's a good compiler. If
they fall down on your job, it's not a good compiler. Since
there is no way to adequately evaluate the different
compilers in such a manner that everyone agrees with, the
question is objectively irresolvable.
Oddly enough, the question usually arises with specific
reference to Borland's Turbo C, Microsoft C 5.0, and
Microsoft Quick C. Well.... ALL of the above packages are in
a class that I would consider "excellent". All have robust
libraries, support graphics, compile quickly, generate
decent code. They all are good packages to develop
applications under. Turbo C and Quick C are WONDERFUL for
the novice programmer who wants to see what C is, and get
some experience with it. Basically, I'll take all three if
given a choice. All have disadvantages, the most common
being that all of them have bugs. I personally prefer Turbo
C's graphics and use it for any graphic presentation of
data, but for fast code and speed I use Microsoft C 5. It's
ALL a matter of personal preference.
The point is simply, there ain't no such thing as the best C
compiler. There's no use even trying to find it. Use what
you have or what you buy to it's fullest extent and it's a
C News 1-04 Page 27 21 Feb 1988
================================================================
/Usr/Bin by Marshall Presnell
================================================================
good deal (and you may learn something before it's done!).
If you have any topic that you would like to see covered in
the /usr/bin, please feel free to drop me a note on the C
BBS or via FidoNet. I'm at 109/639.106.
Next issue: How to communicate with a FOSSIL
C News 1-04 Page 28 21 Feb 1988
================================================================
ARTICLE SUBMISSION STANDARDS AND ADDRESSES
================================================================
As I have repeatedly stated in this newsletter and previous
issues, I would like to see user-submitted articles, reviews or
questions. Listed below are the standards that should be
followed to make my job easier as an editor.
- Articles should be submitted in a ASCII non-formatted
file.
- If the article include code fragments as examples. Then
you can include the entire source file if you like for
inclusion with the newsletter.
- Book or magazine reviews should follow the same format,
that is outlined in this issue. The publisher, author,
title, and ISBN number are a must.
- Compiler/and or product reviews, should include the
version number and manufacture. If possible, reviews
should include a sample program with benchmarks.
If you have any questions you can contact me at the
address's included on the next page.
C News 1-04 Page 29 21 Feb 1988
================================================================
ADDRESSES
================================================================
The C BBS is located at:
C BBS
% BCL Limited
P.O. Box 9162
McLean VA, 22102
or you can send netmail to:
1:109/713 < The phone number in the current nodelist is
inaccurate. At this time it is not known
when it will be corrected. >
C News 1-04 Page 30 21 Feb 1988
================================================================
USER RESPONSE FORM:
================================================================
This form will be included as a regular feature in all future
issues of C NEWS.
What did you think of the content of this Issue? _____________
_______________________________________________________________
What improvements can you think of that would make C News a
better tool for the C Community?
_______________________________________________________________
_______________________________________________________________
What is your favorite section or sections? ___________________
_______________________________________________________________
What don't you like about C News? ____________________________
_______________________________________________________________
Additional Comments: _________________________________________
_______________________________________________________________
_______________________________________________________________
_______________________________________________________________
C News 1-04 Page 31 21 Feb 1988
================================================================
INDEX
================================================================
Subject: Issue:
Articles:
Filename Wildcard Expansion in MSC 4
TurboC and Interrupts: A few Questions 2
Book Reviews:
C Database Development 1
C Programming Guide 1
C Programming Language 1
C Programmer's Guide to Serial Communications 3
C Programmer's Library 1
C Primer Plus 1
C the Complete Reference 2
Crafting C Tools for the IBM PC 2
Learning to Program in C 1
Microsoft C Programming on the IBM PC 1
MS-DOS Developer's Guide 4
Programming in Windows 3
Reliable Data Structures in C 1
TurboC Programmer's Reference Book 2
Compilers:
QuickC 1
Software Reviews:
Bplus11.arc 3
C_Dates.arc 4
Cdate.arc 4
Casm.arc 3
C-subr.arc 4
Docu.arc 3
Jcl-src.arc 4
Mscpopup.arc 3
Ndmake41.arc 4
Nuc-subr.arc 3
Shift_c.arc 4
Sysact11.arc 4
Tp_to_qc.arc 3
Xenixarc.arc 4