Jose's Read Only Forum 2023

General Category => General Discussion => Topic started by: Patrice Terrier on February 12, 2013, 06:03:44 PM

Title: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 12, 2013, 06:03:44 PM
I know this is against the Cnob orthodoxy, however what do you think would be the best way to mimic GOSUB in C, without using a procedure?

:-[
Title: Re: How to mimic GOSUB in C ?
Post by: Charles Pegge on February 12, 2013, 06:49:42 PM
Interesting question, Patrice.

I find that GCC supports inner procedures, and that the outer local and static variables are visible to the inner procedure, thus perfectly mimicking a gosub.

I don't know whether VC supports this construct.


  #include <stdio.h>

  int main()
  {
    int a;
    void mygosub()
    {
     a=4;
    }
    mygosub();
    printf("%i",a);
  }


Charles
Title: Re: How to mimic GOSUB in C ?
Post by: Theo Gottwald on February 12, 2013, 06:57:32 PM
If C can use ASM then just use the ASM INLINE Commands and a Label?
I do not know C but i would do that in PB.
Title: Re: How to mimic GOSUB in C ?
Post by: James C. Fuller on February 12, 2013, 08:41:16 PM
It's not pretty and I'd recommend you rewriting your code but this is how bc9/bcx does it.
James

Basic code:


'==============================================================================
$CPPHDR
$ONEXIT "VC.BAT $FILE$ x86 con"
'==============================================================================


DIM j

CLS
PRINT "Calling Subroutine 9 times ..." : PRINT
FOR j = 1 TO 9
   GOSUB qwerty
NEXT
PRINT : PRINT "All Done!"
END                       ' Don't accidently fall into the subroutine



QwErTy:                   ' BCX Subroutine Labels are NOT case sensitive

PRINT " This is instance >>", j, " <<  of the subroutine call."

RETURN                    ' Return from subroutine back to main program


translated to c++ and compiled with sdk 7.1 cl.


// *********************************************************************
// Created with bc9 - BASIC To C/C++ Translator (V) 9.1.2.0 (2013/02/10)
//                 BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
//              Translated for compiling with a C++ Compiler
//                           On MS Windows
// *********************************************************************
// Additional lines may be needed
#if defined( __cplusplus )
  #include <iostream>
  #include <fstream>
  #include <sstream>
  #include <iomanip>
  typedef std::string stdstr;
  using namespace std;
#endif
#include <process.h>    // dos
#include <conio.h>      // dos
#include <direct.h>     // dos
#include <io.h>         // dos
#include <ctype.h>      // dos/linux
#include <fcntl.h>      // dos/linux
#include <math.h>       // dos/linux
#include <stdio.h>      // dos/linux
#include <string.h>     // dos/linux
#include <stddef.h>     // dos/linux
#include <stdlib.h>     // dos/linux
#include <setjmp.h>     // dos/linux
#include <time.h>       // dos/linux
#include <stdarg.h>     // dos/linux
#include <sys/types.h> 
#include <sys/stat.h>   

// ***************************************************
// types from winapi that may be needed
// ***************************************************
typedef char *PCHAR,*LPCH,*PCH,*NPSTR,*LPSTR,*PSTR;
typedef unsigned int UINT;
typedef unsigned long DWORD,ULONG;
typedef unsigned char UCHAR,byte;
typedef void *PVOID,*LPVOID;
//----------------------------------------------------
// this is missing From MinGWTDM64 stdlib.h
//----------------------------------------------------
#if defined(__MINGW32__) || defined(__MINGW64__)
  #ifndef MAX_PATH
    #define MAX_PATH 260
  #endif
#endif
//----------------------------------------------------


// *************************************************
//        User's GLOBAL ENUM blocks
// *************************************************

// *************************************************
//            System Defined Constants
// *************************************************

#define CCPTR const char*
#define cSizeOfDefaultString 2048

// *************************************************
//            User Defined Constants
// *************************************************


// *************************************************
//               Standard Prototypes
// *************************************************

void    cls(void);
// *************************************************
//          User Defined Types And Unions
// *************************************************


// *************************************************
//                System Variables
// *************************************************

jmp_buf GosubStack[32];
int     GosubNdx;

// *************************************************
//            User Global Variables
// *************************************************

static PCHAR   *g_argv;
static int     g_argc;
static int     j;


// *************************************************
//            User Global Initialized Arrays
// *************************************************



// *************************************************
//                 Runtime Functions
// *************************************************

void cls (void)
{
  system("cls");
}



// ************************************
//       User Subs and Functions
// ************************************

// *************************************************
//                  Main Program
// *************************************************

int main(int argc, char *argv[])
{
  g_argc = argc;
  g_argv = argv;
cls();
printf("%s\n","Calling Subroutine 9 times ...");
printf("\n");
for(j=1; j<=9; j+=1)
  {
    if (setjmp(GosubStack[GosubNdx++])==0) goto QWERTY;
  }

printf("\n");
printf("%s\n","All Done!");
fflush(stdout);
exit(0);

QWERTY:;
printf("%s% d%s\n"," This is instance >>",(int)j," <<  of the subroutine call.");
longjmp (GosubStack [--GosubNdx],1 );

  return 0;   /* End of main program */
}



Title: Re: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 13, 2013, 09:42:57 AM
James, Theo, Charles,

Microsoft discourage the use of setjmp/longjmp (http://msdn.microsoft.com/en-us/library/yz2ez4as(v=vs.80).aspx) within C++ program.

But i am unsure if this would impact the code, because the (gosub) jmp is done inside of the same procedure.

...
Title: Re: How to mimic GOSUB in C ?
Post by: Charles Pegge on February 13, 2013, 11:27:57 AM

Patrice,

On further research, I find that VC++, Clang and Objective C compilers do not support nested procedures unfortunately, only GCC (MinGw). I was rather shocked at the amount of baggage that accompanies a VC installation! GCC does it plain and simple.

Charles
Title: Re: How to mimic GOSUB in C ?
Post by: Theo Gottwald on February 13, 2013, 12:43:28 PM
PowerBasic does it clean and simple.
Title: Re: How to mimic GOSUB in C ?
Post by: James C. Fuller on February 13, 2013, 03:05:38 PM
Quote from: Patrice Terrier on February 13, 2013, 09:42:57 AM
James, Theo, Charles,

Microsoft discourage the use of setjmp/longjmp (http://msdn.microsoft.com/en-us/library/yz2ez4as(v=vs.80).aspx) within C++ program.

But i am unsure if this would impact the code, because the (gosub) jmp is done inside of the same procedure.

...

Patrice,
  My "c" is not the best but my interpretation of the link is the same as yours. Go for it as it appears you maybe walking a tightrope anyway using VC++ to write what is in actuality "c" code not c++.

James
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 14, 2013, 07:51:41 PM
Quote
I was rather shocked at the amount of baggage that accompanies a VC installation! GCC does it plain and simple.

Couple years back I bought VStudio 2008 Pro.  I told the setup utility to install everything for me.   It added 20 gigabytes to my harddrive!  20 gigs!  Couldn't believe it.

As far as the setjmp/lngjmp thing, I've never used those, so have no idea.
Title: Re: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 14, 2013, 07:56:35 PM
Fred,

I am looking for a good UNICODE string class, are you aware of any?

...
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 14, 2013, 10:50:37 PM
Well, the one you've been using from the C++ Standard Library has a wide character string counterpart.  I'll check its usage here in a second after I post this.  I'm a little hazy on the name because I use my own string class and have only used the C++ Std. one a couple times.  Just a second ...
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 14, 2013, 10:58:06 PM
Yea, here we go ...


#ifndef UNICODE                     //This program creates a window upon which are displayed
   #define UNICODE                  //continuously updated mouse coordinates, left button
#endif                              //click positions, window sizing information, and key
#ifndef _UNICODE                    //presses (concatenated together for simple text display).
   #define _UNICODE
#endif
#include <windows.h>
#include <tchar.h>
#ifdef UNICODE
   #define String std::wstring
#else
   #define String std::string
#endif


I thought it was just std::wstring, but didn't want to post until I was sure.  As you can see in the above excerpt from a program of mine, you can fool around with it with macros so as to use either ansi or wide strings.
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 14, 2013, 11:08:41 PM
The string handling I do in C++ is fairly simple so I use my own class which can be run ansi or unicode.  It compiles smaller than the Std Lib one.  Actually, its posted here on your forum ...

http://www.jose.it-berater.org/smfforum/index.php?topic=4615.45

in reply 49.

The actual string class is on my board in the COM section, and there is a link there in reply 49. 

The Std. Lib one is likely the way to go, unless shaving 10 or 20K from a dll/exe is critical to you.  I almost hate to say why I created my own.  Basically, from my own dumbness and failure to do the research, I didn't know the C++ Std. Lib. had one.  That was about 10 years ago, so I started creating my own.  It was a good learning experience and fun. 
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 14, 2013, 11:15:33 PM
It was just a couple weeks ago when I posted that example in your forum Patrice, and that was during a time I was playing with that 64 bit GNU compiler James Fuller turned me on to.  I was happy and amazed when it compiled my string class as 64 bit without any warnings or errors.  Sometimes I just get lucky I guess!

I know you like the Microsoft C/C++ compiler with VS, but I'd have to say the Mingw C\C++ compiler suite is worth looking into.   
Title: Re: How to mimic GOSUB in C ?
Post by: Charles Pegge on February 15, 2013, 12:30:49 AM
GNU compilers seem to cover all platforms - including Android :)
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 15, 2013, 01:52:29 AM
Here's an interesting little tidbit of info James might be interested in ...

... to time the compilation speed of the mingw compiler, use this switch in your compiler string ...

-ftime-report

It produces a report.

I've found the older compiler with my Code::Blocks installation is much faster than the newer one I downloaded a month ago.  Also, the PowerBASIC compiler has really slowed down.  I guess the dead code removal.
Title: Re: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 15, 2013, 09:36:31 AM
I know you like the Microsoft C/C++ compiler with VS
The reason why i use Visual Studio, is that it embraces all the Microsoft technologies within a single package, including managed and un-managed code.

So far, if C# would have been able to produce un-managed code, that would have been my compiler of choice. But i don't like the use of the extra frame-work, and the garbage collector manager. Non-obstant the fact, that i am writing mostly "unsafe" code ;)

Thus i put my choice on C/C++ without ATL and MFC, because i want to produce code without extra runtime, and i want to have direct control on what is going on under the hood, but i really hate the C/C++ syntax and the strong type they are using, HWND, HBITMAP, HANDLE, etc.,  when all could be replaced by DWORD. Also i never know exactly where to put the "*" when declaring/working with pointers.

Translating my GDImage to produce a 64-bit version is a very slow process, because i have to learn all the C/C++ oddities at the same time  :(

...

Title: Re: How to mimic GOSUB in C ?
Post by: Charles Pegge on February 15, 2013, 12:43:01 PM
Patrice,

Are you now prepared to submit to the anti-gosub mind clamp? :)

The only other sensible way is to OOPify your code so that all member variables can be shared between member functions (methods).
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 15, 2013, 01:05:47 PM
Quote
The only other sensible way is to OOPify your code so that all member variables can be shared between member functions (methods).

That's the beauty of inlining class members; it saves the overhead of a seperate function call, which, of course, is what gosub does.

I'll tell you what Patrice, I've had trouble over the years between the slightly different pointer notation between PowerBASIC and C.  They are so similiar, but yet there are subtle differences that drives one crazy.  I do have various code snippets handy outlining the differences perhaps you would be interested in.  Because I use pointers so heavily in my work, I've spent countless hours playing around with these things. 
Title: Re: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 15, 2013, 03:14:46 PM
QuoteAre you now prepared to submit to the anti-gosub mind clamp?
No, i will go the evil's way using couples of jmp/GOTO, because i am lazy and i want to keep the C code, close to the PB's original.

Did i say i like spaghetti  ;D

...
Title: Here is an example of C code that drives me nut.
Post by: Patrice Terrier on February 15, 2013, 03:55:04 PM
Here is an example of C code that drives me nut.

Code in red causes:
Error: a pointer bound to a function may only be used to call a function

typical syntax problem i am faced with...

Quote#include <windows.h>
#include "stdafx.h"

#include <vector>
#include <string.h>
using namespace std;


wstring zGetCTLText(IN HWND hCtrl) {
    std::wstring sBuf;
    long bufsize = 4096;
    vector<WCHAR>buf(bufsize);
    long length = min(GetWindowText(hCtrl, &buf[0], bufsize), bufsize);
    return wstring(buf.begin(), buf.begin() + length);
}

int _tmain(int argc, _TCHAR* argv[])
{
    HWND hWnd = GetForegroundWindow();
    wstring sCaption = zGetCTLText(hWnd);
    if (sCaption.length) { printf("%s", sCaption); }
    return 0;
}

And you know what, the problem is because the ".length" member must be followed by two empty (), like this:
if (sCaption.length()) { printf("%s", sCaption); }

>:(
Title: Re: How to mimic GOSUB in C ?
Post by: Paul Squires on February 15, 2013, 05:03:56 PM
Patrice, I've encounter the same problem while learning C#....forgetting to include the trailing open and close parenthesis when calling a method. Once I made the mistake and figured out the solution then I've been okay ever since. Coming from a VisualBasic background, we never had to include the parenthesis. I guess that "C" languages are more strict.
Title: Re: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 15, 2013, 05:17:27 PM
Paul

The C# syntax is much more easier to read/write from my opinion, but it is managed code  ???

...
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 15, 2013, 07:32:13 PM
That doesn't bother me about needing the brackets () on member function calls.  I'm more bothered with languages that don't require it (such as vb I believe - PB too?), as it seems to overlook the distinction between ordinary variables and member functions.

Patrice, what does this do


vector<WCHAR>buf(bufsize);


Create a vector whose upper limit of growth is restricted to bufsize, as opposed to the standard behaviour of unlimited growth? 

Anyway, how is your function to get text from a control any better than this (short compilable example)...


//Main.cpp - Developed with Code::Blocks / mingw; compiles to 57 k for me with 10.05 / 95 k with 12.11.
#define  UNICODE
#define  _UNICODE
#include <windows.h>
#include <tchar.h>
#include <string>
#define  IDC_BUTTON 1600


std::wstring strGetText(HWND hCtrl)
{
TCHAR szBuffer[4096];
GetWindowText(hCtrl,szBuffer,4096);
return std::wstring(szBuffer);
}


LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
  case WM_CREATE:
    {
       HINSTANCE hIns=((LPCREATESTRUCT)lParam)->hInstance;
       CreateWindowEx(0,_T("button"),_T("Click Me!"),WS_CHILD|WS_VISIBLE,75,50,150,30,hwnd,(HMENU)IDC_BUTTON,hIns,0);
       return 0;
    }
  case WM_COMMAND:
    {
       if(LOWORD(wParam)==IDC_BUTTON)
       {
          HWND hMain=GetForegroundWindow();
          MessageBox(hwnd,strGetText(hMain).c_str(),_T("Your Text..."),MB_OK);
       }
       return 0;
    }
  case WM_DESTROY:
    {
       PostQuitMessage(0);
       return 0;
    }
}

return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
TCHAR szClassName[]=_T("Text Wrapper Demo");
WNDCLASSEX wc={};
MSG messages;
HWND hWnd;

wc.lpszClassName = szClassName;
wc.lpfnWndProc   = fnWndProc;
wc.cbSize        = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
wc.hInstance     = hInstance;
RegisterClassEx(&wc);
hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,200,175,320,200,HWND_DESKTOP,0,hInstance,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
    TranslateMessage(&messages);
    DispatchMessage(&messages);
}

return messages.wParam;
}
Title: Re: How to mimic GOSUB in C ?
Post by: Patrice Terrier on February 15, 2013, 08:02:47 PM
Quotehow is your function to get text from a control any better than this
that was learning code to check the use of VECTOR (to mimic dynamic array), not production code.

...
Title: Re: How to mimic GOSUB in C ?
Post by: Frederick J. Harris on February 15, 2013, 08:59:16 PM
Quote
that was learning code to check the use of VECTOR (to mimic dynamic array), not production code.

Oh! :)

I'm such a minimalist by nature, once I understand something that looks overly complicated, I always start to thinking, "Boy!  I bet we could get rid of this or that or whatever!"