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.
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.
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?
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
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.
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
Shouldn't
DelimiterPtr = C_strstr(BufferPtr:Delimiter21);
be
DelimiterPtr = C_strstr(Buffer:Delimiter21);
Does it matter if it buffer is pointer, it points to a long message string from MQ? It works when searching for x'0D'.
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.
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.
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.
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.
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?
I've gone through all the srvpgm in QC2LE, no _C_strstr to be found.
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;
Thanks for all the information, new stuff for me
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.