Category : C Source Code
Archive   : ARGEX2.ZIP
Filename : ARGV.DOC

Output of file : ARGV.DOC contained in archive : ARGEX2.ZIP

Turbo C Command-line Argument Expander
John Maline
June 23, 1987

6-23-87 J Maline Original version
8-1-87 J Maline Improve memory allocation strategy
8-17-87 J Maline Allow '/' as path separator. I was torn on whether
to do this, but I found out that Microsoft does, and
it really didn't cause any of the problems that I
was concerned about anyway...
9-30-87 J Maline Released (again) to BIX and Usenet
10-6-87 J Maline Add matching of directory names
10-7-87 J Maline Mention incompatibility of file name expansion
not being sorted
Put argv[0] in lower case.
10-17-87 J Maline Expanded filenames now sorted
2-24-88 J Maline Convert ARGV.ASM to Turbo C 1.5 compatibility


This library, when linked in with a Turbo C program will replace the
default command-line processing with a more Un*x-like version.

The default command-line processor supplied with the compiler standard
library simply copies the whitespace separated command-line strings to
the argument array passed to the main() function.

This replacement library does the same job, but additionally expands
wildcard file names into the list of matching file names. This handling
mimics the Un*x convention of having the command processor expand
command-line wild cards, so the program just sees a list of file names.
Command-line wildcard handling isn't 'seen' by the programmer at all.

It was inspired by a module included in Microsoft C that does the same
job. Minor differences will be mentioned.


No special programming is needed (that's the whole point!). The
argument array passed to main() just 'magically' has any wildcard
filenames expanded.

See the enclosed program X.C which simply prints its arguments.

If an error occurs, the message 'Abnormal Program Termination' will
print and the program will stop (before it really started). It will
probably be a result of a memory allocation error.

Compiling/Linking (your program)

Here's the only hard part. The library ARGVx (x is the memory model:
t,s,c,m,l,h) must be linked in BEFORE the standard turbo libraries.
Since Turbo C's default model is small, use ARGVS is you don't use the
-m switch. Examples follow.

TLINK (or LINK for that matter)
Link like normal, put ARGVx before the Cx library.
tlink \turboc\c0x+yourprogram+...,yourprogram,nul,ARGVx+...

TCC (automatic linking)
Just include ARGVx.lib in the list of files. Don't forget the .lib
extension or it'll try to compile ARGVx.c
tcc (switches, including -mx maybe) yourprogram ARGVx.lib

TC (project)
Just mention ARGVx.lib in your project file.

Alternatively, the two objects contained in ARGVx can be included in the
Cx library if you have a librarian (use it to extract the objects from
ARGVx and insert them in Cx). They'll replace the default code and
you'll always have command line expansion! Of course, you'll want to
keep a backup copy of the original libraries (but you didn't need me to
tell you that, did you?)

Command Line Handling

Here's specifically what happens to the command line you've typed in.

0. The name of the program is taken as argument 0 if we're running
under DOS 3.0 or later. In DOS 2.x, the program name isn't available
and a null string is there instead.

1. Find the next 'token' on the command line

