A Repair of WITH ... END WITH

Started by Robert, November 23, 2019, 12:19:18 AM

Previous topic - Next topic

Robert

On August 1, 2012, MrBCX reported a bug regarding WITH ... END WITH as follows

Quote

Message 42981

Bug Report 6.9.1

mrbcx Aug 1, 2012
Greetings friends ...

First off, let me say that I mean no offense to anyone and that the following is simply my narrow-minded opinion.

I continue to only use BCX 6.2.2 for all my projects because it's the only version that I trust. And the reason why I trust it is because I believe it has been more rigorously tested than any version since. I have no need for new features when those come at the cost of destabilizing a previously stable program.

Seeing the recent uptick of chatter tempted me to test 6.9.1 on some of my projects. I didn't get very far. The very first project I tested resulted in a number of errors with 6.9.1

My bug report:

The BASIC code below, translated with 6.2.2 results in the correct "C" output, listed just below the BASIC code. At the bottom of this post is the messed up "C" output produced by 6.9.1


SUB getImage(pic AS HBITMAP, img AS IMAGE PTR)
LOCAL hDC AS HDC
LOCAL bm AS BITMAP
GetObject(pic, SIZEOF(BITMAP), &bm)
WITH img->bmi.bmiHeader
.biBitCount = 32
.biCompression = BI_RGB
.biPlanes = 1
.biSize = SIZEOF(BITMAPINFO)
.biWidth = bm.bmWidth
.biHeight = bm.bmHeight
END WITH
img->width = bm.bmWidth
img->height = bm.bmHeight
img->bufLen = bm.bmWidth*bm.bmHeight*4
img->buf = calloc(img->bufLen,1);
hDC = CreateCompatibleDC(NULL)
SelectObject(hDC, pic)
GetDIBits(hDC, pic, 0, img->height, img->buf, &img->bmi,DIB_RGB_COLORS)
DeleteObject(pic)
DeleteDC(hDC)
END SUB


=========================================
Correctly generated code from BCX 6.2.2+
=========================================

void getImage (HBITMAP pic, IMAGE* img)
{
static HDC hDC;
memset(&hDC,0,sizeof(hDC));
static BITMAP bm;
memset(&bm,0,sizeof(bm));
GetObject(pic,sizeof(BITMAP), &bm);
img->bmi.bmiHeader.biBitCount=32;
img->bmi.bmiHeader.biCompression=BI_RGB;
img->bmi.bmiHeader.biPlanes=1;
img->bmi.bmiHeader.biSize=sizeof(BITMAPINFO);
img->bmi.bmiHeader.biWidth=bm.bmWidth;
img->bmi.bmiHeader.biHeight=bm.bmHeight;
img->width=bm.bmWidth;
img->height=bm.bmHeight;
img->bufLen=bm.bmWidth*bm.bmHeight*4;
img->buf=calloc(img->bufLen,1);;
hDC=CreateCompatibleDC(NULL);
SelectObject(hDC,pic);
GetDIBits(hDC,pic,0,img->height,img->buf, &img->bmi,DIB_RGB_COLORS);
DeleteObject(pic);
DeleteDC(hDC);
}


===================================
Flawed code generated using 6.9.1
===================================


void getImage (HBITMAP pic,IMAGE* img)
{
static HDC hDC;
memset(&hDC,0,sizeof(hDC));
static BITMAP bm;
memset(&bm,0,sizeof(bm));
GetObject(pic,sizeof(BITMAP), &bm);
img->bmi.bmiHeader.biBitCount= 32;
img->bmi.bmiHeader.biCompression= BI_RGB;
img->bmi.bmiHeader.biPlanes= 1;
img->bmi.bmiHeader.biSize= sizeof( BITMAPINFO);

img->bmi.bmiHeader.biWidth= bm img->bmi.bmiHeader.bmWidth;
img->bmi.bmiHeader.biHeight= bm img->bmi.bmiHeader.bmHeight;


These 2 lines are an utter mess! ^^^^^^^^^^^^^^^^^^^^^^^^^^^


img->width= bm.bmWidth;
img->height= bm.bmHeight;
img->bufLen= bm.bmWidth* bm.bmHeight* 4;
img->buf= calloc( img->bufLen, 1);;
hDC= CreateCompatibleDC( NULL);
SelectObject(hDC,pic);
GetDIBits(hDC,pic,0,img->height,img->buf, &img->bmi,DIB_RGB_COLORS);
DeleteObject(pic);
DeleteDC(hDC);
}


