All,

Sorry to come so late. If I bring a whine to go with your chheese, will
you still let me come join the party <grin />?

This solution is much clearer than declaring an undifferentiated
char*argv[]; thank you again, Barbara.

However, I see a problem: there is no null terminator for userid. That
1999999999 values of SALARY() do not show the bug is just bad luck.
Okay, 2000000000 values if you count minus zero; stop being so picky!

Here is what I came up with. It additionally trims unquoted trailing
blanks from USERID(); note DFT(''), which makes an omitted USERID() into
the null string rather than a blank.

I must be overlooking something in some standard library which already
does this. Any pointers?

Cheers,
Terry.

========== start command source
/* parms pgm(aa4721) */
CMD PROMPT('Command with 3 arguments')
PARM KWD(USERID) TYPE(*CHAR) LEN(10) +
VARY(*YES *INT2) dft('')
PARM KWD(SALARY) TYPE(*DEC) LEN(10 2)
PARM KWD(CUSTNO) TYPE(*INT4)
========== start program source
#include <stdio.h>
#include <decimal.h>
#include <assert.h>
#include <string.h>

/* from the command definition
*/
#define MAXLEN_USERID 10

typedef struct varying2
{
short int len;
char data[1]; /* ycch! This relies on the lack of bound
checking */
/* in C. And we had better not instantiate one of
*/
/* these, at least not in a straightforward way.
*/
} varying2_t;

/* I can't believe that I have to write this myself!
*/
/*
*/
void
varying2ToCharStar( varying2_t * v2
, short int destMaxLen
, char * dest )
{
assert( v2->len < destMaxLen ); /* Ensure destination is big
enuf */
strncpy( dest, v2->data, v2->len ); /* data from caller
*/
dest[ v2->len ] = '\0'; /* terminating null
*/

} /* varying2ToCharStar() */

typedef struct inputArguments
{
char * pgmname;
varying2_t * userid;
decimal(10,2) * salary;
int * custno;
} main_args_t;

void main(int argc, main_args_t * main_args)
{
char userid[ 1 + MAXLEN_USERID ];
varying2ToCharStar( main_args->userid, MAXLEN_USERID, userid );
printf("1st arg = %s, userid = %s, 3rd arg = %D(10,2), 4th arg = %d",
main_args->pgmname, userid,
*main_args->salary, *main_args->custno);
}
========== end source code



On Wed, 2009-02-25 at 10:04 -0600, Elvis Budimlic wrote:
Both Barbara's and mine example ought to work. I like Barbara's approach
better as it allows handling of varying data types, so I just tried it out.
Here are the results:

/*START C member source */
#include <stdio.h>
#include <decimal.h>

typedef struct inputArguments
{
char * pgmname;
char * userid;
decimal(10,2) * salary;
int * custno;
} main_args_t;

void main(int argc, main_args_t * main_args)
{
printf("1st arg = %s, 2nd arg = %s, 3rd arg = %D(10,2), 4th arg = %d",
main_args->pgmname, main_args->userid,
*main_args->salary, *main_args->custno);
}
/* END C member source */

Not sure if you're aware of it, but argv[0] is initialized implicitly by the
OS to the fully qualified program name (i.e. ELVIS/INPTST). So, first
argument is always a char *, as illustrated in the struct with the leading
pgmname variable.
To compile the C source, I used this command:

CRTBNDC PGM(ELVIS/INPTST) SRCFILE(ELVIS/C) OUTPUT(*print) DBGVIEW(*ALL)

/* START *CMD source */
CMD PROMPT('Command with 3 arguments')
PARM KWD(USERID) TYPE(*CHAR) LEN(10)
PARM KWD(SALARY) TYPE(*DEC) LEN(10 2)
PARM KWD(CUSTNO) TYPE(*INT4)
/* END *CMD source */

Note that there is no 'pgmname' keyword, as it's passed implicitly by the
OS.
To compile the *CMD source, I used this command:

CRTCMD CMD(ELVIS/INPTST) PGM(ELVIS/INPTST) SRCFILE(ELVIS/CMD)

Then, to test the program, I invoked my command as:

INPTST USERID(MYUSERID) SALARY(3300.44) CUSTNO(77)

And got the following output:

1st arg = ELVIS/INPTST, 2nd arg = MYUSERID , 3rd arg = 3300.44, 4th arg =
77

Hth, Elvis

Celebrating 11-Years of SQL Performance Excellence on IBM i, i5/OS and
OS/400
www.centerfieldtechnology.com


-----Original Message-----
Subject: Re: [C400-L] Submit a program call

Back again... I tried out both Elvis' and Barbara's (I hope a first name
basis is ok!) solutions but I can't even get a compile:

"A parameter of type "main_args_t *" cannot be initialized with an
expression of type "char **"."

After taking a closer look at the language ref manual it seems as though one
*has* to pass char **? Just seems so incredibly awkward that I, just to
perform a simple SBMJOB on the call to this program, would need to go
through a CL program and manually append null terminators etc... (which is
what they do in the Programmer's guide when calling C from CL).





This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2019 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].