const char* issue??

Started by jcfuller, February 09, 2020, 02:37:25 PM

Previous topic - Next topic

jcfuller


This appears to be a const char* issue


'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'my bcx.ini has the iMatch macros
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPP
$NOMAIN
$ONEXIT "VSCPP.BAT $FILE$ -m64 con "

$HEADER
    #define overloaded
    #include <iostream>
    #include <string>
    typedef std::string stdstr;
$HEADER


Function main()
    Raw As stdstr s1
    s1 = "$IFUSE USE_CScrollWindow"
    'If LEFTSTR(s1.c_str(),"$IFUSE") Then
    '    std::cout << "LEFTSTR" << std::endl
    'End If
    'If Left$(s1.c_str(),6) = "$IFUSE" Then
    '    std::cout << "Left$" << std::endl
    'End If
    If iMatchLft(s1.c_str(),"$IFUSE") Then
        std::cout << "iMatchLft" << std::endl
    End If
    Pause
End Function


My bcx.ini

'***********************
'  Bracket Handling
'***********************

CONST c_SglQt = 39
CONST c_DblQt = 34
CONST c_LPar  = 40
CONST c_RPar  = 41
CONST c_Komma = 44
CONST c_LtBkt = 91
CONST c_RtBkt = 93


CONST iMatchLft(A,B) = iMatch(A,B,0)
CONST iMatchWrd(A,B) = iMatch(A,B,1)
CONST iMatchRgt(A,B) = iMatch(A,B,2)




FUNCTION iMatch(Arg As const char Ptr, MatchStr As const char Ptr, mt)

  IF mt = 2 THEN
    DIM RAW L1, L2
    L1 = LEN(Arg$) : L2 = LEN(MatchStr$)
    IF L1 < L2 THEN FUNCTION = FALSE
    Arg = (Arg + L1) - L2
  END IF

  WHILE *MatchStr
    'If we run out string to match against then return no match
    IF *Arg = 0 THEN FUNCTION = FALSE
    'bit ORing a character with 0x20 produces the lower case of it
    IF (*Arg BOR 32) <> (*MatchStr BOR 32) THEN FUNCTION = FALSE
    INCR Arg
    INCR MatchStr
  WEND
  IF mt AND *Arg <> 0 THEN FUNCTION = FALSE
  FUNCTION = TRUE
END FUNCTION

'==============================================================================

'------------------------------------------------------------------------------
FUNCTION iMatchNQ(Arg As const char Ptr, MatchStr As const char Ptr)
  Dim As Int mi
  DIM AS PCHAR  a = (char Ptr)Arg


  WHILE MatchStr[mi]
    IF *a = c_DblQt THEN
      mi=0
      WHILE *(++a) <> c_DblQt
        IF *a = 0 THEN FUNCTION = 0
      WEND
    END IF

    IF a[mi] = 0 THEN FUNCTION = 0
    'If we run out string to match against then return no match
    'bit ORing a character with 0x20 produces the lower case of it
    IF (a[mi] BOR 32) <> (MatchStr[mi] BOR 32) THEN
      INCR a : mi= -1
    END IF
    INCR mi
  WEND
  FUNCTION = (a-Arg) + 1  ' We have a match
END FUNCTION




MrBcx

You ini file has "const char" in it ... how is this a BCX bug?

FUNCTION iMatchNQ(Arg As const char Ptr, MatchStr As const char Ptr)

Robert

Quote from: jcfuller on February 09, 2020, 02:37:25 PM

This appears to be a const char* issue


'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'my bcx.ini has the iMatch macros
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPP
$NOMAIN
$ONEXIT "VSCPP.BAT $FILE$ -m64 con "

$HEADER
    #define overloaded
    #include <iostream>
    #include <string>
    typedef std::string stdstr;
$HEADER


Function main()
    Raw As stdstr s1
    s1 = "$IFUSE USE_CScrollWindow"
    'If LEFTSTR(s1.c_str(),"$IFUSE") Then
    '    std::cout << "LEFTSTR" << std::endl
    'End If
    'If Left$(s1.c_str(),6) = "$IFUSE" Then
    '    std::cout << "Left$" << std::endl
    'End If
    If iMatchLft(s1.c_str(),"$IFUSE") Then
        std::cout << "iMatchLft" << std::endl
    End If
    Pause
End Function


My bcx.ini

'***********************
'  Bracket Handling
'***********************

CONST c_SglQt = 39
CONST c_DblQt = 34
CONST c_LPar  = 40
CONST c_RPar  = 41
CONST c_Komma = 44
CONST c_LtBkt = 91
CONST c_RtBkt = 93


CONST iMatchLft(A,B) = iMatch(A,B,0)
CONST iMatchWrd(A,B) = iMatch(A,B,1)
CONST iMatchRgt(A,B) = iMatch(A,B,2)