A token is a sequence of characters followed by a separator.
Spaces, tabs and newlines are normally separators, unless surrounded by
a pair of double quotes ("). End of line is a separator. Since double
quotes have a special meaning, to really include a double quote, it must
be preceeded by a backslash (\).

For example, here's how the following line is separated into tokens.

hi mom "how are" you doing" "today? "\"I'm fine\""

how are
doing today?
"I'm fine"

2. If the token has a wildcard character (* or ?) that wasn't enclosed
in double quotes, try to expand it into the matching file names. If no
matches are found, the actual (unexpanded) token is placed in the
argument array. In the above example, "doing today?" has a wildcard
character, so it tries to expand. It'll fail, so "doing today?" is
inserted in the list unchanged.

Both normal files and directory files are matched. Hidden and system
files are ignored, along with volume labels. The special directories,
'.' and '..' are specifically excluded from the expansion even if they
match the wildcard. This is Microsoft compatible and a change from the
earliest versions.

If one or more matches are found, the token is put in the argument
array, with the wildcard part replaced by the actual file names (once
for each matching file). This is accomplished by appending the expanded
file name to the "path part" of the token. The path part is everything
from the start of the token to the last occurance of ':', '\' or '/'.

All of the file names resulting from the expansion of a token are sorted

For example, assuming the root directory of the disk contains the
files autoexec.bat, config.sys and The following
command line expands as follows (assume we're in the root):

\*.* hi mom *.* *.xyz *.*/s

\autoexec.bat (leading backslash included, the path part)
\ (...forward slash would have worked too!)
\config.sys (...notice that these 3 are sorted)
hi (copied just like normal)
autoexec.bat (no backslash, because none on this token) (...these 3 are sorted)
*.xyz (no match, put token in unchanged)
*.*/s (error expanding because of "/s", added unchanged)

The text going straight from the command line to the argument array is
unchanged in case (upper/lower). The file name part of expanded wild
cards is lower case. The Microsoft C version uses upper case for
expanded names. I prefer lower case.

There are a couple of minor differences between my command line handling
and Turbo C's built in handling. Turbo C considers something in double
quotes to be a token by itself, even if immediately preceeded or
followed by other non-whitespace characters.

For the command line argument: when"in"the"course"
Turbo C default parsing:
My parsing:

Turbo C's default command-line parsing doesn't consider the line-feed
character to be a separator. Since I use the isspace() function to find
separators, I consider it one.


ARGVT.LIB Tiny model library
ARGV.DOC This documentation
ARGV.ASM Assembler module
EXPAND.C C code (most of the work)

MAKEFILE Make file for compiling/assembling
X.C Example program, prints its argv[].

Compiling (ARGVx)

Since both source and libraries are included, you can use this package
"right out of the box" or change it to suit your tastes or fix bugs.

A makefile is included in the distribution to automate construction of
the package. The makefile runs with Borland's 'make' utility. The
makefile uses Microsoft MASM 4.0 and Lattice's OML librarian.
Microsoft's LIB can be substituted for OML by changing the makefile.

Since almost all of the program logic is contained in the C module, most
changes would not involve changing the assembly module. Turbo C and a
librarian are the only things really needed to remake the libraries in
this case. Simply recompile EXPAND.C and replace it in the library.

See the comment at the top of EXPAND.C for symbols that you can define
on the tcc command line (-D...) to change the operation of the package.
The two of most interest are -DWILDSORT=0 to disable sorting of expanded
file names and -DWILDMASK=??? to change what files are eligible to be
matched by wildcards (hidden/system/directory/...).

Examine the makefile for necessary switches in the assembly and
compilation if you'll be doing any of this "by hand".

I'd be very interested in hearing about any changes made, especially bug


The library is made up of a small assembler function 'setargv' which
calls 'setargs', written in Turbo C. Source code and a makefile are
provided. MASM 4.0 or later is required if the assembler function must
be changed (unlikely, 90% of the work is in C). The makefile is written
for the Lattice librarian, OML. Minor changes needed for Microsoft's
LIB or whatever...

This is implemented by replacing one of Borland's assembler modules of
the startup code. It was a pretty clean replacement, but considering
the low-level nature of this code, I can't guarantee what will happen
when Turbo C 2.0 (or whatever) comes out. You can rest assured that if
it's not compatible, I'll be working on the upgrade...

As of Turbo C 1.5, the internal variables I access, _argv and _argc are
documented, so are unlikely to change in the future. The only change
from the Turbo C 1.0 version is the older one refers to the undocumented
variables __argv and __argc, which don't exist in 1.5.

I'm VERY interested in any feedback, bugs, suggestions.

No warranty, expressed or implied... Not liable for damages... Other
pseudo-legal stuff to keep you from sueing me... This has nothing to do
with Texas Instruments (my own hardware, my own copy of TC, my own

John Maline UUCP: ut-sally!im4u!ti-csl!tifsie!john
Texas Instruments sun!texsun!ti-csl!tifsie!john
PO Box 655012 M/S 3618 uiucdcs!convex!smu!tifsie!john
Dallas, TX 75265 Voice: (214)995-3575 BIX: jwmaline