• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

How to mimic GOSUB in C ?

Started by Patrice Terrier, February 12, 2013, 06:03:44 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

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?

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

Charles Pegge

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

Theo Gottwald

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.

James C. Fuller

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 */
}




Patrice Terrier

#4
James, Theo, Charles,

Microsoft discourage the use of setjmp/longjmp 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 Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge


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

Theo Gottwald

PowerBasic does it clean and simple.

James C. Fuller

Quote from: Patrice Terrier on February 13, 2013, 09:42:57 AM
James, Theo, Charles,

Microsoft discourage the use of setjmp/longjmp 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

Frederick J. Harris

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.

Patrice Terrier

Fred,

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

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

Frederick J. Harris

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 ...

Frederick J. Harris

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.

Frederick J. Harris

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. 

Frederick J. Harris

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.   

Charles Pegge

GNU compilers seem to cover all platforms - including Android :)