[net.lang.c] WHAT DOES NARGS

LINNDR%VUENGVAX.BITNET@wiscvm.ARPA (04/25/86)

Some recent postings mentioned a function called nargs() and discussed
its nonportability. What does this function do and under what version of
UN*X would I expect to find it. My SVR2 materials for the VAX do not seem
to include it.

David Linn
----------------------------------------------------------
BITNET:         LINNDR@VUEngVAX.BITNET or PEARL@VANDVMS1.BITNET
MAILNET:        LINN_D_R    \
                David_R_Linn >@VANDERBILT.MAILNET
                David_Linn  /
CSNET:          drl@vanderbilt.csnet
SnailMail:      P.O. 3241-B Vanderbilt
                Nashville, TN   37235

dan@BBN-PROPHET.ARPA (Dan Franklin) (04/25/86)

The short answer is, nargs() does nothing, now, and you are unlikely to
find it on any modern "UNIX brand operating system." Don't use it.  To
quote the 6th edition manual page, "altogether it is best to avoid using
this routine and depend on, for example, passing an explicit argument count."

In 6th edition UNIX, nargs() returned the number of arguments on the
stack.  Well, not quite: it returned the number of *words* of arguments on
the stack; you needed to know already whether the arguments were ints (1
word) or doubles (4 words) or the new-fangled, partially-implemented
"long" datatype (also 2 words).

Even in 6th edition nargs() was falling out of favor, as the manual page
implies.  Its main problem then was that it didn't work in separate I & D
space, which was becoming quite popular as programs grew too large to fit
in 64kbytes (48kbytes for text and data).  It was also a bit sluggish, and
those of us who looked inside it never really felt comfortable with it
either.  As the old "dragon book" said in a footnote, "... argument counts
are obtained by a method we shall not discuss." The method was to peek at
the instruction stream immediately following the JSR and decode the
instructions to see how many words were popped off the stack immediately
following the call.  There was a potential off-by-one problem because the
top of the stack was normally kept "empty"; you could call a routine with
one argument without doing a push of the argument.  So the compiler chose
one of two equivalent forms of addressing for the destination to indicate
to nargs() whether or not it should add 1 to the number of popped words.

Nargs() understood that the compiler might pop the stack using either
explicit stack pointer arithmetic or instructions that popped the stack as
a side effect ("cmp (sp)+, (sp)+" was good for two words).  To handle some
kinds of optimization, nargs() was capable of following jump instructions.
I think it stopped at the first instruction that wasn't a kind of pop or a
jump.

In separate I&D space this didn't work because in user mode on a PDP-11, a
program couldn't read its own instruction space: instructions and data
occupied the same "addresses".  In theory you could use the MFPI (move
from previous instruction space) instruction to get around this, but in
practice you would find that DEC had specially prohibited this, even when
both the current and previous instruction spaces were user mode.  I think
this was intended as a kind of "security".  Some organizations solved the
problem by cutting a trace on one of the processor boards, which was all
it took to make nargs() work using MFPI.

It is amusing to note that the wait() system call in the V6 library
used nargs() to determine whether it was being called with 0 or 1
arguments.  The first time we tried running a program that used wait()
in separate I&D space, we got quite a surprise!

	Dan

gwyn@BRL.ARPA (VLD/VMB) (04/25/86)

nargs() was suppressed about the time of 7th Edition UNIX (1978)
and should not be used for anything these days.  It returned the
actual argument count, for use in functions taking a variable
number of arguments.  If nargs() had to be supported, it would
have an impact on the run-time architecture; many ofthose now
in use simply cannot support nargs().

franka@mmintl.UUCP (Frank Adams) (05/01/86)

In article <289@brl-smoke.ARPA> gwyn@BRL.ARPA writes:
>nargs() was suppressed about the time of 7th Edition UNIX (1978)
>and should not be used for anything these days.  It returned the
>actual argument count, for use in functions taking a variable
>number of arguments.  If nargs() had to be supported, it would
>have an impact on the run-time architecture; many of those now
>in use simply cannot support nargs().

This is not strictly speaking true.  You could have a convention whereby
the number of arguments was always pushed on the stack or left in a
register or something.  This would mean that supporting nargs would
put a burden (time and space) on a program compiled with the compiler.
This is definitely not a good idea.

Frank Adams                           ihnp4!philabs!pwa-b!mmintl!franka
Multimate International    52 Oakland Ave North    E. Hartford, CT 06108