Based on suggestions from J.C. Fuller, my repair for this problem is to replace lines 10687 through 10738 in BCX733.bas with



  IF PrependCnt THEN
    i = PrependCnt
    WHILE i
      IF NOT iMatchWrd(Stk$[1],"with") AND NOT iMatchWrd(Stk$[1],"prepend") AND NOT iMatchWrd(Stk$[1],"endwith") AND NOT iMatchWrd(Stk$[1],"endprepend") THEN
        CALL InsertTokens(0,1,PrependVar$[i])
      END IF
      i--
    WEND
  END IF

  IF WithCnt THEN
i = WithCnt
    WHILE i
      IF NOT iMatchWrd(Stk$[1],"with") AND NOT iMatchWrd(Stk$[1],"prepend") AND NOT iMatchWrd(Stk$[1],"endwith") AND NOT iMatchWrd(Stk$[1],"endprepend") THEN
        CALL InsertTokens(0,1,WithVar$[i])
      END IF
      i--
    WEND
  END IF

  IF PrependCnt THEN
    CALL BuildDelimStr(1,Ndx, Src$)
    CALL XParse(Src$)
  END IF

  IF WithCnt THEN
    CALL BuildDelimStr(1,Ndx, Src$)
    CALL XParse(Src$)
  END IF



Ian Casey (RIP)

Hi Robert,
Glad to see you here.

I did make the changes you suggested to my copy, the 2 lines with memset were missing, the rest of the output of BCX looked identical to what was wanted. I did try to add the memset lines and recompile but still got many errors.
PellesC 9.00 I tried 64 bit and 32 bit no difference.
At least it gives the translation required minus the memset lines.

Ian


MrBcx

#2
I have been working most of the day on a forthcoming version  7.3.4. 

Besides Roberts fix, I've worked on a few other things.

A zip file and announcement will be provided but I'm not there yet.

I will say that most of the regression testing today is shaking out well.

Kevin

ps:  One of the things I wasted time on today was TRYING to update our OSVERSION() function to report Win10 & Server 16
       Besides requiring a specific manifest, Microsoft requires some info that appears to only be in the Win10 SDK and unavailable
       more broadly.  Leave it to MS to make the easy, hard and the hard, impossible.  If anyone feels adventurous enough to try
       where I failed to update the OSVersion() function, I will put you in for a special recognition award.


Robert

Quote from: iancasey on November 23, 2019, 05:14:02 PM
Hi Robert,
Glad to see you here.

I did make the changes you suggested to my copy, the 2 lines with memset were missing, the rest of the output of BCX looked identical to what was wanted. I did try to add the memset lines and recompile but still got many errors.
PellesC 9.00 I tried 64 bit and 32 bit no difference.
At least it gives the translation required minus the memset lines.

Ian

Hi Ian:

MrBCX's original snippet is not a complete program so on a compile many errors will occur.

Recent versions of BCX do not use memset to initialize declared variables to zero so the memset lines will be missing.

The parsing problem that was the origin of the bug report is no longer there.

This is what I get with the repair made.


void getImage (HBITMAP pic,IMAGE* img)
{
  HDC      hDC={0};
  BITMAP   bm={0};
  GetObject(pic,sizeof(BITMAP), &bm);
  img->bmi.bmiHeader.biBitCount  = 32;
  img->bmi.bmiHeader.biCompression  = BI_RGB;
  img->bmi.bmiHeader.biPlanes  = 1;
  img->bmi.bmiHeader.biSize  = sizeof( BITMAPINFO);
  img->bmi.bmiHeader.biWidth= bm.bmWidth;
  img->bmi.bmiHeader.biHeight= bm.bmHeight;
  img->width= bm.bmWidth;
  img->height= bm.bmHeight;
  img->bufLen= bm.bmWidth* bm.bmHeight* 4;
  img->buf= calloc( img->bufLen, 1);;
  hDC= CreateCompatibleDC( NULL);
  SelectObject(hDC,pic);
  GetDIBits(hDC,pic,0,img->height,img->buf, &img->bmi,DIB_RGB_COLORS);
  DeleteObject(pic);
  DeleteDC(hDC);
}


Side effects? I don't know. If the repair is added to BCX then we may find out, maybe, if it is a complete repair. If not, you know, it WILL blow up.

