[comp.unix.wizards] Command interfaces

blarson@skat.usc.edu (Bob Larson) (01/01/70)

In article <3161@psuvax1.psu.edu> schwartz@gondor.psu.edu (Scott E. Schwartz) writes:
>In article <432@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>>    PR1MOS:
[comments about pre-rev 14 primos, which is about as modern as unix
version 3 or VMS 1.0.  Do you wonder why I ignore complaints about its
command interface?]

(Primos 21.0.1 is the latest supported release I have used.  Due to
non-disclosure agreements, I can't discuss current beta testing, if
any.)

>>	If SEG understands wildcards this is the first I've heard of it.
>I last used primos at rev 20.  SEG didn't know about wildcards

SEG doesn't know about wildcards.  Wildcards are handled for SEG by
the Primos command processor.  (There is no way to turn off wildcard
expantion to a program loaded with SEG other than telling the command
processor not to expand them, such as quoting the argument.)
(Wildcards have been part of the primos command processor since 19.0,
about 5 years.)

>then either, but there is a new utility called "BIND" that makes
>(new) EPF style runfiles.  (These work like primos "internal"
>commands.) BIND takes command line options, unlike SED.
>Part of the magic of BIND is it allows you to specify what command
>line objects (i.e. wildcards) are expanded by the command processor
>when the BINDee is invoked.

(Bind has been supported since primos 19.4)

>One catch when talking about primos wildcards is that they
>are treated in a fundamentaly different way than unix wildcards.
>The command line "cc @.c" with files a.c b.c  is equivalent to 
>	cc a.c
>	cc b.c
>rather than "cc a.c b.c".  That is, the command processor
>iterates over wildcards rather than expanding them.  To get unix
>style behavior, you have to use the Multics-ism "cc [wild @.c]"
>or use BIND to tell the command processor not to expand wildcards
>for cc.  Primos supplies library routines to search directoies
>using wildcards.

You can also specify to bind that the wildcard will only match files
not directories, that the user should be queried for each file on
wildcard matches unless the -novfy option is given, (used by delete)
which argument name matching is to be performed against, etc.

This is an example of the difference between command interfaces
between unix and primos.  Most primos commands will only process one
file per run, (including the C compiler) so the primos wildcard
expantion matches what the primos commands expect.  Only those
commands which have some use for processing multiple files together
(ld and emacs are examples) need to turn off the command processor
wildcard expantion and do their own.  (Of course system calls to do the
wildcard expantion are available.)  For programs like delete it
doesn't matter to the user how it is done, and for programs like copy
and rename the primos way is more powerfull because of name generation.

When talking about primos wildcards, you should remember that they are
in general more powerfull that unix wildcards.  Besides + (match any
single character) @ (match a sequence of 0 or more characters not
containing .) and @@ (match any sequence), there are facilities to do
name genearation and iteration.

For example, how would you do the equivelent of this in unix:

cmpf *>old>@@.(c,h) == -report ==.+cmpf -file

(Explanation: compare all files in the old sub-directory ending in .c or
.h with the file of the same name in the current directory, and put
the output in the file of the same name with .cmpf appended.  Non-files
(directories and segment directories) ending in .c or .h are ignored.
[I do prefer the output of diff -c to that of cmpf, but that isn't
what I'm talking about here.]

>Note that is would be easy to add this kind of functionality
>to unix... just add more bits to the inode structure, 

These bits should be part of the program object, in my opinion.
Shells that understand them can notice the new magic number and look
at some flag word to figure out what wildcard expantion to do.

>st_dowild say.  Then have the shell look at them before
>expanding wildcards.  It will never catch on, though :-)

>For the record, after several years of using primos, it is clear
>to me that the unix scheme is sufficiently clearer and simpler 
>so as to outweigh many of the arguments against having the shell
>to globbing.  Nothing is perfect, but in general unix does it better.

After several years of using primos, it is clear to me the unix way of
handling wildcards is much less powerfull.  However, many users will
never bother to figure out more than the minimum needed to do their
job.  It is clear to me that power, ease of use, etc. have almost no
relation to how operating systems are chosen anyway.
--
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%fns1@ecla.usc.edu
			oberon!fns1!info-prime-request

andy@rocky.STANFORD.EDU (Andy Freeman) (12/04/87)

In article <337@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>In article <1890@celtics.UUCP> roger@celtics.UUCP (Roger B.A. Klorese) writes:
>> >Because, unless one knows and fully understands that globbing is done by
>> >the shell and not the program, one would expect, as with other operating
>> >systems...

>In article <6774@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
>> In fact that is a key "win" of UNIX over OSes that make applications deal
>> with globbing.

>Have you ever used TOPS-10?  That was a system where globbing was done by
>the program, not the shell.  Result?  No two programs had exactly the
>same syntax for file names (some would let you quote strange characters
>by writing octal, some wouldn't, some allowed directories, some didn't,
>&c &c).  And of course user-programs and commands HAD to use different
>syntax...  Doug Gwyn is absolutely right:  doing file-name expansion in
>the shell so that EVERY command does it EXACTLY the same way is wonderful.

Have you ever used TOPS-20?  That was a system that provided a command
interface that was used by most programs.  (There's an emulation package
that lets tops-10 programs run under tops-20; those programs don't use
the interface.)  The result - every program, not just the shell, parses
arguments in the same way.  Every program has recognition and expansion
not only for file names, but other kinds of arguments as well.  Every
program has abbreviations (these can be defeated by the program if
necessary - you can make users type out "destructive" commands in
completely).  Every program will tell you what it's expecting and can
provide defaults, overridable of course, that it will tell you about.
Line editing commands know that different kinds of arguments have different
structure so they do the right thing, and this works the same way for
every program.  Expansion to multiple file names in TOPS-20 isn't done
the way unix it, but thanks to the command parser and the file system
interface, every program does it exactly the same way.

TOPS-20 shares one of unix' big failures - the command parser doesn't
know what arguments other programs expect so it can't parse them
for you.  Therefore, many things that are unix programs, rm, e.g.,
are part of the standard command shell.  Many programs will take
their arguments off the command line, where you can't take advantage
of the parser, or prompt for them directly, where you can.  It would
be much easier to add the capability to do this right (so the user
can take advantage of the parser either way) in TOPS-20 than it would
be to add it to unix.  It could be done by modifying the command parser
so that it would work with every TOPS-20 program.  (They wouldn't even
have to be recompiled.)

True, TOPS-20 is inadequate in many ways.  It isn't portable.  No one
ever wrote a decent shell-like programming language for it (but the
ones that were written used the command interface for their programs).
The standard command shell doesn't know about I/O redirection (even
though the operating system supports it) so most programs aren't written
in a way that would take advantage of it.  There isn't a good systems
programming environment.  (This is sometimes an advantage.  Unix makes
it easy for any fool to write a program and many of them do.)

-andy
-- 
Andy Freeman
UUCP:  {arpa gateways, decwrl, sun, hplabs, rutgers}!sushi.stanford.edu!andy
ARPA:  andy@sushi.stanford.edu
(415) 329-1718/723-3088 home/cubicle

ok@quintus.UUCP (Richard A. O'Keefe) (12/04/87)

I mentioned TOPS-10 as a horrible example of a system which did not do
globbing in the shell.  Various people asked whether I had used TOPS-20,
MULTICS, or PR1MOS.

    MULTICS:
	I have never had the pleasure of using MULTICS.
	It has always sounded like a Good Thing, if you can stomach PL/I.

    PR1MOS:
	I've not only used PR1MOS, I have access to some of the manuals.
	The last time I used it seriously was Rev 14, back when they
	were just starting to switch over to UNIX- (or AEGIS-) like
	options.  A release or two before that, you passed options to
	the Fortran compiler by writing octal numbers in the command
	line (this set the P300's A and B registers to the numbers you
	wrote; on PR1ME 400s and 500s the compilers still ran in
	32R = PR1ME 300 mode).  I am **NOT** kidding, folks, you had
	to be able to add octal to use the FTN compiler.
	If SEG understands wildcards this is the first I've heard of it.

    TOPS-20:
	Yes, I have used TOPS-20.  In fact the command line parser
	available under TOPS-10 looked to me like a backwards port
	of the TOPS-20 command line parser.  The snag was that
	ordinary programmers never heard about it (the system calls
	manual didn't mention it because it wasn't a system call,
	and as for a system library manual, forget it, there wasn't
	even an easily accessible routine to parse a file name and
	turn it into the linked bit patterns the system calls wanted).
	The programs I used under TOPS-20 were mostly ones that were
	really TOPS-10 programs that had been ported, so of course
	didn't use the command line parser (good grief, they didn't
	even use exactly the same syntax for file names), so
	IN ORDER TO USE TOPS-20 I HAD TO KNOW WHICH PROGRAMS USED
	THE "STANDARD" COMMAND LINE PARSER AND WHICH DIDN'T,
	and for every program I used that didn't use the standard
	command line parser I had to know its specific peculiar syntax.

