• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

Translating PB to C/C++

Started by Patrice Terrier, July 25, 2013, 12:23:52 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

LTRIM$() Unicode version:

wstring LTRIM$(IN wstring sBuf, IN wstring sChar) { // dllexport
    wstring sResult = sBuf;
    LONG_PTR nLength = sBuf.length();
    if (nLength && (sChar.length())) {
        //sChar = sChar.substr(0, 1);
        long K = 0;
        while (K < nLength) {
            // if (*sBuf.substr(K, 1).c_str() == *sChar.c_str()) {
            // This is the sChar ANY search version
            if (std::wstring::npos != sChar.find(sBuf.substr(K, 1))) {
                ++K; }
            else {
                break;
            }
        }
        sResult = sBuf.substr(K, nLength);
    }
    return sResult;
}
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

TRIM$() Unicode version:

wstring TRIM$(IN wstring sBuf, IN wstring sChar) {
    return LTRIM$(RTRIM$(sBuf, sChar), sChar);
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

PARSE$() Unicode version:

wstring PARSE$(IN wstring sMain, IN wstring sDelim, IN long nIndex) {
    wstring sResult = $NULL;
    long nLength = (long) sDelim.length();
    if (nLength == 0) { sDelim = L","; ++nLength; } // Use comma "," as default delimiter
    sMain = RTRIM$(sMain, sDelim); sMain += sDelim;
    if (sMain.length() && nLength) {
        LONG_PTR prev_pos = 0, pos = 0, nCount = 0;
        while( (pos = sMain.find(sDelim, pos)) != std::wstring::npos ) {
            wstring substring(sMain.substr(prev_pos, pos - prev_pos));
            ++nCount;
            if (nCount == nIndex) { sResult = substring; break; }
            prev_pos = ++pos;
        }
    }
    return sResult;
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

PARSECOUNT() Unicode version:

long PARSECOUNT(IN wstring MainString, IN wstring MatchString) {
    long count = 0;
    size_t pos = 0;
    while((pos = MainString.find(MatchString, pos)) != std::string::npos) {
         ++count; ++pos;
    }
    return count;
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

HEX$() Unicode version:

wstring HEX$(IN long nVal) { // dllexport
    WCHAR hex[33] = {0};
    _ltow_s(nVal, hex, 16); // Use base 16 for Hexadecimal.
    return CharUpper(hex);
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

STRING$() Unicode version:

wstring STRING$(IN long nCount, IN BYTE UseChar) {
    wstring sbuffer; sbuffer.assign(nCount, UseChar);
    return sbuffer;
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

GetTempPath() Unicode version:

Retrieve the current TMP/TEMP path.

WCHAR* TempPath () {
    static WCHAR buf[MAX_PATH];
    long nSize = GetTempPath(GetTempPath(NULL, NULL), &buf[0]);
    wstring sTempPath = RTRIM$((wstring) buf, $ANTI);
    sTempPath += $ANTI;
    memset(&buf[0], 0, sizeof(buf));
    CopyMemory(&buf[0], (WCHAR*) sTempPath.c_str(), sTempPath.length() * 2);
    return buf;
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

ExeName() Unicode version:

Retrieve the current EXE name.

static wchar_t  *$NULL = L"";

WCHAR* ExeName () {
    static WCHAR buf[MAX_PATH];
    if (GetModuleFileName(NULL, buf, MAX_PATH)) {
        return buf;}
    else {
        return $NULL;
    }
}

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#23
There is no built-in function to perform a SELECT CASE AS CONST$ in C/C++

Here is a replacement that would do it, using a hash function to turn the char string into a DWORD, in order to perform the switch/case as fast as possible.

The hash function:
DWORD hashStr(IN char* szText){
    DWORD hash = 0, nLen = (long) strlen(szText), K;
    if (nLen > 0) {
        for (K = 0; K < nLen; K++) {
            hash = (K * hash) + szText[K];
        }
    }
    return hash;
}

Note: You must insure that the hash function doesn't produce any collision.


and how to use it:
BOOL CALLBACK EnumChildProc(IN HWND hWnd, IN LPARAM lParam) {
    char zChildClass[64] = {0};

    if (GetClassNameA(hWnd, zChildClass, sizeof(zChildClass))) {

       CharUpperA(zChildClass);

       switch (hashStr(zChildClass)) {

       case 7925100: // "MDICLIENT"
            break;
       case 3961174590: // "TOOLBARWINDOW32"
            break;
       case 1881446725: // "MSCTLS_STATUSBAR32"
            break;
       case 25313: // "BUTTON"
            break;
       case 570326284: // "SYSTABCONTROL32"
            break;
       case 14743: // "#32770"
            break;
       case 26052: // "STATIC"
            break;
       case 3565744546: // "SYSTREEVIEW32"
            break;
       case 149782: // "LISTBOX"
            break;
       case 3878117282: // "MSCTLS_TRACKBAR32"
            break;
       case 2813312866: // "SYSLISTVIEW32"
            break;
       case 831093140: // "SYSHEADER32"
            break;
       case 1028461: // "RICHEDIT"
            break;
       case 1005323: // "COMBOBOX"
            break;
       case 1125: // "EDIT"
            break;
       case 876965674: // "REBARWINDOW32"
            break;
       case 991760690: // "MSCTLS_PROGRESS32"
            break;
       case 728101136: // "MSCTLS_UPDOWN32"
            break;
       case 78374326: // "ZIMAGECTRL"
            break;
       case 814530776: // "ZOPENGLCTRL"
            break;
       default:
            break;
       }
    }
    return TRUE;   // continue enumeration of children...
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Patrice,
  I am not a big fan of the c++ switch case so I am glad I don't have to work with it.
All Select Case in bc9Basic is translated to if statements.

This bc9Basic code

'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Select case test with stdstr
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPPHDR
$NOMAIN
$ONEXIT "GWGPP481.BAT $FILE$ -m32 con"

Function main() As int
    Raw As std::string s1 = "button"

    Select Case Ucase$(s1.c_str())
        Case "TOOLBARWINDOW32"
            Print "TOOLBARWINDOW32"
        Case "MSCTLS_STATUSBAR32"
            Print "MSCTLS_STATUSBAR32"
        Case "BUTTON"
            Print "BUTTON"
        Case Else
            Print "No Match"   
    End Select
    pause
End Function




Is translated to


int main (int argc,PCHAR* argv)
{
  g_argc= argc;
  g_argv= argv;
  std::string  s1="button";
  if(str_cmp(ucase(s1.c_str()),"TOOLBARWINDOW32")==0)
    {
      printf("%s\n","TOOLBARWINDOW32");
      goto L1000;
    }
  if(str_cmp(ucase(s1.c_str()),"MSCTLS_STATUSBAR32")==0)
    {
      printf("%s\n","MSCTLS_STATUSBAR32");
      goto L1000;
    }
  if(str_cmp(ucase(s1.c_str()),"BUTTON")==0)
    {
      printf("%s\n","BUTTON");
    }
  else // case else
    {
      printf("%s\n","No Match");
    }
L1000:;
  Pause();
  return 0;
}


James

Patrice Terrier

James;

In case of many IF statement, that is very hard to read and maintain.

Swicth case is highly optimized, and no need to check for each conditions first.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Quote from: Patrice Terrier on September 11, 2013, 07:53:52 PM
James;

In case of many IF statement, that is very hard to read and maintain.

Swicth case is highly optimized, and no need to check for each conditions first.

...

I agree but I don't have to deal with it . Let the translator do it's work! :)

The switch case may be highly optimized, but as you have found, it has more limitations than the standard "BASIC" implementation.

I do appreciate you sharing so please don't hesitate to post as many conversions as you can. My C++ is abysmal so don't take anything I post too seriously :)

James
 



Patrice Terrier

#27
James,

From what i can see, the code translation in your example is really not optimized.
It does the ucase(s1.c_str()) in each of the IF, instead of doing it only once.

For me it is clear that no translator could come close to hand crafted code :)
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Well that's my fault in not optimizing it in the first place and not calling ucase in the select statement.
As long as I don't have to deal with all the c++ braces and semi colons :) I'll live with a little less optimization.
But when it's needed I can use straight c++ or assembler.

James


Daniel Corbier

I'm glad I'm not the only person who wants to convert PowerBASIC source code to C++.  I created a tool named uCalc Transform that is specifically designed to help translate source code (among other uses).  This is what I intend to use to make my PB-written software available on other platforms (Android, Mac OS, Linux, etc), and also to create a 64-bit version of my uCalc Fast Math Parser DLL.  I already use it to auto-generate the headers for Delphi, C#, Visual Basic.NET, VB6, and various flavors of C++, taking PB source code as input.

I started an Open Source PB to C++ project.  Please join me to help complete the project.  Visit:

https://github.com/uCalc/powerbasic-to-cpp
Daniel Corbier
uCalc Software