Board index » delphi » Declaring variable number of arguments in a function or procedure

Declaring variable number of arguments in a function or procedure

Sorry if this is fairly obvious, but I would like to call some external C
functions that take a variable number of arguments, and have been having a hard
time declaring them in pascal.  How can I declare a function or procedure that
takes a variable number of parameters without using 'array of const'...for
example, how would I declare the writeln procedure?

I'm fairly new to Pascal, so some of the subtelties are still a little fireign
to me.  Thanks for your help.

 

Re:Declaring variable number of arguments in a function or procedure


Quote
> Sorry if this is fairly obvious, but I would like to call some external C
> functions that take a variable number of arguments, and have been having a hard
> time declaring them in pascal.  How can I declare a function or procedure that
> takes a variable number of parameters without using 'array of const'...for
> example, how would I declare the writeln procedure?

   In Pascal, you can't.  The ability to create procedures/functions
with variable arguments exists only with the compiler writer/vendor, and
we poor programmers aren't allowed to do such things.  Pascal is a
highly typed language, and I think that's why we have this restriction.
   To solve your problem, you'll have to be creative: design a single
structure which contains enough information that the called routine can
parse/decipher the variable information you're sending it.  You might be
able to use the "untyped parameter" in this endeavor.

Re:Declaring variable number of arguments in a function or procedure


Quote
Kurt Fitzner wrote:
> Sorry if this is fairly obvious, but I would like to call some external C
> functions that take a variable number of arguments, and have been having a hard
> time declaring them in pascal.  How can I declare a function or procedure that
> takes a variable number of parameters without using 'array of const'...for
> example, how would I declare the writeln procedure?

This is called overloading, and it's a feature of C++ (not C).  Turbo
Pascal doesn't allow this.  Some or all of the TP-compatible compilers
under development may be able to do this, i.e., GNU Pascal, FPK Pascal,
or TMT Pascal.  I'm not sure how TMT would coordinate it, but if you
have the C++ source, you could most likely compile it with DJGPP and
link it with the GNU compiler.  (Actually, I'm not sure about it, but
perhaps Delphi has some overloading capabilities.)

As for procedures like writeln, they're special cases handled by the
linker.  It breaks up the procedure into calls to hidden procedures with
names like WriteChar(), WriteString(), WriteLongint(), etc.  And with
other overloaded functions or procedures, the compiler will generate
code based on how the procedure call is used.  For example, with the
declarations:

type
  Tmyarray = array[0..1023] of byte;
  Pmyarray = ^Tmyarray;

var
  myarray : Pmyarray;

The following two lines should generate identical code:

  new (myarray);  {allocate a structure with known size}

and

  getmem (myarray,sizeof(Tmyarray));

The only difference is where it gets the size of the structure from.
Regardless, when you have a case like this (allocation of memory for a
structure with a known size), the rule of thumb is to use new(), and to
release the memory allocated with dispose().

Quote
> I'm fairly new to Pascal, so some of the subtelties are still a little fireign
> to me.  Thanks for your help.

--
Scott Earnest        | We now return you to our regularly |
set...@ix.netcom.com | scheduled chaos and mayhem. . . .  |

Re:Declaring variable number of arguments in a function or procedure


Quote
>Kurt Fitzner wrote:

>> Sorry if this is fairly obvious, but I would like to call some external C
>> functions that take a variable number of arguments, and have been having a hard
>> time declaring them in pascal.  How can I declare a function or procedure that
>> takes a variable number of parameters without using 'array of const'...for
>> example, how would I declare the writeln procedure?

>> I'm fairly new to Pascal, so some of the subtelties are still a little fireign
>> to me.  Thanks for your help.

If I give you some ideas will you be careful not to shoot yourself in
the foot? :-)  

Non of this is tested, but it seems plausible.  Of course there is no
guarantee you'll get all the "C" library functions to link, but here
goes ---

<CANCEL TYPE CHECKING>

Your two main problems are 1) you have to "push" the parameter list to
the stack, and 2) you have to remove all the parameters from the stack
when done.

The second is relatively easy.  Declare a word to which you will assign
SPtr before starting.  SPtr is a R/O variable, so you will have to
revert to using an inline procedure to restore the stack.

The next problem is to get the parameters to the stack.  Pascal "pushes"
parameters left-to-right, while "C" pushes parameters right-to-left.  So
begin by defining an external Pascal procedure that receives either
receives no parameters, or receives the fixed, or non-optional "C"
parameters in reverse order.  To "push" the optional parameters we'll
inline procedures.  Define one inline procedure for each variable type
you wish to pass (push).  Since Turbo will not allow an empty inline
statement, you'll have to define at least one instruction.  NOP perhaps?

Now to "craft" your call, start by saving SPtr, then invoke your NOP
inline procedures to "push" optional parameters.  Use the "C" prototype
as a guide and push them in right-to-left order.  Make the call using
the partial "C" interface procedure.  The next statement should be your
inline procedure to restore the stack.

VAR SaveSP: Word;