There are several problems with having a command line parser of some
sort as a library package.  The fact that a lot of my programs are
rather smaller than a good command line parser like the TOPS-20 one
is one of them.  (Though UNIX System V.3 shared libraries should
make that argument go away;  making shared libraries is an incredible
process but it is Someone Else's Problem.)  The number-one problem is
that when I use a utility I have to remember whether the programmer
was courteous enough to use the standard interface or not, and if he
DIDN'T I am in trouble.  A command line parser which was in a shared
library and which had to be included so that a program could be
invoked as a command would be a good compromise.

There is another argument.  Lisp programmers are familiar with the
EVAL problem.  That is, a function which normally expects to do its
own argument evaluation is sometimes called with its arguments
evaluated.  If program P1 has command line arguments which it calls
wild-card expansion on (say it handles "*") and program P2 wants to
ask P1 to process a particular file whose name it has just computed,
P2 has real trouble if that name looks as though it contains
wild-cards, such as the name "*".  Of course if the wild-card
characters cannot be part of a file-name, some of this problem goes
away.  TOPS-20 avoided this problem by making just such a restriction
and by not being all that good at programs-calling-programs in the
first place.  Another method is to have a "quoting" function which
will quote all meta-characters in a file name.  (How many people
know that setting the 8th bit of characters USED to do this in UNIX?)

Don't forget that programs are users too.
I have used about a dozen operating systems, and of those, only UNIX
and the Burroughs MCP made it anything less than acutely painful for
one program to call another.  I imagine MULTICS must have been good
at it too.  What relevance has this to user interfaces?  Well, the
easier it was for the author of a program to write it, the better the
chance he got it right, and what's the good of any sort of interface
to a broken program?

hedrick@athos.rutgers.edu (Charles Hedrick) (12/04/87)

Richard O'Keefe says basically that it's better to let the shell parse
file names rather than individual programs because there are both
technical and people problems with getting people to use a consistent
command parser in their programs.  This response seems very odd to me.
At most the existing Unix shell does wildcard file name parsing, and
then only for commands typed directly to the shell.  That's only part
of the problem.  Programs still have to parse options and arguments
that aren't file names.  And many programs have internal commands once
you start them.  Because Unix depends upon the shell for parsing,
there is no standard parsing library for use in programs.  Thus ~
works in file names on the command line, and in Emacs, but not when I
use the ~r command in mail to read a file.  And of course every
program has its own oddities in parsing options.  As for programs that
themselves have command scanners, it seems to depend upon what
operating system that author had used before they came to Unix.  Some
of the newer Berkeley command scanners (e.g.  lpc) look a lot like a
typical VMS or TOPS-20 scanner.  Others (mail) tend to the
single-letter command tradition of ed.  In the long run, I think we'd
all be better off to have an "official" command parser that was used
in parsing both the command line and commands given inside the
program.  I think TOPS-20 proves this point very clearly.  TOPS-20 is
a second-generation offshoot of TOPS-10.  TOPS-10 was a lot like Unix.
The command scanner (or a program called from it, COMPIL) would take
some central responsibility for what was typed on the command line.
But once you went into the program, you got whatever the author
happened to come up with.  Like Unix, there was an old tradition of
single-letter commands and options,

  outfil=infile/o/23d

and a new one of longer names:

  outfil=infile/option/detail:23

This variation all stopped with TOPS-20, with its single official
command scanner.  It took a number of years before there were
native-mode TOPS-20 programs for everything, so for a while we had all
the TOPS-10 command styles, plus the new TOPS-20 one.  But for the
last 5 years or so, the normal TOPS-20 user at Rutgers has been using
only native TOPS-20 programs.  And the native TOPS-20 programs all use
the TOPS-20 scanner.  Because TOPS-20 programs were all done in
assembly, the scanner was put into the kernel, and there were system
calls to use it.  (TOPS-20 tended to use the kernel as a shared
library.  This sounds sort of wierd, but it works remarkably well.
They were able to keep system call overhead low enough that programs
actually used system calls to do things like parse a floating point
number, convert date formats, etc.  On the 20, assembly language
programming was remarkably pleasant.)  Obviously on Unix this would be
done via a library.  I think the TOPS-20 experience is important,
because much of it would be duplicated if we tried to fix Unix
parsing.  As with TOPS-20, there would be a period where the old and
the new overlapped.  But a properly designed new standard would be
enough of an improvement that I think we could be fairly sure it would
take over within a few years.  People do use standard routines when
they are available.  

As Mark Crispin has said, if we are lucky, within a few years, Unix
will have all the amenities that TOPS-20 users had 10 years ago.  Then
we can all start moving forward again. (But this time no hardware
vendor will be able to pull the rug out from under us.)  [To be fair,
much the same process of standardization also took place on TOPS-10,
which continued in parallel wth TOPS-20.  TOPS-10 gots its own
official scanner, this time as a library, called SCAN/WILD.  I haven't
been around TOPS-10 recently enough to know whether SCAN and WILD have
managed to get rid of all the old ad hoc command scanners.  Certainly
it was moving that way last time I looked.]

schwartz@gondor.psu.edu (Scott E. Schwartz) (12/05/87)

In article <432@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>    PR1MOS:
>	I've not only used PR1MOS, I have access to some of the manuals.
>	The last time I used it seriously was Rev 14, back when they
>	were just starting to switch over to UNIX- (or AEGIS-) like
>	options.  A release or two before that, you passed options to
>	the Fortran compiler by writing octal numbers in the command
>	line (this set the P300's A and B registers to the numbers you
>	wrote; on PR1ME 400s and 500s the compilers still ran in
>	32R = PR1ME 300 mode).  I am **NOT** kidding, folks, you had
>	to be able to add octal to use the FTN compiler.

This is still supported, by the way.

>	If SEG understands wildcards this is the first I've heard of it.

I last used primos at rev 20.  SEG didn't know about wildcards
then either, but there is a new utility called "BIND" that makes
(new) EPF style runfiles.  (These work like primos "internal"
commands.) BIND takes command line options, unlike SED.
Part of the magic of BIND is it allows you to specify what command
line objects (i.e. wildcards) are expanded by the command processor
when the BINDee is invoked.

One catch when talking about primos wildcards is that they
are treated in a fundamentaly different way than unix wildcards.
The command line "cc @.c" with files a.c b.c  is equivalent to 
	cc a.c
	cc b.c
rather than "cc a.c b.c".  That is, the command processor
iterates over wildcards rather than expanding them.  To get unix
style behavior, you have to use the Multics-ism "cc [wild @.c]"
or use BIND to tell the command processor not to expand wildcards
for cc.  Primos supplies library routines to search directoies
using wildcards.

Note that is would be easy to add this kind of functionality
to unix... just add more bits to the inode structure, 
st_dowild say.  Then have the shell look at them before
expanding wildcards.  It will never catch on, though :-)

For the record, after several years of using primos, it is clear
to me that the unix scheme is sufficiently clearer and simpler 
so as to outweigh many of the arguments against having the shell
to globbing.  Nothing is perfect, but in general unix does it better.

In terms of "rm *".  Assuming it is that important a case to take care
of, why not have the shell recognise and fork "rm" after checking
arguments.  Certainly "login" in the shell is precident enough. And the
old executable can stay in /bin for those in the know to use when the
need arises.



-- Scott Schwartz            schwartz@gondor.psu.edu

mike@nexus.UUCP (Mike Hickey) (12/05/87)

Greetings!

    Having been a TOPS hacker of sorts, all this discussion piqued my
interest.  Regarding a script language, there was PCL (Programable
Command Language) available from C-M University.  You were able to
"install" new commands into TOPS complete with arg evaluation and arg
help using the '?'.  

    As for a parser under un*x, Columbia Univ.  has been working on a
