Midrange News for the IBM i Community


Posted by: mssunny
strstr()
has no ratings.
Published: 17 Feb 2014
Revised: 18 Feb 2014 - 1192 days ago
Last viewed on: 25 May 2017 (2783 views) 

Using IBM i? Need to create Excel, CSV, HTML, JSON, PDF, SPOOL reports? Learn more about the fastest and least expensive tool for the job: SQL iQuery.

strstr() Published by: mssunny on 17 Feb 2014 view comments(15)

Hi, I need help with C-function strstr(). Searching delimiters in a string buffer, finding x'0D' works but not x'0D0A' or x'0D25'. I get null pointer. I have the hex values defined as 1A and 2A fields.

 

Return to midrangenews.com home page.
Sort Ascend | Descend

COMMENTS

(Sign in to Post a Comment)
Posted by: DaleB
Premium member *
Reading, PA
Comment on: strstr()
Posted: 3 years 3 months 7 days 6 hours 41 minutes ago

Would help if you could show code snipped with variable declarations and how they're used in strstr(). Are both strings (string to be searched and also the string to be found) null terminated?

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 6 hours 15 minutes ago
Edited: Mon, 17 Feb, 2014 at 10:42:59 (1193 days ago)
D Delimiter 	S 	1A	inz(x'0D')
D Delimiter2 	S 	2A	inz(x'0D0A')
D Delimiter21 	S 	2A	inz(x'0D25')
D c_strstr 	PR	*	ExtProc('strstr')
D buf1	 		*	Value Options(*String)
D buf2 			*	Value Options(*String)

C_memcpy (LastPosPtr: X00: 1); //append X00

DelimiterPtr = C_strstr(BufferPtr:Delimiter21);

Well this is about it. Works only for x'0D'.

How does the formatting work, tried the RPG source but ..

Thanks

Posted by: bobcozzi
Site Admin ****
Chicagoland
Comment on: strstr()
Posted: 3 years 3 months 7 days 5 hours 50 minutes ago
Edited: Mon, 17 Feb, 2014 at 13:30:02 (1193 days ago)

You might want to adjust your strstr prototype first:

D** strstr          PR              *   extProc(*CWIDEN:'_C_strstr') 
D strstr          PR              *   extProc(*CWIDEN:'strstr') 
D  str1                           *   VALUE OPTIONS(*STRING:*TRIM) 
D  str2                           *   VALUE OPTIONS(*STRING:*TRIM) 

By including the *TRIM option, you don't have to screw with adding the null terminator when you call a C function requiring a string.

Next you might try reversing your LF/CR sequence as some files may have it in different sequences.

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 5 hours 30 minutes ago

Where can I find _C_strstr, compiler cannot find it.

I have seen the hex in debug, it shows '0D25'. So is it not right to search for it? 

Thanks

Posted by: tdaly
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 5 hours 15 minutes ago

Shouldn't

DelimiterPtr = C_strstr(BufferPtr:Delimiter21);

be

DelimiterPtr = C_strstr(Buffer:Delimiter21);

 

 

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 5 hours 5 minutes ago

 

Does it matter if it buffer is pointer, it points to a long message string from MQ? It works when searching for x'0D'.

Posted by: bobcozzi
Site Admin ****
Chicagoland
Comment on: strstr()
Posted: 3 years 3 months 7 days 5 hours 3 minutes ago

Sure you can have the 0D0A in the proper sequence. But use my prototype and Tom's suggestion. Also you are implying that you are on V5R4. If so, you need to include BNDDIR('QC2LE') on your header specification.

 

Posted by: DaleB
Premium member *
Reading, PA
Comment on: strstr()
Posted: 3 years 3 months 7 days 4 hours 50 minutes ago

As far as searching for one value over the other, depends on what's in your data. CRLF is x'0D25' EBCDIC, but x'0D0A' in ASCII.

Just curious, any particular reason you're trying to use C strstr() instead of %SCAN?