Jeff

Kevin,

I put this together about a year ago to reliably detect Win10.  It ain't pretty, but it works (for me).  Hope it helps.

TYPE REALOSVERSIONINFO
  MajorVersion
  MinorVersion
END TYPE

FUNCTION GetRealOSVersionInfo() AS REALOSVERSIONINFO
  !NTSTATUS (WINAPI *RtlGetVersion)(LPOSVERSIONINFOEX);
  DIM rosvi AS REALOSVERSIONINFO
  DIM osvi AS OSVERSIONINFO
  DIM osviex AS OSVERSIONINFOEX

  osvi.dwOSVersionInfoSize = sizeof(osvi)
  GetVersionEx(&osvi)

  IF osvi.dwMajorVersion >= 6 THEN
    !*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandle("ntdll"), "RtlGetVersion");
    IF RtlGetVersion THEN
      osviex.dwOSVersionInfoSize = sizeof(osviex)
      RtlGetVersion(&osviex)
    END IF
    rosvi.MajorVersion = osviex.dwMajorVersion
    rosvi.MinorVersion = osviex.dwMinorVersion
  ELSE
    rosvi.MajorVersion = osvi.dwMajorVersion
    rosvi.MinorVersion = osvi.dwMinorVersion
  END IF

  FUNCTION = rosvi 
END FUNCTION

FUNCTION Win10OrNewer() AS BOOL
  DIM bRet AS BOOL
  DIM rosvi AS REALOSVERSIONINFO
 
  bRet = FALSE
  rosvi = GetRealOSVersionInfo()
  IF rosvi.MajorVersion >= 10 THEN
    bRet = TRUE
  END IF
 
  FUNCTION = bRet
END FUNCTION


Jeff

Quote from: MrBcx on November 23, 2019, 07:04:32 PM

ps:  One of the things I wasted time on today was TRYING to update our OSVERSION() function to report Win10 & Server 16
       Besides requiring a specific manifest, Microsoft requires some info that appears to only be in the Win10 SDK and unavailable
       more broadly.  Leave it to MS to make the easy, hard and the hard, impossible.  If anyone feels adventurous enough to try
       where I failed to update the OSVersion() function, I will put you in for a special recognition award.

MrBcx

That's pretty clever Jeff ... now I want to know what other tricks you have up your sleeve :-)

MrBcx

Here is a shorter, consolidated version of Jeff's Windows 10 detection function.



FUNCTION Win10OrNewer() AS BOOL
  DIM osvi AS OSVERSIONINFO
  DIM osviex AS OSVERSIONINFOEX
  DIM dwMaj  AS DWORD
! NTSTATUS (WINAPI *RtlGetVersion)(LPOSVERSIONINFOEX);
  osvi.dwOSVersionInfoSize = SIZEOF(osvi)
  GetVersionEx(&osvi)
  IF osvi.dwMajorVersion >= 6 THEN
      !*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandle("ntdll"), "RtlGetVersion");
    IF RtlGetVersion THEN
      osviex.dwOSVersionInfoSize = SIZEOF(osviex)
      RtlGetVersion(&osviex)
    END IF
    dwMaj = osviex.dwMajorVersion
  ELSE
    dwMaj = osvi.dwMajorVersion
  END IF
  IF dwMaj >= 10  THEN
    FUNCTION = TRUE
  END IF
END FUNCTION

Michael Henning

Just started testing 7.34...I too have been using 6.0 and older. Just got 100 + errors with 7.34 and Pelles c compiling BcxIde.
Still sifting through but the following stuck out.

The following WITH fails badly:

SUB SaveViewState()
   DIM RAW buffer$

   WITH ViewState
      buffer$ = _
      STR$(.lines)   + "," + STR$(.folds)   + "," + _
      STR$(.markers) + "," + STR$(.indents) + "," + _
      STR$(.endline) + "," + STR$(.showspace) + "," + _
      STR$(.navwin) + "," + STR$(.outwin)
   END WITH

   WriteIniString("DEFAULTS", "ViewState", buffer$ )
END SUB

7.34 Output:
  strcpy(ViewStatebuffer, join(15,str(.lines),",",str(.folds),",",str(.markers),",",str(.indents),",",str(.endline),",",str(.showspace),",",str(.navwin),",",str(.outwin)));