version of the COMND system call (that did all the parsing) written in
'C'.  There is a newsgroup that handles info but the address escapes
me right now.  

Perhaps this will jog someone else's memory....

andy@rocky.UUCP (12/05/87)

In article <432@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes:
>    TOPS-20:
>	Yes, I have used TOPS-20.  In fact the command line parser
>	available under TOPS-10 looked to me like a backwards port
>	of the TOPS-20 command line parser.  The snag was that
>	ordinary programmers never heard about it (the system calls
>	manual didn't mention it because it wasn't a system call,

The TOPS-20 command parser I referred to is the COMND% system call.
It's in the JSYS manual with every other system call.

>	and as for a system library manual, forget it, there wasn't
>	even an easily accessible routine to parse a file name and
>	turn it into the linked bit patterns the system calls wanted).

TOPS-20 files are manipulated with file numbers (which are assigned on a
per job basis).  GTJFN% (which can parse file names that the user types
and uses COMND%'s filename editing conventions) does this conversion.
(I think that COMND% will call GTJFN% in the appropriate circumstance.)
If you couldn't find this system call, how did you do file I/O?  (Maybe
he's flaming the quality of the library of the implementation of the
language he was using.  The c library on unix machines tends to be far
better, but that doesn't seem relevant to the topic at hand.)

>	The programs I used under TOPS-20 were mostly ones that were
>	really TOPS-10 programs that had been ported, so of course
>	didn't use the command line parser (good grief, they didn't
>	even use exactly the same syntax for file names), so
>	IN ORDER TO USE TOPS-20 I HAD TO KNOW WHICH PROGRAMS USED
>	THE "STANDARD" COMMAND LINE PARSER AND WHICH DIDN'T,
>	and for every program I used that didn't use the standard
>	command line parser I had to know its specific peculiar syntax.

Well, c programs that were developed under unix usually don't use
the TOPS-20 command parser after they're ported either.  How could
anyone use such a flawed system....

