Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What is this???

2 views
Skip to first unread message

Cyrand

unread,
Aug 4, 1998, 3:00:00 AM8/4/98
to
I'm looking at some code which goes like this. It's clearly not ANSI,
but what is it? Why does it work? How could I convert it to ANSI?
Lastly, why is it using variable argument functios when it has a fixed
number of arguments?

int
scrollmenul(orgy, orgx, title, maxrows)
char *title;
{
char *choices[MAX_LIST_SIZE], **cpp;
va_list argp;

cpp = choices;
va_start(argp, maxrows);
while (*cpp++ = va_arg(argp, char *))
;
return scrollmenuv(orgy, orgx, title, maxrows, choices);
}

--
Email: cyr...@hotmail.com
(supporter of the campaign against grumpiness in c.l.c)
"Light thinks it travels faster than anything but it is wrong.
No matter how fast light travels it finds that darkness has always
got there first, and is waiting for it." --Terry Pratchett

Cyrand

unread,
Aug 4, 1998, 3:00:00 AM8/4/98
to
James Hu wrote:
> The only things that made the code non-conforming were the lack of
> "..." and the missing call to va_end(). Putting the "..." into the
> function made it necessary to use the improved ANSI C function
> declaration syntax.

Thanks. Can I mix declaration syntaxes? I seem to remember hearing you
can't. If I only need to change functions that use variable arguments,
this is a minor change. If I have to change every function, I have a
big project on my hands.

Chris Torek

unread,
Aug 4, 1998, 3:00:00 AM8/4/98
to
In an article my server has not received, James Hu wrote:
>>The only things that made the code non-conforming were the lack of
>>"..." and the missing call to va_end(). Putting the "..." into the
>>function made it necessary to use the improved ANSI C function
>>declaration syntax.

In article <35C7B099...@juno.com> Cyrand <cyr...@juno.com> wrote:
>Thanks. Can I mix declaration syntaxes?

Yes. You can also mix prototype declarations with old-style
definitions, e.g.,

int f1(int, char *);
int f2(void);

int
f1(i, p)
int i;
char *p;
{
/* ... */
return 17;
}

int
f2()
{
/* ... */
return 42;
}

You must, however, be aware of several restrictions. First, all
variable-arguments functions must be prototyped, and their definitions
must use the newfangled 1989 prototype definition format (as James
Hu mentioned). Second, old-style function definitions do not provide
prototypes and need not be verified against the prototype, so that,
for instance:

int f3(int);
int f3(p) char *p; { return *p; }

need not draw a diagnostic (despite being obviously broken). Third
and probably most tricky, you must widen all the arguments according
to "the usual arithmetic conversions": char and short become int,
and float becomes double. This means that the correct prototype
for a function *defined* as:

void
f4(c, x)
char c;
float x;
{
/* ... */
}

is:

void f4(int, double);

and *not* the obvious but wrong "void f4(char, float)".

The fact that you can mix these means that you can do the following:

#ifdef USE_PROTOTYPES
#define PROTO(args) args
#else
#define PROTO(args) ()
#endif

int f1 PROTO((int, char *));
int f2 PROTO((void));
int f3 PROTO((int));
int f4 PROTO((int, double));

This kind of PROTO macro (sometimes spelled just "P", or in
implementation-specific headers like those in 4.4BSD's /usr/include
directory, __P) allows you to get the benefits of prototypes while
still being able to compile on creaky old pre-1990 systems.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA Domain: to...@bsdi.com +1 510 234 3167
Antispam notice: unsolicited commercial email will be handled at my
consulting rate; pyramid-scheme mail will be forwarded to the FTC.

James Hu

unread,
Aug 5, 1998, 3:00:00 AM8/5/98
to
On Tue, 04 Aug 1998 18:54:57 -0500, Cyrand <cyr...@juno.com> wrote:
>I'm looking at some code which goes like this. It's clearly not ANSI,
>but what is it? Why does it work? How could I convert it to ANSI?
>Lastly, why is it using variable argument functios when it has a fixed
>number of arguments?
>
>int
>scrollmenul(orgy, orgx, title, maxrows)
>char *title;
>{
> char *choices[MAX_LIST_SIZE], **cpp;
> va_list argp;
>
> cpp = choices;
> va_start(argp, maxrows);
> while (*cpp++ = va_arg(argp, char *))
> ;
> return scrollmenuv(orgy, orgx, title, maxrows, choices);
>}