PROCEDURE PopSP(SPtr: Word); INLINE( $5C {pop SP} );
PROCEDURE AddSP(Amt: Word); INLINE($58/$03/$E0 {pop AX; add SP,AX});
PROCEDRE  _Long(i: Longint); INLINE( $90 {nop} );
PROCEDURE _Pchar(p: pChar);  INLINE( $90 {nop} );

example:

FUNCTION _sprintf(Buffer, Format: pChar); EXTERNAL
FUNCTION _itoa(Radix: Integer; Buffer: pChar; Value: Long); EXTERNAL;

VAR s: Array[0..24] of Char;
    Buff: Array[0..80] of Char;

.....
    _itoa(8, @s, 123);
    AddSP(10);

    Long(@s);
    _sprintf(@Buff, '123 decimal == %s octal');
    AddSP(12);

--or--
    SaveSP := SPtr;

    _itoa(8, @s, 123);
    PopSP(SaveSP);

    Long(@s);
    _sprintf(@t, '123 decimal == %s octal');
    PopSP(SaveSP);

</CANCEL TYPE CHECKING>

I notice for just about every function that takes variable parameters,
there are corresponding "C" functions that take a pointer to a parameter
list.  You might want to consider them as an alternative.  You can
probably make life even easier if you wrap each "C" function in a Pascal
counterpart so you would have to deal with underscores or having to
manually reset the stack after each call.

BTW, If anyone tries any of this I'd like to know how they made out.

    ...red

Re:Declaring variable number of arguments in a function or procedure


Quote
kfitz...@compusmart.ab.ca (Kurt Fitzner) wrote:
>Sorry if this is fairly obvious, but I would like to call some external C
>functions that take a variable number of arguments, and have been having a hard
>time declaring them in pascal.  How can I declare a function or procedure that
>takes a variable number of parameters without using 'array of const'...for
>example, how would I declare the writeln procedure?

>I'm fairly new to Pascal, so some of the subtelties are still a little fireign
>to me.  Thanks for your help.

    Normally, this is not possible... normally.

    But, one day, I've seen a Delphi source where the author has said
that he have found how to code a procedure with variable number of
arguments.  I have printed this source but not tried.  

    As soon as I retrieve this printing in my archive (hum hum), I will
send you a copy.

Quote

--
 AVONTURE Christophe                    0 0      The Crazy Programmer
 Christophe.Avont...@is.belgacom.be      |         Brussels (Belgium)
 Uses Standard_Disclaimer;              \_/            Happy New Year
 French Pascal programmation site     http://www.mygale.org/07/jmy51/

Re:Declaring variable number of arguments in a function or procedure


Quote
Kurt Fitzner wrote:

> Sorry if this is fairly obvious, but I would like to call some external C
> functions that take a variable number of arguments, and have been having a hard
> time declaring them in pascal.  How can I declare a function or procedure that
> takes a variable number of parameters without using 'array of const'...for
> example, how would I declare the writeln procedure?

> I'm fairly new to Pascal, so some of the subtelties are still a little fireign
> to me.  Thanks for your help.

This is one area where Pascal is not vague at all: you _cannot_ declare functions
that take a variable number of parameters. You can cheat, using e.g.
arrays of pointers + an indication of how many pointers are valid, but then you
lose type- and range checking.

Sorry,

Remco
--
--------------------------------------------------------------------------------
This is an automatically generated signature for Remco Vietor in netscape.
The views expressed in this message should be taken as the personal views of
the author, unless stated otherwise.

Re:Declaring variable number of arguments in a function or procedure


Quote
Mike Copeland wrote:

> > Sorry if this is fairly obvious, but I would like to call some external C
> > functions that take a variable number of arguments, and have been having a hard
> > time declaring them in pascal.  How can I declare a function or procedure that
> > takes a variable number of parameters without using 'array of const'...for
> > example, how would I declare the writeln procedure?

>    In Pascal, you can't.  The ability to create procedures/functions
> with variable arguments exists only with the compiler writer/vendor, and
> we poor programmers aren't allowed to do such things.  Pascal is a
> highly typed language, and I think that's why we have this restriction.
>    To solve your problem, you'll have to be creative: design a single
> structure which contains enough information that the called routine can
> parse/decipher the variable information you're sending it.  You might be
> able to use the "untyped parameter" in this endeavor.

There seems to be a second reason why Pascal can't have procedures with
a variable number of parameters.
AFAIK, in C (and C++?) it is the _caller_ that puts the parameters on
stack, calls the procedure and clears the stack on return. The caller
should know how much was put on stack.
In Pascal, on the other hand, it is the _called procedure_ that clears
up the stack before returning. So at _compile time_ the procedure
has to know how many bytes to remove from the stack.
This is also (one of) the reason for the use of PASCAL call model in
windows.

Regards,

Remco

--
--------------------------------------------------------------------------------
This is an automatically generated signature for Remco Vietor in netscape.
The views expressed in this message should be taken as the personal views of
the author, unless stated otherwise.

Other Threads