Descriptors in VMS C (was Re: VMS C & records in files)

Leo de Wit leo at philmds.UUCP
Sat Aug 27 07:07:26 AEST 1988


In article <1003 at nmtsun.nmt.edu> warner%hydrovax at nmt.edu (M. Warner Losh) writes:
>In article <612 at philmds.UUCP>, leo at philmds.UUCP (Leo de Wit) writes...

   [my stuff conceirning $DESCRIPTOR macro deleted]...

>This macro can only be used when you know what the string is that you are 
>dealing with in advance.  While this is true for a large number of cases, 
>it isn't true in ALL cases.

   True; the char ptr must be an array, since sizeof is used.

   [some of Warner's stuff deleted]...

>                                                                 You can
>use the function I posted, or you could write a macro that looks something 
>like:
>
>#define fill_in_desc(d,s)	{d->dsc$w_length = strlen(s); \
>				 d->dsc$a_address = s;}
>and use it like this:
>
>func(str)
>char *str;
>{
>	$DESCRIPTOR(user_string_dsc, "");
>
>	fill_in_desc(user_string_dsc, str);
>}
>
>and that would also take care of the problem of freeing stuff up, since it 
>is done by the 'C' compiler via automatic variables.  So this would be an
>even better solution than the function that I posted.  Leo, thank you for 
>pointing out this macro.  It made me rethink some of the methods that I was 
>using.
>
>Warner		warner%hydrovax%nmt at relay.cs.net
>My spelling and views are my own.

There are still some drawbacks: if you use automatic variables, you
still have to declare them (for instance by the $DESCRIPTOR macro) and
fill them (for instance by the macro you suggested). It can be done all
at once however (oh, how I love C 8-):

Suppose you need to build such a string descriptor from a (C type) string
str, and have to pass the address of this struct (to a VMS system call).
This should do the trick:

   LIB$SOMETHING(&make_descr_s(str));

where make_descr_s is defined by:

struct dsc$descriptor_s make_descr_s(str)
char *str;
{
    struct dsc$descriptor_s retval;

    retval.dsc$w_length  = strlen(str);
    retval.dsc$b_dtype   = DSC$K_DTYPE_T;
    retval.dsc$b_class   = DSC$K_CLASS_S;
    retval.dsc$a_pointer = str;

    return retval;
}

Note that make_descr_s returns a struct on the stack; the VMS library
function will get a pointer to this struct by passing the address (&).
It would do you no good by typing make_descr_s as a
struct dsc$descriptor_s *, and returning the address of retval, since
retval, being an automatic variable, will be gone when make_descr_s
returns. In the case retval is declared as static, this WILL work, but
you get trouble when using multiple instances of make_descr_s in one
parameter list: all values returned will point to the same static
buffer (containing the last created descriptor).

For instance (supposing make_descr_s returns a pointer to a static struct):

   LIB$OTHERTHING(make_descr_s(str1),make_descr_s(str2));

will fail.

So the solution given seems pretty neat. You could even say

#define Make_Str_Descr(str) &make_descr_s(str)

and use

   LIB$SOMETHING(Make_Str_Descr(str));

if you don't like the & in the arg list (but I don't recommend that
practice, since it does not really clear things up).

                                      Leo.



More information about the Comp.lang.c mailing list