FUNCTION iMatch(Arg As const char Ptr, MatchStr As const char Ptr, mt)

  IF mt = 2 THEN
    DIM RAW L1, L2
    L1 = LEN(Arg$) : L2 = LEN(MatchStr$)
    IF L1 < L2 THEN FUNCTION = FALSE
    Arg = (Arg + L1) - L2
  END IF

  WHILE *MatchStr
    'If we run out string to match against then return no match
    IF *Arg = 0 THEN FUNCTION = FALSE
    'bit ORing a character with 0x20 produces the lower case of it
    IF (*Arg BOR 32) <> (*MatchStr BOR 32) THEN FUNCTION = FALSE
    INCR Arg
    INCR MatchStr
  WEND
  IF mt AND *Arg <> 0 THEN FUNCTION = FALSE
  FUNCTION = TRUE
END FUNCTION

'==============================================================================

'------------------------------------------------------------------------------
FUNCTION iMatchNQ(Arg As const char Ptr, MatchStr As const char Ptr)
  Dim As Int mi
  DIM AS PCHAR  a = (char Ptr)Arg


  WHILE MatchStr[mi]
    IF *a = c_DblQt THEN
      mi=0
      WHILE *(++a) <> c_DblQt
        IF *a = 0 THEN FUNCTION = 0
      WEND
    END IF

    IF a[mi] = 0 THEN FUNCTION = 0
    'If we run out string to match against then return no match
    'bit ORing a character with 0x20 produces the lower case of it
    IF (a[mi] BOR 32) <> (MatchStr[mi] BOR 32) THEN
      INCR a : mi= -1
    END IF
    INCR mi
  WEND
  FUNCTION = (a-Arg) + 1  ' We have a match
END FUNCTION





Hi James:

What's the problem? Please specify BCX translator version and compiler version.


Compiles without a problem here. My batch file. 64 bit.  BCX 7.4.4, VS 2019.

jcfuller

#3
It is the lines that are commented that error not the iMatchLf

Bcx 7.4.4 vs2019 and nuwen

James


Robert

Quote from: jcfuller on February 09, 2020, 04:01:08 PM
It is the lines that are commented that error not the iMatchLf

Bcx 7.4.4 vs2019 and nuwen

James

What would be useful to solve this problem would be a list of places in BCX where char* could be changed to const char* wilthout ill effects. Then there might be a possibility of change.

In defense of your position, in many of the string functions in Pelle's C, const char * is used as parameter data type, for example



char * strrchr(const char *string, int c);
char * strstr(const char *string1, const char *string2);
int strcmp(const char *string1, const char *string2);
char * _strrichr(const char *string, int c);



where the passed string is amended, char * is used



char * _strrev(char * string);
char * strcat(char * restrict dst, const char * restrict src);
char * strcpy(char * restrict dst, const char * restrict src);
char * strtok(char * restrict string1, const char * restrict string2);




jcfuller

Robert,
  What functions that take a char* actually change it? I think they are few and far between??

James


jcfuller

Robert/Kevin,
  If we had a list of those functions/Subs that did not change the passed (abcd$) char* abcd we could $ONEXIT (for now could be added to bcx later) a FixCppChars.exe utility to change the char* to const char* before compile.
Feasible?

James

jcfuller

Another idea?
Function test(s$) As Integer -> char* s
Function test(s$$) As Integer -> const char* s

James

Robert

Quote from: jcfuller on February 10, 2020, 06:22:21 AM
Robert/Kevin,
  If we had a list of those functions/Subs that did not change the passed (abcd$) char* abcd we could $ONEXIT (for now could be added to bcx later) a FixCppChars.exe utility to change the char* to const char* before compile.
Feasible?

James

This too Gyro Gearloose-ish for me. I would prefer the functions should be adjusted. Most of the BCX string functions were written with LCC-Win32 as the compiler and it really didn't care in the early days what data type was being passed. And there was no concern whatsoever about C++.

What I really have been concerned about can be seen in your source code for BC9 Afx. For example, in the LEFT$ function you have changed the parameter data type to const char * and the inside the function you cast the related arguments to char *. Really James! W.T.F. are you doing there?

I absolutely do not want to patch up code in that manner because it is found later that it doesn't work correctly. I think a good guide would be Pelle's C use on const char * in the parameters of string functions. This will take some time and care to get right.

Robert

Quote from: jcfuller on February 10, 2020, 04:07:47 AM
Robert,
  What functions that take a char* actually change it? I think they are few and far between??

James

Open up the Pelle's C string.h header and see which functions take char * or const char * parameters and go from there.

jcfuller

Robert,
  I admit I'm a horrid c/c++ coder but I'm confused on your comment on my Left$.
Both bc9 and Bcx have the same code except for the const in the function ().
Taking your advice and looking a the PellesC string.h it has:
extern size_t __cdecl strlen(const char *);
Bcx passes a char* but bc9 passes a const char*
???
James