int
scrollmenul (int orgy, int orgx, char *title, int maxrows, ...)


{
char *choices[MAX_LIST_SIZE], **cpp;
va_list argp;

cpp = choices;
va_start(argp, maxrows);

while ((*cpp++ = va_arg(argp, char *)))
;
va_end (argp);


return scrollmenuv(orgy, orgx, title, maxrows, choices);
}

The only things that made the code non-conforming were the lack of


"..." and the missing call to va_end(). Putting the "..." into the
function made it necessary to use the improved ANSI C function
declaration syntax.

I also added an extra pair of parentheses around the test condition to
quiet a warning.

The K&R C did not have a syntax for declaring functions with variable
arguments.


--
James C. Hu <j...@cs.wustl.edu> Computer Science Doctoral Candidate
http://www.cs.wustl.edu/~jxh/ Washington University in Saint Louis
>>>>>>>>>>>>> I use *SpamBeGone* <URL:http://www.internz.com/SpamBeGone/>

James Hu

unread,
Aug 5, 1998, 3:00:00 AM8/5/98
to
On Tue, 04 Aug 1998 20:08:41 -0500, Cyrand <cyr...@juno.com> wrote:
>James Hu wrote:

>> ... Putting the "..." into the function made it necessary to use the
>> improved ANSI C function declaration syntax. ...

>Thanks. Can I mix declaration syntaxes? ...

A guarded yes. The gotcha's generally involve mixing oldstyle function
prototypes with the improved style for the same function.

Martin Ambuhl

unread,
Aug 5, 1998, 3:00:00 AM8/5/98
to

Cyrand wrote in message <35C79F51...@juno.com>...

|I'm looking at some code which goes like this. It's clearly not ANSI,
|but what is it? Why does it work? How could I convert it to ANSI?
|Lastly, why is it using variable argument functios when it has a fixed
|number of arguments?
|
|int
|scrollmenul(orgy, orgx, title, maxrows)
|char *title;
|{
| char *choices[MAX_LIST_SIZE], **cpp;
| va_list argp;
|
| cpp = choices;
| va_start(argp, maxrows);
| while (*cpp++ = va_arg(argp, char *))
| ;
| return scrollmenuv(orgy, orgx, title, maxrows, choices);
|}
========
/* mha - you are looking at old K&R code. It looks suspiciously like the
* code in the example in the standard section 7.8.1.3 (The va_end
macro).
* You might look either at the following rewrite of your code or that
in
* the standard for a way to replace your old code.
*/
#include <stdarg.h>
#define MAX_LIST_SIZE 1024
int scrollmenuv(int orgy, int orgx, char *title, int maxrows, char
**choices);

int scrollmenul(int orgy, int orgx, char *title, int maxrows,...)


{
char *choices[MAX_LIST_SIZE], **cpp;
va_list argp;

cpp = choices;
va_start(argp, maxrows);
while ((*cpp++ = va_arg(argp, char *))) ;
va_end(argp);

return scrollmenuv(orgy, orgx, title, maxrows, choices);

}

Martin Ambuhl (mam...@tiac.net)
/* Newsgroup posts also e-mailed */

Lawrence Kirby

unread,
Aug 5, 1998, 3:00:00 AM8/5/98
to
In article <6q8lan$f...@elf.bsdi.com> to...@elf.bsdi.com "Chris Torek" writes:

...

>You must, however, be aware of several restrictions. First, all
>variable-arguments functions must be prototyped, and their definitions
>must use the newfangled 1989 prototype definition format (as James
>Hu mentioned). Second, old-style function definitions do not provide
>prototypes and need not be verified against the prototype, so that,
>for instance:
>
> int f3(int);
> int f3(p) char *p; { return *p; }
>
>need not draw a diagnostic (despite being obviously broken).

I believe a diagnostic is required here. 6.5 has a constraint that
declarations in the same scope that refer to the same object or function
specify compatible types. 6.5.4.3 is clear that these don't have
compatible types. The main problem with K&R style declarations and
definitions is that there is no enforced argument type checking in function
calls.

>Third and probably most tricky, you must widen all the arguments according
>to "the usual arithmetic conversions": char and short become int,
>and float becomes double.

These are the default argument promotions (6.3.2.2). The usual arithmetic
conversions are a set of rules to bring two arithmetic operands to a
common type. Both make use of the integral promotions. I think I've just
about reached the stage where I don't mix them up but relapse is always
possible. :-)

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------


0 new messages