Oh, for formatting in this editor, try using Shift+Enter between your lines of code. You can also see the HTML using Tools > Source code.

Posted by: bobcozzi
Site Admin ****
Chicagoland
Comment on: strstr()
Posted: 3 years 3 months 7 days 4 hours 40 minutes ago

One more thing. In RPG if you have OPTIONS(*STRING) with a pointer passed by VALUE, RPG makes a copy of the data. I'm guessing that it never really works for you. But instead, you get lucky. In other words, you should EITHER pass the original character variable NOT a ptr to it, or you pass the ptr to it (for parm 1 of strstr) and then change the prototype so that you have "* VALUE" instead of "* VALUE OPTIONS(*STRING)" for the first parameter.

You're doing both which is producing unpredictable results.

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 4 hours 34 minutes ago

We are on V7R1 but compiler cannot find your _C_strstr.
The data is csv converted to ebcdic by MQ so it shows x'0D25' in debugger. 
The program works with pointers, I just copied it

Thanks, I'll try your  suggestions.

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 4 hours 26 minutes ago

I tried the QC2LE still not going through compilation. Definition not found for symbol '_C_strstr'. This is a SQLRPGLE, does that make a difference?

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 4 hours 4 minutes ago

 

I've gone through all the srvpgm in QC2LE, no _C_strstr to be found.

Posted by: bobcozzi
Site Admin ****
Chicagoland
Comment on: strstr()
Posted: 3 years 3 months 7 days 3 hours 32 minutes ago
Edited: Mon, 17 Feb, 2014 at 13:28:21 (1193 days ago)

Sorry, that _C_strstr is from my habbit of using the IFS inline functions. It should be 'strstr'.

If you set the *CWIDEN option on the EXTPROC and pass in the data, it should work.

Normally OPTIONS(*STRING:*TRIM) is all you need. You don't need to add a null as the compiler does that for you. If the S1 (first) parameter of strstr is a ptr, the compiler probably doesn't add the null and passes it directly. So the issue is probably a cobination of your prototype not being perfect, and adding the null. This code works on my V7R1 system.

     H BNDDIR('COZTOOLS/COZTOOLS') DFTACTGRP(*NO) 
     H  OPTION(*NODEBUGIO:*SRCSTMT)
      /include cozTools/qcpysrc,cprotos
      /include cozTools/qcpysrc,joblog

     D s1              S             32A   Inz('Hello World strstr')
     D s2              S              2A   Inz(X'0D25')
     D sPtr            S               *   inz(%addr(s1))
     D ptr             S               *
     D data            S             32A   based(ptr)
     C                   MOVE      *ON           *INLR
      /free
           s1 = %trimR(s1) + X'0D2500';  // Add CRLF and null to end of string.
           ptr = strstr(s1 : s2 );
          if (ptr = *NULL);
             joblog('strstr(%s:%s)=NULL' : %trimR(s1) : %trimR(s2));
          else;
             joblog('strstr(%s:%s)=%s' : %trimR(s1) : %trimR(s2) : data);
          endif;
           ptr = strstr(sptr : s2 );
          if (ptr = *NULL);
             joblog('strstr(%%addr(%s):%s)=NULL' : %trimR(s1) : %trimR(s2));
          else;
             joblog('strstr(%s:%s)=%s' : %trimR(s1) : %trimR(s2) : data);
          endif; 

 

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 7 days 3 hours 5 minutes ago

Thanks for all the information, new stuff for me

Posted by: mssunny
Premium member *
Comment on: strstr()
Posted: 3 years 3 months 6 days 11 hours ago

 

To update, there was RFH2 header data in the MQ msg which caused the strstr() failure. Without it there was no problem.

BTW. when I used the *trim in the prototype, got pointer arithmetic problem. We get the datalength inbetween 2 crlf by subtraction of pointers and get 'Space pointer operands do not point to the same space object'. Works ok without *trim.
Thanks again.