>There are several problems with having a command line parser of some
>sort as a library package.  The fact that a lot of my programs are
>rather smaller than a good command line parser like the TOPS-20 one
>is one of them.  (Though UNIX System V.3 shared libraries should
>make that argument go away;  making shared libraries is an incredible
>process but it is Someone Else's Problem.)

See above.  The COMND% system call requires the system call instruction
and tables that describe the arguments.  These tables contain pointers
to user code that performs the action associated with the argument and
descriptions of the arguments (such as their ascii form for commands).
Unless you're running the ultimate cisc, you can't use less space even
if you do character i/o without buffering and line editing.  (COMND%
is usually in the swappable portion of the OS which is sort of like
a shared library only it has bad connotations.)

>					The number-one problem is
>that when I use a utility I have to remember whether the programmer
>was courteous enough to use the standard interface or not, and if he
>DIDN'T I am in trouble.  A command line parser which was in a shared
>library and which had to be included so that a program could be
>invoked as a command would be a good compromise.

Yes, TOPS-20 programmers can write their own incompatible command parsers.
Unix doesn't provide much of a choice.

>There is another argument.  Lisp programmers are familiar with the
>EVAL problem.  That is, a function which normally expects to do its
>own argument evaluation is sometimes called with its arguments
>evaluated.  If program P1 has command line arguments which it calls
>wild-card expansion on (say it handles "*") and program P2 wants to
>ask P1 to process a particular file whose name it has just computed,
>P2 has real trouble if that name looks as though it contains
>wild-cards, such as the name "*".  Of course if the wild-card
>characters cannot be part of a file-name, some of this problem goes
>away.  TOPS-20 avoided this problem by making just such a restriction
>and by not being all that good at programs-calling-programs in the
>first place.

TOPS-20 doesn't make programs-calling-programs difficult.  The problem
is that most TOPS-20 programs prompt for their own inputs directly from
the terminal.  This terminal-oriented convention makes it difficult for
one program to use another, but this is not due to anything in TOPS-20.
It is just as easy/hard to write such programs under unix.

I'm not sure what the objection is.  If * is not a legal character in
a file name, it won't appear in a name that has been generated by a
program.  Since TOPS-20's file name<->file number/handle system calls
(GTJFN% and its inverse) know about wildcards and the quoting convention
(as should all programs that generate file names containing "special"
characters in file names), one can pass computed names with wild cards
to other programs.  The called program can decide whether or not to
manipulate all matching files or just the first one (alphabetically).
One can also pass names that use quoted "special" characters - unless
the called program undoes the quoting, they won't be treated specially.
Apart from the fact that wild card expansion is inconvient for user
programs under unix (look at all the programs that don't do it), this
is just like unix.

-andy

ps - TOPS-20 suffers from its lack of a decent library that most programming
languages can use.  On the other hand, the TOPS-20 sites I'm familar with
are more multi-lingual than the unix sites I use regularly.  The latter run
nothing but shell scripts and c and fortran programs.
-- 
Andy Freeman
UUCP:  {arpa gateways, decwrl, sun, hplabs, rutgers}!sushi.stanford.edu!andy
ARPA:  andy@sushi.stanford.edu
(415) 329-1718/723-3088 home/cubicle

ok@quintus.UUCP (12/05/87)

In article <432@cresswell.quintus.UUCP> I said of the **TOPS-10**
command line parser SCAN/WILD that
1> The snag was that
1> ordinary programmers never heard about it (the system calls
1> manual didn't mention it because it wasn't a system call,
In article <802@rocky.STANFORD.EDU>, andy@rocky.STANFORD.EDU
(Andy Freeman) said
2> The TOPS-20 command parser I referred to is the COMND% system call.
2> It's in the JSYS manual with every other system call.
I was talking about TOPS-10 at that point, not TOPS-20, as I think the
text made clear.  I tried for two years to get a copy of the SCAN/WILD
documentation for TOPS-10.  (This was several years ago.)

By the way, there IS a UNIX library package for parsing command lines
(*after* file-name expansion has been done by the shell).
It's called getopt.  There is a getopt(3) for C programs to call, and
a getopt(1) for sh scripts to call.  This is a System V feature, but
the version I use is a public-domain version written by Henry Spencer
and sent to net.sources in 1984.  "man -k option" or "man -k command"
will tell you about it.  System V release 3 has a souped-up version
called getopts().

I last used TOPS-20 about 4 years ago.  I must say that I very much liked
the command interface:  I accessed the machine infrequently over a slow
network and didn't have any TOPS-20 manuals.  Being forced to stay a novice,
I was *very* pleased with the prompts, completion &c.  But typing <ESC> at
a program that wasn't expecting it wasn't always a good idea...

VMS and TOPS-20 have a number of similarities:  a comparison from someone
who has used both a lot would be illuminating.

---------------------------------------------------
Timesharing (n): an access method whereby one computer uses many people.
			--- IBM definition.

howie@cunixc.columbia.edu (Howie Kaye) (12/05/87)

In article <118@nexus.UUCP> mike@nexus.UUCP (Mike Hickey) writes:
>
>    As for a parser under un*x, Columbia Univ.  has been working on a
>version of the COMND system call (that did all the parsing) written in
>'C'.  There is a newsgroup that handles info but the address escapes
>me right now.  
>
>Perhaps this will jog someone else's memory....

I support (and wrote part of) this package.  It is called CCMD, and
does a bit more than COMND did.  There is no newsgroup, but rather a
mailing list.  Mail to:
	info-ccmd-request@cu20b.columbia.edu
will get you information.  Mail to:
	info-ccmd@cu20b.columbia.edu
will actually post to the mailing list.

There is also a blurb about the package in the September '87 issue of
;login: (from Usenix).

------------------------------------------------------------
Howie Kaye				howie@columbia.edu
Columbia University 			hlkcu@cuvma.bitnet
Systems Group				...!rutgers!columbia!howie

budd@bu-cs.UUCP (12/08/87)

Older TOPS-10 programs had ersatz wildcarding (most notablly PIP,
which would accept imbeded spaces in filenames), while more recent
CUSPier ones used the WILD libarary along with SCAN to provide a
consistant command interface.  Like all such tools there can be more,
or less sophisticated uses of them. LINK implemented per file
switches.  SCAN also provided a consistant init file parser (ISCAN)
which read a SWITCH.INI file and looked for switches for this utility
(like a .Xdefaults file).  Many TOPS-10 utilities (including PIP) had
powerful wildcard abilities;

.RENAME FOO*.X=BAR*.Y

Neither TOPS-20 nor Un*x can do this as simply.  (Of course in csh I
just use foreach when I want to do anything fancy)

I don't deny the beauty of the Un*x command line philosophy, but there
are times when the program does know better.  Perhaps globbing should
be per shell procedure / alias.

	Phil Budne, Boston University

chris@mimsy.UUCP (Chris Torek) (12/08/87)

In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>For example, how would you do the equivelent of this in unix:
>
>cmpf *>old>@@.(c,h) == -report ==.+cmpf -file
>
>(Explanation: compare all files in the old sub-directory ending in .c or
>.h with the file of the same name in the current directory, and put
>the output in the file of the same name with .cmpf appended.  Non-files
>(directories and segment directories) ending in .c or .h are ignored.

`sh' is a programming language, and can be shown to be Turing
equivalent (proof by vigourous handwaving), so unless the Pr1me
CLI can also be shown to be Turing equivalent, the Unix shell
interface is more powerful.

	for i in old/*.[ch]; do		# all files in the old subdir..
		if [ -f $i ]; then	# ignore directories named .c or .h
			j=`echo $i | sed 's,.*,,'`
					# get name without leading dir
			diff $i $j > $j.cmpf
					# and compare, output in `.cmpf'
		fi
	done

(I never said it was more concise. :-) )

This sort of thing, like the `rename *.bar .baz' that others are
so proud of :-) , seems to be desired only rarely; in such cases,
shell `for' loops, or programs like one posted sometime last year[1],
do the trick quite easily.

-----
[1] Program name and author forgotten, but basically, it ran a
command iteratively, so that *.bar could be renamed to *.baz with
a syntax like `doit mv \*.bar =.baz'.  It may have been posted
more than a year ago.  At any rate, I did not save it.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

ok@quintus.UUCP (Richard A. O'Keefe) (12/09/87)

In article <17130@bu-cs.BU.EDU>, budd@bu-cs.BU.EDU (Philip Budne) writes:
> Many TOPS-10 utilities (including PIP) had > powerful wild-card abilities;
> .RENAME FOO*.X=BAR*.Y
> Neither TOPS-20 nor Un*x can do this as simply.
Someone commenting favourably on a version of PR1MOS more recent than the
one I used 5 years ago mentioned that PR1MOS has a similar feature.

This is DEFINITELY not one for the novices!  Let's suppose we have a
uniform system so that every command that does this at all does it the
same way, and those that don't report it as an error.  Quickly now,
what does
	RENAME NEW*FOO?.TXT AS OLD?FOO*.TXT
do?  What happens if there are different numbers of wild-cards in the
two sides?  For example, suppose you have a "MOVE <file> TO <directory>"
command, then
	MOVE NEW*FOO*.TXT TO NEWFOO*
might be a reasonable thing to do, if only you knew what it meant.
What happens if you want to say "remove each *.o for which the
corresponding *.c or *.s exists?"

I have used operating systems with this sort of feature, and the trouble
was that except in the very simplest case (exactly one wild-card in both
patterns, and it is the same wild-card in both places) I never quite knew
what it was going to do.  If what you want to do fits into the strait-
jacket the command-line-processor's designer happened to think of, fine.
If you want anything slightly more complicated, you are just as much on
your own as you are in the Bourne shell.

What we want is a general way of mapping file-names from one form to
another.  What's a good tool for that?  Why, an editor!  The Bourne
shell equivalent of the rename thingy is

	ls | sed -n -e 's^/foo\(.*\).x$/& baz\1.y/p' | xargs -n2 mv
	-------------------###########----#######----------------##

The underlined characters are boiler-plate.  The first chunk of sharps
marks the pattern to match the old name.  The second chunk of sharps
marks the pattern to generate the old and new names together.  The last
chunk of sharps marks the command you want applied.  If you add '-p'
just after "xargs", you will be prompted for permission to execute each
constructed command.  This makes ANY command interactive.  The scheme
generalises to making any number of new file names, and lets you permute
the chunks matched by the wild-cards any way you like.

If you haven't got xargs, or if you don't trust the one you've got,
you can change the sed script slightly and pipe it into the shell:

	ls | sed -n -e 's^/foo\(.*\).x$/mv & baz\1.y/p' | sh -f
	-------------------###########--##---#######-----------

The "-f" here suppresses file-name expansion in the shell.
You can insert "pick" as another pipe-line stage to make it interactive.

Neither version of this pipeline is particularly simple, and I agree
that this is not the kind of thing you want to type in.  On the other
hand, I have never done RENAME FOO*.X BAZ*.Y that I didn't end up
regretting it.  It is not clear to me that making a hard-to-understand
command easy to type is a great virtue.  This pipeline IS, however, the
kind of thing you might reasonably put in a script.  Whenever I have
wanted to do something like this, I have first wanted to check that it
was going to do what I expected it to, and often there isn't any way of
doing so (perhaps the current PR1MOS equivalent of "echo", whatever that
is?). On a BSD system, I can type
	ls | sed -n -e <stuff>
and check what comes out the other end, and when I am confident that
I have the transformation right I can then say
	!! | xargs -p -n2 mv

This touches on a user interface topic that I haven't seen mentioned yet,
which is that when I am about to do something complicated I like to build
the command up in small steps, testing it as I go.  I was about to say that
this is orthogonal to the globbing in the shell/in the command question,
but in fact it ISN'T.  Because what I want is to be able to see exactly
what command will be executed and with exactly which arguments, *without*
actually running the command.  (In fact, at the time I test the script,
the command may well not be written yet.)  If you never write anything
complicated enough to warrant testing, globbing in the command may be
just what you want, but the chances are the Macintosh interface would
suit your needs even better.

g-rh@cca.CCA.COM (Richard Harter) (12/09/87)

In article <9679@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>
>`sh' is a programming language, and can be shown to be Turing
>equivalent (proof by vigourous handwaving), so unless the Pr1me
>CLI can also be shown to be Turing equivalent, the Unix shell
>interface is more powerful.
>
	Although I have much respect for Chris, this is rather wide of
the mark.  It takes very little to be Turing equivalent; CLI is also
Turing equivalent (proof by more vigorous handwaving).  More to the point
in discussing languages are the classes of tasks that can be programmed
readily in a language.

	The claim at hand is that CLI is more powerful and expressive
that sh, i.e. the class of tasks that it can handle easily and economicly
is greater.   Having worked with both (and not being willing to claim
expertise in either) I will only say that this is not immediately obvious
to me.  Each strikes me as being baroque in its own fashion.


>
>This sort of thing, like the `rename *.bar .baz' that others are
>so proud of :-) , seems to be desired only rarely; in such cases,
>shell `for' loops, or programs like one posted sometime last year[1],
>do the trick quite easily.
>

'seems to desired only rarely' is a red flag.  Within a particular language
one very tends to do that which can be done easily within the language.
For example, FORTRAN has no natural mechanism for recursion.  One can do
recursion in FORTRAN, albeit painfully.  Is it any surprise that FORTRAN
programmers rarely find a need for recursion?  The same holds true of
command languages as well -- if a particular approach cannot be implemented
readily in a command language, then it won't be used.

It does seem to me that command languages (shell languages) are an area
that needs more work.  Perhaps some one is doing this work, but I haven't
seen it.


-- 

In the fields of Hell where the grass grows high
Are the graves of dreams allowed to die.
	Richard Harter, SMDS  Inc.

schwartz@gondor.cs.psu.edu (Scott E. Schwartz) (12/09/87)

In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>In article <3161@psuvax1.psu.edu> schwartz@gondor.psu.edu (Scott E. Schwartz) writes:
>When talking about primos wildcards, you should remember that they are
>in general more powerfull that unix wildcards.  Besides + (match any
>single character) @ (match a sequence of 0 or more characters not
>containing .) and @@ (match any sequence), there are facilities to do
>name genearation and iteration.

Agreed, to some extent.  But the dark underside of the primos command
processor is that you can't ever have more functionality than it gives
you at the moment.  Unix pipes and such mean that the shell's metacharacters
can be aimed at handling the simple general case, and letting shell
control structures do the rest.

>For example, how would you do the equivelent of this in unix:
>
>cmpf *>old>@@.(c,h) == -report ==.+cmpf -file
>
>(Explanation: compare all files in the old sub-directory ending in .c or
>.h with the file of the same name in the current directory, and put
>the output in the file of the same name with .cmpf appended.  Non-files
>(directories and segment directories) ending in .c or .h are ignored.
>[I do prefer the output of diff -c to that of cmpf, but that isn't
>what I'm talking about here.]

Well, for the bourne shell this will do:

	(cd ./old; ls | while read f; do if [ -f $f ] ; then echo $f; fi; done) | 
	while read f; do diff ./old/$f $f >$f.+cmpf; done

byzantine, I agree, but easy to whip up.  If i've missed a condition that
the primos command applies, I be it can be corrected with little difficulty.

By the way, how does primos handle something like
	ls  [!B]*.[!c]
i.e. multiple internal negation.



-- Scott Schwartz            schwartz@gondor.cs.psu.edu

chris@mimsy.UUCP (Chris Torek) (12/09/87)

In article <9679@mimsy.UUCP> I wrote:
>			j=`echo $i | sed 's,.*,,'`

Oops, I dropped a character.  That should be ... sed 's,.*/,,'`
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

jack@cwi.nl (Jack Jansen) (12/09/87)

In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
> [Discussing primos wildcards versus unix wildcards]
>For example, how would you do the equivelent of this in unix:
>
>cmpf *>old>@@.(c,h) == -report ==.+cmpf -file
>
>(Explanation: compare all files in the old sub-directory ending in .c or
>.h with the file of the same name in the current directory, and put
>the output in the file of the same name with .cmpf appended.  Non-files
>(directories and segment directories) ending in .c or .h are ignored.
>[I do prefer the output of diff -c to that of cmpf, but that isn't
>what I'm talking about here.]

Uhm, yes, unfortunately I find the 'feature' quite unusable.
I *never* come up with the correct sequence of == and @@, so I have to type
the command three times before I get it right. (really retype, that is.
'History mechanism' is something primos has never heard about).

I definitely prefer
for i in *.[ch]; do
    diff old/$i $i >$i.diff
done

(and you can add an 'if [ -d $i ]' if you really care about directories
ending in .c or .h. I don't, because I don't *have* directories ending
in .c or .h).

And, to continue some gripes on primos wildcards:
- I would expect them to work *always*. I.e. if I do
  TYPE @@
  (TYPE is primos echo) I would expect a list of all files, *not* '@@'.
- If I want all arguments on one line, and I use [WILD @@.TMP], and the
  result doesn't fit in 80 characters, I DO DEFINITELY NOT WANT IT TO TRUNCATE
  IT AT EIGHTY CHARS! I lost an important file that way: it was trying
  to generate a list containing PRECIOUSFILE.TMP, but, unfortunately,
  the .TMP started at position 81. So, it removed PRECIOUSFILE in stead.
  sigh.
  
Sorry, there are some neat ideas in primos, but the command processor and
it's wildcards is definitely *not* one of them.
-- 
	Jack Jansen, jack@cwi.nl (or jack@mcvax.uucp)
	The shell is my oyster.

henry@utzoo.UUCP (Henry Spencer) (12/10/87)

> ... Well, the
> easier it was for the author of a program to write it, the better the
> chance he got it right...

As somebody (Kernighan?) once pointed out, if you want people to observe
standards, being standard must be easier than being non-standard.  Why do
people use stdio, or the math functions?  Because it's easier than doing
it yourself, unless you have special needs.  Why don't people use getopt
more?  Because the interface to getopt is a little complicated and it is
hard to get it right when you are typing a program in from scratch.  (For
some discussion about why this is the wrong way to program, and how to
avoid it, come to the Dallas Usenix and listen to my talk!)  Why is command
syntax such a chaotic mess on systems like TOPS-10?  Because it is harder
to do it right than to fudge it crudely.
-- 
Those who do not understand Unix are |  Henry Spencer @ U of Toronto Zoology
condemned to reinvent it, poorly.    | {allegra,ihnp4,decvax,utai}!utzoo!henry

bostic@ucbvax.BERKELEY.EDU (Keith Bostic) (12/10/87)

In article <5565@oberon.USC.EDU>, blarson@skat.usc.edu (Bob Larson) writes:
> For example, how would you do the equivelent of this in unix:
> 
> cmpf *>old>@@.(c,h) == -report ==.+cmpf -file
> 
> (Explanation: compare all files in the old sub-directory ending in .c or
> .h with the file of the same name in the current directory, and put
> the output in the file of the same name with .cmpf appended.  Non-files
> (directories and segment directories) ending in .c or .h are ignored.

OK:

for i in *.[ch]; do
>	if [ -f $i ] ; then
>		cmp $i old/$i > $i.cmpf
>	fi
> done

Note, the above construct has, potentially, far more power than you needed.
Now, if you wish to argue that it's not a "command-line" interface, I would
agree.  And my response would be, in that case, that one of that complexity/
power is unncessary when you can have real programming interfaces.
Incidentally, you *can* put it on a single line...

> After several years of using primos, it is clear to me the unix way of
> handling wildcards is much less powerfull.

Depends how you delimit "wildcards".   I think I disagree.

> It is clear to me that power, ease of use, etc. have almost no
> relation to how operating systems are chosen anyway.

Chosen by whom?  If marketing was all it took, we'd all be running
you-know-what.

--keith

blarson@skat.usc.edu (Bob Larson) (12/10/87)

In article <3167@psuvax1.psu.edu> schwartz@gondor.cs.psu.edu (Scott E. Schwartz) writes:
>In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>>In article <3161@psuvax1.psu.edu> schwartz@gondor.psu.edu (Scott E. Schwartz) writes:
>Agreed, to some extent.  But the dark underside of the primos command
>processor is that you can't ever have more functionality than it gives
>you at the moment.
Not true, since it allows access to functions that may be user written, and
is a programming language in itself.

[example in answer to my question ommited.  The shortest one I received via
mail.  (It took advantage of a feature of diff that the others didn't.)

>By the way, how does primos handle something like
>	ls  [!B]*.[!c]
>i.e. multiple internal negation.

Primos does not dirrectly support double negation, however it also has
CPL (equivelent to shell scripts):

&do i &list [wild ^@@.c]
  &if [substr %i% 1 1] ^= B &then type %i%
&end

Substite dir for type if you want to add options.  
If anyone cares to notice this doesn't handle large directories, I
would note that unix lacks (to my knolage) any reasonable way to
handle large wildcard expantion, and that fixing the above cpl take 1
more line.

I don't plan on continuing the command processor debate, like editors,
it is mainly a matter of personal preference.  I think primos handles
the common case of name generation nicely (without any ambiguities
such as those mentioned about an unspecified os in a different
message), but lacks direct support for multiple negation.  (A rare
case for me.)  (Where the primos command processor realy looses is in
lack of general-purpouse redirection, pipes, and easy handling of
multi-tasking.)
--
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%fns1@ecla.usc.edu
			oberon!fns1!info-prime-request

zap@draken.nada.kth.se (Svante Lindahl) (12/10/87)

In article <5565@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
#For example, how would you do the equivelent of this in unix:
#
#cmpf *>old>@@.(c,h) == -report ==.+cmpf -file

I can do it using either /bin/sh or csh, but it does require more
typing than in Primos. The test for existence of the file is not
necessary so these examples could be simplified at the expense of
risking a few error messages to the terminal.

C-shell:
% foreach i (`cd old; ls *.[ch]`)
> if (-r $i) diff -c old $i > $i.cmpf
> end

Bourne-shell:
$ for i in `cd old; ls *.[ch]` ; do
> if [ -r $i ] ; then diff -c old $i > $i.cmpf ; fi
> done

Svante Lindahl	    zap@nada.kth.se	uunet!nada.kth.se!zap

ignatz@chinet.UUCP (Dave Ihnat) (12/11/87)

This is a little annoying.  First, I doubt the PR1MOS CLI can handle
general wildcards in as flexible a manner as sh or ksh; you can truly
construct some bizarre patterns, if you wish.  But the second part of
my annoyance is that you *don't* want an expression that rivals the
sendmail syntax for complexity and illegibility; the example given
does, and I know I could come up with some that are worse for the
shell using wildcards, negation, and alternates.  Finally, the keynote
is that this is another religious argument, akin to the question
"My {OS | editor | machine } is better than *, because..."
Nobody is ever going to either definitively answer the argument, nor
are we going to convince somebody that X really *is* better than Y,
and sell their box that runs Y to buy an X box.

If a discussion of what should *be put into* a CLI--what features
should be cross-implemented--should spring up, fine.  But "my CLI's
better than your CLI" is boring; I've heard it all before over vi vs.
emacs, BSD vs SysX, etc.
-- 
			Dave Ihnat
			ihnp4!homebru!ignatz || ihnp4!chinet!ignatz
			(w) (312) 882-4673

aglew@ccvaxa.UUCP (12/14/87)

..> Henry Spencer on getopt():
>Why don't people use getopt
>more?  Because the interface to getopt is a little complicated and it is
>hard to get it right when you are typing a program in from scratch.  (For
>some discussion about why this is the wrong way to program, and how to
>avoid it, come to the Dallas Usenix and listen to my talk!)

Another reason not to use getopt: because it requires information to
be put in two places. You have to have a string containing your option
letters, and a case for the actual option. Bad design.
	Still, many thanks to Henry for the PD version.

Actually, I'm a little relieved to hear Henry say that getopt is not
used as often as it should be. I don't particularly like getopt,
but feel guilty when I don't use it.

peter@sugar.UUCP (Peter da Silva) (12/14/87)

In article <5565@oberon.USC.EDU>, blarson@skat.usc.edu (Bob Larson) writes:
> For example, how would you do the equivelent of this in unix:
> 
> cmpf *>old>@@.(c,h) == -report ==.+cmpf -file
> 
> (Explanation: compare all files in the old sub-directory ending in .c or
> .h with the file of the same name in the current directory, and put
> the output in the file of the same name with .cmpf appended.  Non-files
> (directories and segment directories) ending in .c or .h are ignored.
> [I do prefer the output of diff -c to that of cmpf, but that isn't
> what I'm talking about here.]

for i in old/*.[hc]; do diff -c $i `basename $i` > `basename $i`.diff; done

Explanation: compare all files in the old subdirectory anding in .c or .h
with the file of the same name in the current directory, and put the output
in the file of the same name with .diff appended. This doesn't filter out
directories because I wouldn't bother... but if you want:

for i in old/*.[hc]; do if [ ! -d $i ]; then diff -c $i `basename $i` > `basename $i`.diff; fi; done

If you want to do it recursively on all subdirectories of 'old':

find old -name '*.[hc]' -type f -exec diff -c '{}' '`basename {} `'...

These examples, by the way, both use the Primos meaning of wildcards. I presume
that's what you want. i.e.: using the 'for i in pat' structure you can perform
Primos style wildcarding on UNIX, but not vice-versa. What sort of control
structures does Primos support?
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

allbery@ncoast.UUCP (Brandon Allbery) (12/15/87)

As quoted from <450@cresswell.quintus.UUCP> by ok@quintus.UUCP (Richard A. O'Keefe):
+---------------
| If you haven't got xargs, or if you don't trust the one you've got,
| you can change the sed script slightly and pipe it into the shell:
| 
| 	ls | sed -n -e 's^/foo\(.*\).x$/mv & baz\1.y/p' | sh -f
| 	-------------------###########--##---#######-----------
| 
| The "-f" here suppresses file-name expansion in the shell.
| You can insert "pick" as another pipe-line stage to make it interactive.
+---------------
| This touches on a user interface topic that I haven't seen mentioned yet,
| which is that when I am about to do something complicated I like to build
| the command up in small steps, testing it as I go.  I was about to say that
| this is orthogonal to the globbing in the shell/in the command question,
| but in fact it ISN'T.  Because what I want is to be able to see exactly
| what command will be executed and with exactly which arguments, *without*
| actually running the command.  (In fact, at the time I test the script,
| the command may well not be written yet.)  If you never write anything
+---------------

If you look at both the segments quoted above, you'll have the answer.  Use
"sh -nf", of course.

Yes, I use an editor to do this.  In any case, "doit" is the way to go,
although I usually put the list of files into a file and fire up an Emacs
on it (which lets me notice that I accidentally included "precious.c"), then
"sh" the result.  I've constructed not only commands but Makefiles from this
(and in one un-memorable case, a UNIX-PC Office menu of my MH folders...).

No matter what technique you name, some people will like it and some people
won't.  Unfortunately, changing it on the fly is impossible because many
of the alternatives require rewriting most of the system programs....  Maybe
a per-user shared library containing a personalized "getopt" clone which also
does globbing?  No, I suspect that most general way is "sh"; if the user
REALLY wants it, a script can be written for commands which want to do their
own globbing (an alias would be better, since you could quote the globbable
arguments).  PERHAPS add a way to suppress globbing... on shell scripts,
aliases, or functions only.
-- 
Brandon S. Allbery		      necntc!ncoast!allbery@harvard.harvard.edu
 {hoptoad,harvard!necntc,cbosgd,sun!mandrill!hal,uunet!hnsurg3}!ncoast!allbery
			Moderator of comp.sources.misc

mohamed@hscfvax.harvard.edu (Mohamed_el_Lozy) (12/16/87)

In article <22179@ucbvax.BERKELEY.EDU> bostic@ucbvax.BERKELEY.EDU
(Keith Bostic) writes:
>> > Henry Spencer on getopt():
>> > Why don't people use getopt
>> > more?  Because the interface to getopt is a little complicated and it is
>> > hard to get it right when you are typing a program in from scratch.  (For
>
>If the interface to the program is reasonably well defined, i.e. it follows
>the rules laid down in S5, it's not tough at all.  Just put the following 14
>lines in a file in some directory, copy them in and edit as needed.  It just
>doesn't get any easier, this side of 4th GL's.
>

It can (and perhaps should) be made even easier.  A year or so ago I
posted a program to the non-moderated sources group called mkprog that
would take (too many) arguments and produce the getopt(3) switch,
together with declaring the flags as suitable variables and many other
things.

Looking in ~pub on j.cc.purdue.edu I found a similar program called, as
I recall, mkcmd which allowed even more specification of exactly what
you want.  I believe that it has not been posted yet.

Complex interfaces can, and should, be made simpler by putting a
suitable wrapper around them.

bostic@ucbvax.BERKELEY.EDU (Keith Bostic) (12/16/87)

In article <57900005@ccvaxa>, aglew@ccvaxa.UUCP writes:
> 
> > Henry Spencer on getopt():
> > Why don't people use getopt
> > more?  Because the interface to getopt is a little complicated and it is
> > hard to get it right when you are typing a program in from scratch.  (For
> > some discussion about why this is the wrong way to program, and how to
> > avoid it, come to the Dallas Usenix and listen to my talk!)

If the interface to the program is reasonably well defined, i.e. it follows
the rules laid down in S5, it's not tough at all.  Just put the following 14
lines in a file in some directory, copy them in and edit as needed.  It just
doesn't get any easier, this side of 4th GL's.

	#include <stdio.h>
	extern char	*optarg;
	extern int	optind;
	int	ch;

	while ((ch = getopt(argc, argv, "")) != EOF)
		switch((char)ch) {
		case '':
			break;
		case '?':
		default:
			fprintf(stderr, "usage: %s", *argv);
			exit(1);
		}

> Another reason not to use getopt: because it requires information to
> be put in two places. You have to have a string containing your option
> letters, and a case for the actual option. Bad design.

I am totally lost.  You want to explain how you're going to avoid having
"information in two places"?

> Actually, I'm a little relieved to hear Henry say that getopt is not
> used as often as it should be. I don't particularly like getopt,
> but feel guilty when I don't use it.

Why wouldn't you use it?  It's easier to write a command interface with it
than without it, if you do the interface correctly.  Getopt is the best thing
of its type I've seen, although I'm certainly open to something new.  That
guilty feeling?  It's a good thing, go with it.

Keith Bostic
ARPA:	bostic@okeeffe.berkeley.edu
UUCP:	ucbvax!bostic or seismo!keith

schwartz@gondor.cs.psu.edu (Scott E. Schwartz) (12/16/87)

In article <22179@ucbvax.BERKELEY.EDU> Keith Bostic writes:
>In article <57900005@ccvaxa>, aglew@ccvaxa.UUCP writes:
   [quotee unidentified]
>> Another reason not to use getopt: because it requires information to
>> be put in two places. You have to have a string containing your option
>> letters, and a case for the actual option. Bad design.
>
>I am totally lost.  You want to explain how you're going to avoid having
>"information in two places"?
>

Time for a plug for Pr1mos (for a change :-).   Primos has a command
parser called cl$pix.  You give it a picture of the command line in a 
string like   '-f TREE -g TREE -h INT -i -j REST'
and a pointer to a structure that corresponds to those objects:
	01 args
		02 farg string(255)
		02 garg string(255)
		02 harg bin(15)
		02 iarg bit(1) aligned
 		02 jarg bit(1) aligned
		02 rest string(1024) 
(pl/1, anyone?)

Anyway, the information is indeed in some sense in two places, but
the name for each option is in only one place: in the command picture string.	
cl$pix does a great job too.  arguments need not come in any particular
order for it to figure out where they go, you can give alternative names
for switches, and it does some type checking on what you do give it
e.g. -h cat provokes a message to the effect that it was expecting an integer.

If someone with access to Primos docs wants to write a unix version
it would be a good way to see if people prefer that style of option
parsing. (The only Prime I've ever seen is 100s of miles away right now.)

Also, there is a command parser used in one of the columns in Dr.Dobbs
journal that seems to be in this spirit.  It might be worth looking at.

>Why wouldn't you use it?  It's easier to write a command interface with it
>than without it, if you do the interface correctly.  

Certainly getopt is in general better than nothing.


-- Scott Schwartz            schwartz@gondor.cs.psu.edu

blarson@skat.usc.edu (Bob Larson) (12/16/87)

In article <142@piring.cwi.nl> jack@cwi.nl (Jack Jansen) writes:
>Uhm, yes, unfortunately I find the 'feature' quite unusable.
>I *never* come up with the correct sequence of == and @@, so I have to type
>the command three times before I get it right. (really retype, that is.

As with most user interface questions, it is a matter of personal
preference and what you are used to.

>'History mechanism' is something primos has never heard about).

There are at least two command line editors for primos 19.4 and later
on the market, two I know of being passed around, and one included
with primos 21.0 that works with prior version of primos.  (The best
of the lot in my opinion - I like emacs.)  The only os I know of that
has such a wide variety is unix -- but with unix you have to replace
your whole shell to switch command line editors.

>I definitely prefer
>for i in *.[ch]; do
>    diff old/$i $i >$i.diff
>done

I never had time to dig to deep into my unix manuals for this.  It
doen't look any more intuitive to me than the primos example.

>And, to continue some gripes on primos wildcards:
>- I would expect them to work *always*. I.e. if I do
>  TYPE @@
>  (TYPE is primos echo) I would expect a list of all files, *not* '@@'.

Well, fix your expectations.  Wildcards should only be expaned where
filenames are expected.

>- If I want all arguments on one line, and I use [WILD @@.TMP], and the
>  result doesn't fit in 80 characters, I DO DEFINITELY NOT WANT IT TO TRUNCATE
>  IT AT EIGHTY CHARS! I lost an important file that way: it was trying

A.  No standard primos command expects a list of files like this.

B.  The only limit I know of is 160 characters not 80: it applies to
commands directly typed to the command processor (not as a result of
function calls like wild) and the commands that get their command line
from the ancient rdtk$$ call -- anything writen since 19.4 has no
reason to use this and many good reasons not to that I won't list
here.  (Prime is gradually changing over on their utilites.)

C.  There is a limit of 1024 characters for command lines after function
expantion.  If this limit is exceeded, an error message is generated and
the command is not executed.

Therfore, I conclude that this problem must have been a programmer error:
using rdtk$$ to read a command line that should be expected to be long.
Bob Larson	Arpa: Blarson@Ecla.Usc.Edu	blarson@skat.usc.edu
Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson
Prime mailing list:	info-prime-request%fns1@ecla.usc.edu
			oberon!fns1!info-prime-request

bostic@ucbvax.BERKELEY.EDU (Keith Bostic) (12/17/87)

In article <489@hscfvax.harvard.edu>, mohamed@hscfvax.harvard.edu (Mohamed_el_Lozy) writes:
> It can (and perhaps should) be made even easier.  A year or so ago I
> posted a program to the non-moderated sources group called mkprog that
> would take (too many) arguments and produce the getopt(3) switch,
> together with declaring the flags as suitable variables and many other
> things.

	I've seen several of these programs, and I usually have two problems
with them -- they invariably do too much, and they invariably do too little,
i.e. they invariably handle things that I've never needed, and invariably
don't handle things I want.
	For example, with the option "-f filename", I often immediately
open the file, for obvious reasons.  I've yet to see a program that will
handle that.  And global variables!  How many programs (that aren't using
one of these parsers) really need to have their option variables be
global?  How about options that update the same variable, but have a
relationship, i.e. both set a variable unless it's already set in which
case it's an error?  Sure, I know that I can use one of these programs
if I parse arguments the way *it* wants to parse them, but the idea of
tools is to make my life easier -- not to help me reduce my social life
to a fond memory.

> Complex interfaces can, and should, be made simpler by putting a
> suitable wrapper around them.

I agree -- but I have yet to see an example where the wrapper is less
complex than the wrappee.  Send me one and I'll switch in a heartbeat.

Keith Bostic
ARPA:	bostic@okeeffe.berkeley.edu
UUCP:	ucbvax!bostic or seismo!keith

aglew@ccvaxa.UUCP (12/20/87)

In article <22179@ucbvax.BERKELEY.EDU> Keith Bostic writes:
>In article <57900005@ccvaxa>, aglew@ccvaxa.UUCP writes:
>>..> Henry Spencer on getopt()
>> Another reason not to use getopt: because it requires information to
>> be put in two places. You have to have a string containing your option
>> letters, and a case for the actual option. Bad design.
>
>I am totally lost.  You want to explain how you're going to avoid having
>"information in two places"?

Well, in the days before I came to UNIX (using Whitesmith's on a PDP with
RT-11, if I remember correctly), I used to do:

main(argc,argv)
   int argc;
   char **argv;
{
   for(;*++argv;) {
        if( !strcmp(*argv,"-flag") ) {
	    Flag = 1;
        }
	else if( BinaryFlag(*argv,"binary",&Bflag) ) {
	    /* Set or reset Bflag if -binary or -nobinary
  	       was specified */
	}
 	else if( OpenFile(&argv,"-f","rw",&fd) ) {
	}
	else if( HandleDefaultArguments() ) {
	    /* This and others would handle arguments standard
               to all my code, such as verbose, debug, etc. */
	}
        else 
	    Usage();
   }

   ...

}

No, it's not UNIX, it doesn't use single letter flags, but I'm not
so sure that it wasn't better in promoting a standard interface than
getopts.

allbery@ncoast.UUCP (Brandon Allbery) (12/20/87)

As quoted from <22179@ucbvax.BERKELEY.EDU> by bostic@ucbvax.BERKELEY.EDU (Keith Bostic):
+---------------
| In article <57900005@ccvaxa>, aglew@ccvaxa.UUCP writes:
| > Another reason not to use getopt: because it requires information to
| > be put in two places. You have to have a string containing your option
| > letters, and a case for the actual option. Bad design.
| 
| I am totally lost.  You want to explain how you're going to avoid having
| "information in two places"?
+---------------

You answered *this* one a bit earlier in your posting.  ("It doesn't get any
easier, _this_side_of_4th_GL's_."  Emphasis is mine.)

v---- note $ token in column 1 to trigger preprocessing

$		options (argc, argv) {
		/* usage is "[-b str]" */
		string option 'b' into foo:
		/* this option's usage is "[-c]" */
		boolean option 'c' into bar:
		    break;
		/* usage is "[-d mode]" */
		string option 'd' into baz as "mode":
		    if (strcmp(baz, "gorf") == 0) {
		        fprintf(stderr, "%s" -dgorf invalid\n");
		        exit(1);
		    }
		    break;
		}

Notice that type conversion and assignment is automatic; and, if necessary,
special processing can be performed.  I may actually write such a preprocessor;
it could collect the options and their arguments, and build a usage string
automatically.  By default any unmatched option would get the usage string and
exit, but a "default:" phrase could be used to allow special processing.
(Note:  I already *have* written some preprocessors of this general form, most
of them are for DBMS C hooks. It's not difficult for someone experienced with
lex/yacc.)
-- 
Brandon S. Allbery		      necntc!ncoast!allbery@harvard.harvard.edu
 {hoptoad,harvard!necntc,cbosgd,sun!mandrill!hal,uunet!hnsurg3}!ncoast!allbery
			Moderator of comp.sources.misc

arnold@emory.uucp (Arnold D. Robbins {EUCC}) (12/22/87)

In article <5754@oberon.USC.EDU> blarson@skat.usc.edu (Bob Larson) writes:
>>'History mechanism' is something primos has never heard about).
>
>There are at least two command line editors for primos 19.4 and later
>on the market, two I know of being passed around, and one included
>with primos 21.0 that works with prior version of primos.  (The best
>of the lot in my opinion - I like emacs.)  The only os I know of that
>has such a wide variety is unix -- but with unix you have to replace
>your whole shell to switch command line editors.

Interestling enough, this is not necessarily so. In the 8th Edition shell,
the shell itself has no builtin history mechanism. Instead, if HISTORY is
a defined parameter (shell variable), the shell appends the text of each
command to the file indicated by $HISTORY. There is a separate command
(named '=' and '==') that does command history editing and then submits
the new command for execution.

By extension, anyone could write their own history editor that worked the
same way, without building it into the shell.

After considerable thought, this approach, in my opinion, seems both
simple and elegant. Too bad we mere mortals can't get v8 or v9.
-- 
Arnold Robbins
ARPA, CSNET:	arnold@emory.ARPA	BITNET: arnold@emory
UUCP: { decvax, gatech, }!emory!arnold	DOMAIN: arnold@emory.edu (soon)
	``csh: just say NO!''

peter@sugar.UUCP (Peter da Silva) (12/22/87)

In article <5754@oberon.USC.EDU>, blarson@skat.usc.edu (Bob Larson) writes:
> In article <142@piring.cwi.nl> jack@cwi.nl (Jack Jansen) writes:
> >I definitely prefer
> >for i in *.[ch]; do
> >    diff old/$i $i >$i.diff
> >done
> I never had time to dig to deep into my unix manuals for this.  It
> doen't look any more intuitive to me than the primos example.

The fact that half a dozen people so far have come up with this command
line should tell you something.

Here's how it works:

	for each file, i, that matches "*.[ch]"
		diff the copy of that file in "old" with the copy in the
			current directory, putting the output in a file
			of the same name but with a suffix of ".diff"
			appended.

Which is what your example does... but less explicitly.
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.

ftw@datacube.UUCP (12/22/87)

aglew@ccvaxa.UUCP writers:


> Well, in the days before I came to UNIX (using Whitesmith's on a PDP with
> RT-11, if I remember correctly), I used to do:

<code example deleted>

Gee, why didn't you use getflags() ?



				Farrell T. Woods 

Datacube Inc. Systems / Software Group	4 Dearborn Rd. Peabody, Ma 01960
VOICE:	617-535-6644;	FAX: (617) 535-5643;  TWX: (710) 347-0125
INTERNET: ftw@datacube.COM
UUCP: {rutgers, ihnp4, mirror}!datacube!ftw

"OS/2 -- Half an operating system"

robf2@pyuxf.UUCP (robert fair) (12/29/87)

In article <106600024@datacube>, ftw@datacube.UUCP writes:
+ 
+ aglew@ccvaxa.UUCP writers:
+ 
+ 
+ > Well, in the days before I came to UNIX (using Whitesmith's on a PDP with
+ > RT-11, if I remember correctly), I used to do:
+ 
+ <code example deleted>
+ 
+ Gee, why didn't you use getflags() ?
+ 
Well, I guess I'm stupid because never heard of getflags(). Nor has my
Unix (V.2) manual. So, gee, why don't you enlighten us all ?

Rob Fair
ihnp4!pyuxww!pyuxf!robf2

aglew%fang@gswd-vms.Gould.COM (Andy Glew) (12/30/87)

-ftw@datacube.UUCP writes:
-+ aglew@ccvaxa.UUCP (me) writes:
-+ > Well, in the days before I came to UNIX (using Whitesmith's on a PDP with
-+ > RT-11, if I remember correctly), I used to do:
-+ 
-+ <code example deleted>
-+ 
-+ Gee, why didn't you use getflags() ?
-+ 
-Well, I guess I'm stupid because never heard of getflags(). Nor has my
-Unix (V.2) manual. So, gee, why don't you enlighten us all ?
-
-Rob Fair
-ihnp4!pyuxww!pyuxf!robf2

getflags() was one of Whitesmith's quirky C routines, similar to getopt().
Whitesmith C had a lot of nonstandard but deserved to be a standard stuff.

I didn't use it for the same reasons that I don't use getopt() - I don't like
writing stuff twice, I don't like all single letter flags, I like having
"standard" sets of arguments and flags that I define in libraries, and I like
being able to use the same recognizer on .profile type files that I use
on the command line.

By the way: does anyone have the canonical Whitesmith to UNIX conversion
headers and libraries?

BTW2: there is no need to get snarky, guys. "Gee" doesn't have to be
pejorative.

Andy "Krazy" Glew. Gould CSD-Urbana.    1101 E. University, Urbana, IL 61801   
aglew@mycroft.gould.com    ihnp4!uiucdcs!ccvaxa!aglew    aglew@gswd-vms.arpa
   
My opinions are my own, and are not the opinions of my employer, or any
other organisation. I indicate my company only so that the reader may
account for any possible bias I may have towards our products.

ftw@datacube.UUCP (12/30/87)

robf2@pyuxf.UUCP writes:
> In article <106600024@datacube>, ftw@datacube.UUCP writes:
> + 
> + aglew@ccvaxa.UUCP writers:
> + 
> + 
> + > Well, in the days before I came to UNIX (using Whitesmith's on a PDP with
                                                     ^^^^^^^^^^^^
> + > RT-11, if I remember correctly), I used to do:
> + 
> + <code example deleted>
> + 
> + Gee, why didn't you use getflags() ?
> + 
> Well, I guess I'm stupid because never heard of getflags(). Nor has my
> Unix (V.2) manual. So, gee, why don't you enlighten us all ?

Whitesmiths wrote a function called getflags() which they include in the
libraries that they ship along with their compilers.  It's much like a
very specialized version of sscanf():  It takes the addresses of argc
and argv, a format string, and the addresses of variables to fill.  The
format string can specify booleans, numeric fields, single characters,
and strings.  getflags() will rattle through argv collecting the flags
and filling the variables (flags may be specified in any order when a
program is invoked; they need not be in the order given in the format
string), and update argc and argv accoring to the number of items matched.
It also does things like automatic conversion of hex and octal numbers.
It is not super picky about whitespace between a flag and its value.

getflags() has advantages over getopt() in my opinion:  You don't have to
write a loop around it, you don't have to declare a couple of externs,
and it provides a more uniform way of reporting mal-formed command line
args (it issues it's own message regarding usage in this case).

Whitesmiths is pushing (I don't know exctly how hard) to have
getflags() become more of a standard.  They may also release a copy
of that function into the Public Domain if they can get it to become
a standard.  It would be nice to see a getflags() or something similar
to it become standard.  I think that getopt() was a good first step,
but it's kind of clunky to use.

> Rob Fair

Feel more enlightened, Rob? ;-) ;-)

> ihnp4!pyuxww!pyuxf!robf2



				Farrell T. Woods 

Datacube Inc. Systems / Software Group	4 Dearborn Rd. Peabody, Ma 01960
VOICE:	617-535-6644;	FAX: (617) 535-5643;  TWX: (710) 347-0125
INTERNET: ftw@datacube.COM
UUCP: {rutgers, ihnp4, mirror}!datacube!ftw

"OS/2 -- Half an operating system"

gwyn@brl-smoke.ARPA (Doug Gwyn ) (01/06/88)

In article <208@pyuxf.UUCP> robf2@pyuxf.UUCP (robert fair) writes:
-In article <106600024@datacube>, ftw@datacube.UUCP writes:
-+ aglew@ccvaxa.UUCP writers:
-+ > Well, in the days before I came to UNIX (using Whitesmith's on a PDP with
-+ > RT-11, if I remember correctly), I used to do:
-+ <code example deleted>
-+ Gee, why didn't you use getflags() ?
-Well, I guess I'm stupid because never heard of getflags(). Nor has my
-Unix (V.2) manual. So, gee, why don't you enlighten us all ?

Why would you expect a UNIX manual to document Whitesmiths C for RT-11?