Stupid question. Haven't done production C in a while and just inherited some legacy code. In case it makes a difference it is running out of OMVS on a Z/OS IBM mainframe. The C program is invoked by an assembler program. The assembler program passes in a number arguments that are simply addresses. Some are addresses that contain addresses, and some are just addresses.

The C program then uses strcpy and memcpy to move data back and forth between the assembler program and the C program. I'm at the point where I'm trying to save some space. Currently I am copying the passed addresses to a pointer variable, and then using that variable in strcpy. For example

char *cTempPtr = NULL, search[256] = "init";
cTempPtr = argv[1];
strcpy(search, cTempPtr);

What I would like to do is cut out the need for the extra pointer variable and just dereference the address contained in argv[1]. I have tried numerous combinations of *argv[1], etc... but apparently I just don't remember by reference/dereference logic well enough. I also haven't found any useful hits on google. To clarify I would like the code to look like:

char *cTempPtr = NULL, search[256] = "init";
strcpy(search, *argv[1]);

That is the basic idea anyway. Basically, the value of argv[1] is an address that points to the first byte of a null terminated character array that has been allocated in the assembler program. So, I want strcpy to use the address in argv[1] to copy that value, without having to use a middleman in the form of a pointer variable. But all my attempts to dereference argv[1] have failed. Any help will be appreciated.

Recommended Answers

All 9 Replies

This is the original code, right?

char *cTempPtr = NULL, search[256] = "init";
cTempPtr = argv[1];
strcpy(search, cTempPtr);

The equivalent of that without using cTempPtr is as follows:

char search[256] = "init";
strcpy(search, argv[1]);

There's no magic involved between assigning cTempPtr and using it in strcpy, the address is the same. If you use *argv[1] instead, you've got a type mismatch because *argv[1] is equivalent to argv[1][0], which is the first character of the second string in argv. The second argument of strcpy expects a pointer to char, not a char.

Ok, that makes sense. But to clarify, if argv[1] holds the value "1234" will using strcpy that way that I am above cause it to copy "1234" or will it go to the address space "1234" and start copying there?

strcpy doesn't know or care if the string represents an address. If you want to copy the contents of the address represented by the string, you first have to convert the address to a suitable type. For example:

int addr = (int)strtol ( argv[1], NULL, 0 );
strcpy ( search, (char*)addr );

Exactly how you go about the conversion depends on how the address is stored in argv. It could be the string representation of an address (eg. "0x12345"), or it could be a pun of the data where each character matches a byte of the address. The above code assumes the former.

It is not clear to me why you try to deference argv[1]

If what you want is to take a portion of argv[1] content, you can do as follows:

strncpy(pPointer,pSource,nNumberOfBytes);

Stupid question. Haven't done production C in a while and just inherited some legacy code. In case it makes a difference it is running out of OMVS on a Z/OS IBM mainframe. The C program is invoked by an assembler program. The assembler program passes in a number arguments that are simply addresses. Some are addresses that contain addresses, and some are just addresses.

The C program then uses strcpy and memcpy to move data back and forth between the assembler program and the C program. I'm at the point where I'm trying to save some space. Currently I am copying the passed addresses to a pointer variable, and then using that variable in strcpy. For example

char *cTempPtr = NULL, search[256] = "init";
cTempPtr = argv[1];
strcpy(search, cTempPtr);

What I would like to do is cut out the need for the extra pointer variable and just dereference the address contained in argv[1]. I have tried numerous combinations of *argv[1], etc... but apparently I just don't remember by reference/dereference logic well enough. I also haven't found any useful hits on google. To clarify I would like the code to look like:

char *cTempPtr = NULL, search[256] = "init";
strcpy(search, *argv[1]);

That is the basic idea anyway. Basically, the value of argv[1] is an address that points to the first byte of a null terminated character array that has been allocated in the assembler program. So, I want strcpy to use the address in argv[1] to copy that value, without having to use a middleman in the form of a pointer variable. But all my attempts to dereference argv[1] have failed. Any help will be appreciated.

It is not clear to me why you

shush. grownups are talking, now.

commented: Don't be a jerk -3
commented: Indeed, you're becoming more and more obnoxious these days. -7

Ok. Well, let me post a section of the original code and then my re-write of it.

Original Code