Robert

#11
Quote from: jcfuller on February 10, 2020, 11:08:17 AM
Robert,
  I admit I'm a horrid c/c++ coder but I'm confused on your comment on my Left$.
Both bc9 and Bcx have the same code except for the const in the function ().
Taking your advice and looking a the PellesC string.h it has:
extern size_t __cdecl strlen(const char *);
Bcx passes a char* but bc9 passes a const char*
???
James

Hi James:

I do not think you are a horrid coder. You are very talented. In the instances below you made a choice to modify your code to avoid a warning

The potential problems that I am concerned about and said there were examples in BC9 were not with LEFT$ but with REMAIN, EXTRACT, INSTR. For example here's your INSTR$

    FPRINT FP_WRITE,"int instr(const char* mane,const char* match,int offset,int sensflag)"
    FPRINT FP_WRITE,"{"
    FPRINT FP_WRITE,"  register char *s;"
    FPRINT FP_WRITE,"  if (!mane || !match || ! *match || offset>(int)strlen(mane)) return 0;"
    FPRINT FP_WRITE,"  if (sensflag)"
    FPRINT FP_WRITE,"    s = _stristr_(offset>0 ? (char*)mane+offset-1 : (char*)mane,(char*)match);"
    FPRINT FP_WRITE,"  else"
    FPRINT FP_WRITE,"    s = _strstr_(offset>0 ? (char*)mane+offset-1 : (char*)mane,(char*)match);"
    FPRINT FP_WRITE,"  return s ? (int)(s-mane)+1 : 0;"

Here's the BCX INSTR$

    FPRINT FP_WRITE, "int instr(char* mane,char* match,int offset,int sensflag)"
    FPRINT FP_WRITE, "{"
    FPRINT FP_WRITE, "  char *s;"
    FPRINT FP_WRITE, "  if (!mane || !match || ! *match || offset>(int)strlen(mane)) return 0;"
    FPRINT FP_WRITE, "  if (sensflag)"
    FPRINT FP_WRITE, "    s = _stristr_(offset>0 ? mane+offset-1 : mane,match);"
    FPRINT FP_WRITE, "  else"
    FPRINT FP_WRITE, "    s = _strstr_(offset>0 ? mane+offset-1 : mane,match);"
    FPRINT FP_WRITE, "  return s ? (int)(s-mane)+1 : 0;"

As I said earlier, I absolutely do not want to patch up code in that manner, that is applying casts, because it is found later that it doesn't work correctly because of the change to const char *.

jcfuller

Robert,
  Aha!:)
I just went through the SUB_RunTimeFunctions.bas file that Kevin uploaded and noted the only functions with char* that changed the char* parameter were _stristr_ and _strstr_.
Didn't check close enough that some of the the others called those.

Am I right in assuming with this case there is no way to make them c++ friendly the way they are written.
I don't think I ever tried instr on a literal before but I just did with bcx and all was fine.

I care about the runtime functions compiling with out warnings using VC++ if the level is set higher that /W1
Is it even possible?
James

MrBcx

Quote from: Robert on February 10, 2020, 10:22:19 AM

What I really have been concerned about can be seen in your source code for BC9 Afx. For example, in the LEFT$ function you have changed the parameter data type to const char * and the inside the function you cast the related arguments to char *. Really James!  W.T.F. are you doing there?

I absolutely do not want to patch up code in that manner because it is found later that it doesn't work correctly. I think a good guide would be Pelle's C use on const char * in the parameters of string functions. This will take some time and care to get right.

And the congregation says, "AMEN"

James - I don't understand why you're even bothering with BCX when BC9 and C++ are clearly your focus. 
Maybe I'm missing something obvious.




Robert

Quote from: jcfuller on February 10, 2020, 02:46:26 PM
Robert,
  Aha!:)
I just went through the SUB_RunTimeFunctions.bas file that Kevin uploaded and noted the only functions with char* that changed the char* parameter were _stristr_ and _strstr_.
Didn't check close enough that some of the the others called those.

Am I right in assuming with this case there is no way to make them c++ friendly the way they are written.
I don't think I ever tried instr on a literal before but I just did with bcx and all was fine.

I care about the runtime functions compiling with out warnings using VC++ if the level is set higher that /W1
Is it even possible?
James

Hi James:

Possible? I don't know. Cast YOUR C++ literals to char *?

The BASIC problem, fundamentally unsolvable but like almost everything kludgable, is that

C String literals are char *. For details see here

https://docs.microsoft.com/en-us/cpp/c-language/c-string-literals?view=vs-2019

and C++ String Literals are const char * and many variants BUT all are const. For details see here

https://docs.microsoft.com/en-us/cpp/cpp/string-and-character-literals-cpp?view=vs-2019#narrow-string-literals

The C++ doc is well worth reading. It's got details on all the new stuff.