6.00 Output:
  strcpy(buffer, join(15,str(ViewState.lines),",",str(ViewState.folds),",",str(ViewState.markers),",",str(ViewState.indents),",",str(ViewState.endline),",",str(ViewState.showspace),",",str(ViewState.navwin),",",str(ViewState.outwin)));


MrBcx

Mike,

I have spent some time trying to compile BCXIDE this morning.  Still a long ways off ...

I will say that the error check function that I posted on the forum found several "EXIT" statements with erroneous or missing pair statements.

If you apply that function as shown in my post, that will help track those down.

I've also found coding errors in your BASIC sources by looking at the Pelles' errors ... for example, an argument to a function was
coded as ID_Fram           e2   (should be ID_Frame2)  ... it's becoming clear that both earlier and later
versions of BCX have their share of troublesome permissive behavior. 

The "WITH/END WITH" is supremely FUBAR ... look at the output from SUB GoFwdBk (direction)


void GoFwdBk (int direction)
{
  int     temp2=SDI[CurDoc].HistIdx;
  SDI[CurDoc]if direction THEN;
  SDI[CurDoc]if++temp2>(MAXLINEHISTORY-1)||.LineHist[temp2]                  =- 1 THEN;
  SDI[CurDoc]temp2   = 0;
  SDI[CurDoc]endif;
  SDI[CurDoc]else;
  SDI[CurDoc]if--temp2<0 THEN;
  SDI[CurDoc]FORtemp2    =( MAXLINEHISTORY- 1) TO 0 STEP- 1;
  SDI[CurDoc]if.LineHist[temp2]        =- 1 THEN;
  SDI[CurDoc]exit FOR;
  SDI[CurDoc]endif;
  SDI[CurDoc]next temp2;
  SDI[CurDoc]endif;
  SDI[CurDoc]endif;
  SDI[CurDoc]if .LineHist[temp2]>-1 THEN;
  SDI[CurDoc].HistIdx   = temp2;
  SDI[CurDoc]GotoLineAndCenter(.LineHist[temp2],0,FALSE);
  SDI[CurDoc]endif;


This is disappointing and I don't know how much I can contribute to unraveling the labyrinth of  source code
that generated it.

MrBcx

Quote from: MrBcx on November 26, 2019, 11:51:26 AM

I have spent some time trying to compile BCXIDE this morning.  Still a long ways off ...


Blocking out all the "WITH/END WITH" usage and a handful of minor changes allowed me complete the compile with Pelles.

Mind you, the program does NOT run -- it doesn't even start up -- a Windows alert pops up stating Entry Point not found.

Not quite light at the end of the tunnel but at least we know there is a tunnel and that we're gonna need a bigger light.


Michael Henning

QuoteBlocking out all the "WITH/END WITH" usage and a handful of minor changes allowed me complete the compile with Pelles.

Mind you, the program does NOT run -- it doesn't even start up -- a Windows alert pops up stating Entry Point not found.

Not quite light at the end of the tunnel but at least we know there is a tunnel and that we're gonna need a bigger light.

Thanks Kevin. I've made several changes since the last release. So I'm guessing i probably fixed the syntax errors already. I know the change in variable handling had caused issues. A lot of the auto variables were really messed up. I went through and manually changed most. I'll take another stab tonight. Working 3rd shift for a coworker this week..

MrBcx

#11
Mike - I have an update

I got BCXIDE to compile and run CORRECTLY using 7.3.3

(1) I fixed the small handful of typos 
(2) I used Bcx 7.3.3 to translate
(3) I modified the build.bat to tell Pellesc to use the CRTMT.Lib for the thread functions

bc bcxide
pw bcxide crtmt.lib



(Open the attached gif in your browser to see it all in action)

MrBcx

Quote from: Robert on November 23, 2019, 12:19:18 AM

Based on suggestions from J.C. Fuller, my repair for this problem is to replace lines 10687 through 10738 in BCX733.bas with


The great irony here is that I just successfully compiled my ScreenShotGrabber program using 7.3.3!

This so-called "WITH/END WITH"  FIX  has spilled more unnecessary blood than I care to think about.


Michael Henning

Hey, that's a good start.

QuoteI've also found coding errors in your BASIC sources by looking at the Pelles' errors ... for example, an argument to a function was
coded as ID_Fram           e2   (should be ID_Frame2)  ... it's becoming clear that both earlier and later
versions of BCX have their share of troublesome permissive behavior

This was only syntax error i found still in my copy but bcx 6.0 removed the extroneus spaces so it never complained.
7.34 still jumbles dim autos. Didn't try 7.33

Robert

Quote from: MrBcx on November 26, 2019, 07:52:56 PM
Quote from: Robert on November 23, 2019, 12:19:18 AM

Based on suggestions from J.C. Fuller, my repair for this problem is to replace lines 10687 through 10738 in BCX733.bas with


The great irony here is that I just successfully compiled my ScreenShotGrabber program using 7.3.3!

This so-called "WITH/END WITH"  FIX  has spilled more unnecessary blood than I care to think about.

Hi Kevin:

My apologies for the lack of diligence in comprehensive testing of the "so-called WITH/END WITH  FIX", which was provided in good faith, and I am truly sorry for wasting your time, but, having said that, I would like to reiterate that after translating, even with BCX733, lines 523 to 544 of your ScreenGrabber Raster_Operations.bas module, that is,



SUB getImage(pic AS HBITMAP, img AS IMAGE PTR)
  LOCAL hDC AS HDC
  LOCAL bm AS BITMAP
  GetObject(pic, SIZEOF(BITMAP), &bm)
  WITH img->bmi.bmiHeader
  .biBitCount = 32
  .biCompression = BI_RGB
  .biPlanes = 1
  .biSize = SIZEOF(BITMAPINFO)
  .biWidth = bm.bmWidth
  .biHeight = bm.bmHeight
END WITH
img->width = bm.bmWidth
img->height = bm.bmHeight
img->bufLen = bm.bmWidth*bm.bmHeight*4
img->buf = calloc(img->bufLen,1);
hDC = CreateCompatibleDC(NULL)
SelectObject(hDC, pic)
GetDIBits(hDC, pic, 0, img->height, img->buf, &img->bmi,DIB_RGB_COLORS)
DeleteObject(pic)
DeleteDC(hDC)
END SUB



the output is still the same buggy code that you were complaining about in the first place.



void getImage (HBITMAP pic,IMAGE* img)
{
  HDC      hDC={0};
  BITMAP   bm={0};
  GetObject(pic,sizeof(BITMAP), &bm);
  img->bmi.bmiHeader.biBitCount= 32;
  img->bmi.bmiHeader.biCompression= BI_RGB;
  img->bmi.bmiHeader.biPlanes= 1;
  img->bmi.bmiHeader.biSize= sizeof( BITMAPINFO);
  img->bmi.bmiHeader.biWidth= bm img->bmi.bmiHeader.bmWidth;
  img->bmi.bmiHeader.biHeight= bm img->bmi.bmiHeader.bmHeight;
  img->width= bm.bmWidth;
  img->height= bm.bmHeight;
  img->bufLen= bm.bmWidth* bm.bmHeight* 4;
  img->buf= calloc( img->bufLen, 1);;
  hDC= CreateCompatibleDC( NULL);
  SelectObject(hDC,pic);
  GetDIBits(hDC,pic,0,img->height,img->buf, &img->bmi,DIB_RGB_COLORS);
  DeleteObject(pic);
  DeleteDC(hDC);
}



and trying to compile the C code output Grab.c with Pelle's C Version 9.0 issues these errors



grab.c(2982): error #2088: Lvalue required.
grab.c(3013): error #2088: Lvalue required.
grab.c(3014): error #2088: Lvalue required.
grab.c(3029): error #2168: Operands of '=' have incompatible types 'long int' and 'BITMAP'.
grab.c(3029): error #2001: Syntax error: expected ';' but found 'img'.
grab.c(3029): error #2152: Unknown field 'bmWidth' of 'BITMAPINFOHEADER' (did you mean: biWidth?).
grab.c(3030): error #2168: Operands of '=' have incompatible types 'long int' and 'BITMAP'.
grab.c(3030): error #2001: Syntax error: expected ';' but found 'img'.
grab.c(3030): error #2152: Unknown field 'bmHeight' of 'BITMAPINFOHEADER' (did you mean: biHeight?).
grab.c(5246): error #2039: Invalid expression.
grab.c(5246): error #2088: Lvalue required.
grab.c(6899): error #2147: Undefined label 'L1090'.



You can see from the output above that I did not correct your "FUNCTON" (sp.) typo.