int main (int argc, char *argv[])
{ /* 01 */
FILE *fd;
char host[20]="xups.uni.edu";
char req[005]="init";
char key[050]="init";
char msg[256]="init";
char nid[256]="Not Found";
char uni_num[256]="Not Found";
char email[256]="Not Found";
char *pt1, *pt2, *pt3, *pt4, *pt5, *pt6;
int  *ptr_nid, *ptr_unino, *ptr_email, *ptr_msg, *ptr;
int  nid_adr, unino_adr, email_adr, msg_adr;
 
pt1 = &req[0];
pt2 = &key[0];
pt3 =  argv[0];
pt4 =  argv[1];
if (argc == 3) {
  pt3 = argv[1];
  pt4 = argv[2];
}
if (argc == 7) {
  pt5 = argv[6];
  pt6 = &host[0];
  strcpy (pt6,pt5);
}
 
strcpy ( pt1,pt3);
strcpy ( pt2,pt4);
 
query_ups(req, key, uni_num, nid, email, msg, host);

Rewrite

main(int argc, char **argv)
{
    char   nid.256.=" ",
           uniID[256] = "",
           email[256]="",
           employeeID[256] = "",
           searchField[256] = "",
           searchValue[256] = "",
           *cTempPtr = NULL;
    int *msgPtr, *nidPtr, *uninoPtr, *emailPtr, *tempPtr;
    int doMemOut = 0, echo = 1;

    switch(argc)
    {
       case 3:
          if(strcmp(argv[1], "alias") == 0)
          {
             strncpy(searchValue,argv[2], sizeof(nid) - 1);
             strcpy(searchField, "CN");
          }
          else if(strcmp(argv[1], "unino") == 0)
          {
             strncpy(searchValue, argv[2], sizeof(uniID) -  1);
             strcpy(searchField, "employeeID");
          }
          else if(strcmp(argv[1], "email") == 0)
          {
             strncpy(searchValue, argv[2], sizeof(email) -  1);
             strcpy(searchField, "uniEduEmailForwardingAddress");
          }
          else
          {
             printf("Specify index to search! alias,unino,email\n");
             return(1);
          }
       break;
       case 7:
          cTempPtr = argv[1];
          strcpy(searchField, cTempPtr);
          cTempPtr = argv[0];
          strcpy(searchValue, cTempPtr);
          cTempPtr = NULL;
          doMemOut = 1;
          echo = 0;
          break;
       default:
          printf("Invalid number of arguments!\n");
          return(1);
       break;
    }
 
    if(query_ups(searchField,searchValue,"uniEduEmailForwardingAddress",email)!=0)

The goal here is to prep the incoming data for the query_ups function. The assembler arguments are as follows.

ARGS     DS    0F         OMVS CALL ARGUMENTS ADDR LIST                 00007700
A1       DS    A          ARGUMENT 1  ADDR-> LDAP REQ KEY TYPE          00007800
A2       DS    A          ARGUMENT 2  ADDR-> LDAP KEY                   00007900
AA3      DS    A          ARGUMENT 3  ADDR-> ADDR-> NETWRKID            00008000
AA4      DS    A          ARGUMENT 4  ADDR-> ADDR-> UNINO               00008100
AA5      DS    A          ARGUMENT 5  ADDR-> ADDR-> EMAIL               00008200
AA6      DS    A          ARGUMENT 6  ADDR-> ADDR-> LDAP MESSAGE        00008300
A7       DS    A          ARGUMENT 7  ADDR-> LDAP SERVER IP ADDRESS     00008400

As you can see, they pull in the data with strcpy originally. I'm just trying to clean it up and make it easier for the next unlucky to look at. To be honest, I don't know how the assembly program is passing the addresses, I don't have access to it. Just the above arg list that was given to me to go off of. I appreciate all of your help. I think the way it is working is basically the same way it was, so I'm assuming it is ok as is. But I guess I won't know until they test it and see if it gets the values from memory like it is supposed to.

/* you are going to have some trouble with your rewritten source at compile time, if you don't change your declaration of nid as a weird sort of structure node: it's a typo, no doubt. Also, you should put in some comments for the next person to show your logic, since they cost nothing. */

Actually, NID is fine. The problem is that I use a TN3270 emulator to connect to the mainframe from Windows. What this means is that the hex code for [] in the mainframe is different than in the Windows world. So, when I copy back and forth I have to edit the hex values to get them to display correctly. Windows, not knowing how to display the hex code, just shows a period.

Also, I will definitely comment this code thoroughly when I am done. It is difficult to move blocks of text on the mainframe in oedit (or at least a lot clumsier than having a mouse) so I write as little as possible until I am sure it is correct/where I want it to be. I appreciate the tips though.

Good on both counts, and glad to try to help; interesting code.--John as gnujohn

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.