Author Topic: C/C++ to C BASIC/JADE convertor needed  (Read 5768 times)

Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
C/C++ to C BASIC/JADE convertor needed
« on: November 17, 2013, 11:35:12 AM »
I think it would help the  C BASIC and JADE projects to attract interest if one could simply run a utility on a C/C++ source program and the #define translation would be done automatically. The concept behind these two projects is to make C look more like BASIC. I think we are at the point with our keyword lists that manual translation is redundant and a wasting developer's time creating examples for others. I had asked Daniel if he could assist but his focus is on a PowerBASIC to C++ translation and anything else at this time would overflow his plate.

I have made an initial attempt at creating a translator in ScriptBasic but I can see it diverting the free time I do have away from the core needs of C BASIC. If anyone out there (All BASIC member or not) would like to create this utility in the language of their choice, it would much appreciated. Maybe a code challenge could come of it?

The All BASIC Developers site has a mailing list and IRC/chat to allow non-members to participate in these development efforts.
« Last Edit: November 17, 2013, 11:48:36 AM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #1 on: November 18, 2013, 01:57:03 PM »
Hint:

I'm having continued success with my ScriptBasic C to C BASIC symbol translation utility. The key seems to be the order the replace routines are run to eliminate like symbol nesting issues.

Maybe AIR can whip up something in Python using pyparsing to make this easier to do.

I'm also thinking that an interactive tool be written so ambiguities can be dealt with immediately before letting it propagate in the wrong direction.
« Last Edit: November 18, 2013, 03:42:31 PM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #2 on: November 19, 2013, 12:30:27 AM »
I thought I would try using UltraEdit search and replace to see how far I could get with my C to C BASIC symbol translation. I think this method is going to work fine. The following list was used in a REPLACE ALL mode. My final step would be to do interactive search and replaces to get the symbols that may have dual meaning. (like * for math and as a PTR)

Code: [Select]
{ = BEGIN
} = END
return = RETURN
if = IF
for = FOR
while = WHILE
switch = SELECT_CASE
case = CASE
break; = END_CASE
default: = CASE_ELSE
END else BEGIN = ELSE
END else  =     ELSE_IF
IF
&& = AND
|| = OR
== = EQ
fprintf = PRINT_FILE
printf = PRINT

Here is the results of the above search and replaces.

Code: [Select]
/* Simple program:  Move N sprites around on the screen as fast as possible */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <SDL/SDL.h>
#include "cbasic.h"

#define NUM_SPRITES 100
#define MAX_SPEED   1

SDL_Surface *sprite;
int numsprites;
SDL_Rect *sprite_rects;
SDL_Rect *positions;
SDL_Rect *velocities;
int sprites_visible;
int debug_flip;
Uint16 sprite_w, sprite_h;

/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void quit(int rc)
BEGIN
  SDL_Quit();
  exit(rc);
END

int LoadSprite(char *file)
BEGIN
  SDL_Surface *temp;

  /* Load the sprite image */
  sprite = SDL_LoadBMP(file);
  IF ( sprite EQ NULL ) BEGIN
    PRINT_FILE(stderr, "Couldn't load %s: %s", file, SDL_GetError());
    RETURN(-1);
  END

  /* Set transparent pixel as the pixel at (0,0) */
  IF ( sprite->format->palette ) BEGIN
    SDL_SetColorKey(sprite, (SDL_SRCCOLORKEY|SDL_RLEACCEL),
            *(Uint8 *)sprite->pixels);
  END

  /* Convert sprite to video FORmat */
  temp = SDL_DisplayFormat(sprite);
  SDL_FreeSurface(sprite);
  IF ( temp EQ NULL ) BEGIN
    PRINT_FILE(stderr, "Couldn't convert background: %s\n",
              SDL_GetError());
    RETURN(-1);
  END
  sprite = temp;

  /* We're ready to roll. :) */
  RETURN(0);
END

void MoveSprites(SDL_Surface *screen, Uint32 background)
BEGIN
  int i, nupdates;
  SDL_Rect area, *position, *velocity;

  nupdates = 0;
  /* Erase all the sprites IF necessary */
  IF ( sprites_visible ) BEGIN
    SDL_FillRect(screen, NULL, background);
  END

  /* Move the sprite, bounce at the wall, and draw */
  FOR ( i=0; i<numsprites; ++i ) BEGIN
    position = &positions[i];
    velocity = &velocities[i];
    position->x += velocity->x;
    IF ( (position->x < 0) OR (position->x >= (screen->w - sprite_w)) ) BEGIN
      velocity->x = -velocity->x;
      position->x += velocity->x;
    END
    position->y += velocity->y;
    IF ( (position->y < 0) OR (position->y >= (screen->h - sprite_w)) ) BEGIN
      velocity->y = -velocity->y;
      position->y += velocity->y;
    END

    /* Blit the sprite onto the screen */
    area = *position;
    SDL_BlitSurface(sprite, NULL, screen, &area);
    sprite_rects[nupdates++] = area;
  END

  IF (debug_flip) BEGIN
    IF ( (screen->flags & SDL_DOUBLEBUF) EQ SDL_DOUBLEBUF ) BEGIN
      static int t = 0;

      Uint32 color = SDL_MapRGB (screen->format, 255, 0, 0);
      SDL_Rect r;
      r.x = (sin((float)t * 2 * 3.1459) + 1.0) / 2.0 * (screen->w-20);
      r.y = 0;
      r.w = 20;
      r.h = screen->h;

      SDL_FillRect (screen, &r, color);
      t+=2;
    END
  END

  /* Update the screen! */
  IF ( (screen->flags & SDL_DOUBLEBUF) EQ SDL_DOUBLEBUF ) BEGIN
    SDL_Flip(screen);
  ELSE
    SDL_UpdateRects(screen, nupdates, sprite_rects);
  END
  sprites_visible = 1;
END

/* This is a way of telling whether or not to use hardware surfaces */
Uint32 FastestFlags(Uint32 flags, int width, int height, int bpp)
BEGIN
  const SDL_VideoInfo *info;

  /* Hardware acceleration is only used in fullscreen mode */
  flags |= SDL_FULLSCREEN;

  /* Check FOR various video capabilities */
  info = SDL_GetVideoInfo();
  IF ( info->blit_hw_CC AND info->blit_fill ) BEGIN
    /* We use accelerated colorkeying and color filling */
    flags |= SDL_HWSURFACE;
  END
  /* If we have enough video memory, and will use accelerated
     blits directly to it, then use page flipping.
   */
  IF ( (flags & SDL_HWSURFACE) EQ SDL_HWSURFACE ) BEGIN
    /* Direct hardware blitting without double-buffering
       causes really bad flickering.
     */
    IF ( info->video_mem*1024 > (height*width*bpp/8) ) BEGIN
      flags |= SDL_DOUBLEBUF;
    ELSE
      flags &= ~SDL_HWSURFACE;
    END
  END

  /* Return the flags */
  RETURN(flags);
END

int main(int argc, char *argv[])
BEGIN
  SDL_Surface *screen;
  Uint8 *mem;
  int width, height;
  Uint8  video_bpp;
  Uint32 videoflags;
  Uint32 background;
  int    i, done;
  SDL_Event event;
  Uint32 then, now, frames;

  /* Initialize SDL */
  IF ( SDL_Init(SDL_INIT_VIDEO) < 0 ) BEGIN
    PRINT_FILE(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
    RETURN(1);
  END

  numsprites = NUM_SPRITES;
  videoflags = SDL_SWSURFACE|SDL_ANYFORMAT;
  width = 640;
  height = 480;
  video_bpp = 8;
  debug_flip = 0;
  WHILE ( argc > 1 ) BEGIN
    --argc;
    IF ( strcmp(argv[argc-1], "-width") EQ 0 ) BEGIN
      width = atoi(argv[argc]);
      --argc;
    ELSE_IF ( strcmp(argv[argc-1], "-height") EQ 0 ) BEGIN
      height = atoi(argv[argc]);
      --argc;
    ELSE_IF ( strcmp(argv[argc-1], "-bpp") EQ 0 ) BEGIN
      video_bpp = atoi(argv[argc]);
      videoflags &= ~SDL_ANYFORMAT;
      --argc;
    ELSE_IF ( strcmp(argv[argc], "-fast") EQ 0 ) BEGIN
      videoflags = FastestFlags(videoflags, width, height, video_bpp);
    ELSE_IF ( strcmp(argv[argc], "-hw") EQ 0 ) BEGIN
      videoflags ^= SDL_HWSURFACE;
    ELSE_IF ( strcmp(argv[argc], "-flip") EQ 0 ) BEGIN
      videoflags ^= SDL_DOUBLEBUF;
    ELSE_IF ( strcmp(argv[argc], "-debugflip") EQ 0 ) BEGIN
      debug_flip ^= 1;
    ELSE_IF ( strcmp(argv[argc], "-fullscreen") EQ 0 ) BEGIN
      videoflags ^= SDL_FULLSCREEN;
    ELSE_IF ( isdigit(argv[argc][0]) ) BEGIN
      numsprites = atoi(argv[argc]);
    ELSE
      PRINT_FILE(stderr,
  "Usage: %s [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]\n",
                argv[0]);
      quit(1);
    END
  END

  /* Set video mode */
  screen = SDL_SetVideoMode(width, height, video_bpp, videoflags);
  IF ( ! screen ) BEGIN
    PRINT_FILE(stderr, "Couldn't set %dx%d video mode: %s\n",
          width, height, SDL_GetError());
    quit(2);
  END
  SDL_WM_SetCaption("C BASIC SDL 1.2 Sprites",0);

  /* Load the sprite */
  IF ( LoadSprite("icon.bmp") < 0 ) BEGIN
    quit(1);
  END

  /* Allocate memory FOR the sprite info */
  mem = (Uint8 *)malloc(4*sizeof(SDL_Rect)*numsprites);
  IF ( mem EQ NULL ) BEGIN
    SDL_FreeSurface(sprite);
    PRINT_FILE(stderr, "Out of memory!\n");
    quit(2);
  END
  sprite_rects = (SDL_Rect *)mem;
  positions = sprite_rects;
  sprite_rects += numsprites;
  velocities = sprite_rects;
  sprite_rects += numsprites;
  sprite_w = sprite->w;
  sprite_h = sprite->h;
  srand(time(NULL));
  FOR ( i=0; i<numsprites; ++i ) BEGIN
    positions[i].x = rand()%(screen->w - sprite_w);
    positions[i].y = rand()%(screen->h - sprite_h);
    positions[i].w = sprite->w;
    positions[i].h = sprite->h;
    velocities[i].x = 0;
    velocities[i].y = 0;
    WHILE ( ! velocities[i].x AND ! velocities[i].y ) BEGIN
      velocities[i].x = (rand()%(MAX_SPEED*2+1))-MAX_SPEED;
      velocities[i].y = (rand()%(MAX_SPEED*2+1))-MAX_SPEED;
    END
  END
  background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);

  /* Print out inFORmation about our surfaces */
  PRINT("Screen is at %d bits per pixel\n",screen->format->BitsPerPixel);
  IF ( (screen->flags & SDL_HWSURFACE) EQ SDL_HWSURFACE ) BEGIN
    PRINT("Screen is in video memory\n");
  ELSE
    PRINT("Screen is in system memory\n");
  END
  IF ( (screen->flags & SDL_DOUBLEBUF) EQ SDL_DOUBLEBUF ) BEGIN
    PRINT("Screen has double-buffering enabled\n");
  END
  IF ( (sprite->flags & SDL_HWSURFACE) EQ SDL_HWSURFACE ) BEGIN
    PRINT("Sprite is in video memory\n");
  ELSE
    PRINT("Sprite is in system memory\n");
  END
  /* Run a sample blit to trigger blit acceleration */
  BEGIN SDL_Rect dst;
    dst.x = 0;
    dst.y = 0;
    dst.w = sprite->w;
    dst.h = sprite->h;
    SDL_BlitSurface(sprite, NULL, screen, &dst);
    SDL_FillRect(screen, &dst, background);
  END
  IF ( (sprite->flags & SDL_HWACCEL) EQ SDL_HWACCEL ) BEGIN
    PRINT("Sprite blit uses hardware acceleration\n");
  END
  IF ( (sprite->flags & SDL_RLEACCEL) EQ SDL_RLEACCEL ) BEGIN
    PRINT("Sprite blit uses RLE acceleration\n");
  END

  /* Loop, blitting sprites and waiting FOR a keystroke */
  frames = 0;
  then = SDL_GetTicks();
  done = 0;
  sprites_visible = 0;
  WHILE ( !done ) BEGIN
    /* Check FOR events */
    ++frames;
    WHILE ( SDL_PollEvent(&event) ) BEGIN
      SELECT_CASE (event.type) BEGIN
        CASE SDL_MOUSEBUTTONDOWN:
          SDL_WarpMouse(screen->w/2, screen->h/2);
          END_CASE
        CASE SDL_KEYDOWN:
          /* Any keypress quits the app... */
        CASE SDL_QUIT:
          done = 1;
          END_CASE
        CASE_ELSE
          END_CASE
      END
    END
    MoveSprites(screen, background);
  END
  SDL_FreeSurface(sprite);
  free(mem);

  /* Print out some timing inFORmation */
  now = SDL_GetTicks();
  IF ( now > then ) BEGIN
    PRINT("%2.2f frames per second\n",
          ((double)frames*1000)/(now-then));
  END
  SDL_Quit();
  RETURN(0);
END

I had to add a BEGIN and END #define as I'm a little more verbose with the traditional version of C BASIC. I'm happy to say that the REPLACE ALL work great except for the FOR as it picked up the SDL format and change it to upper case. (not allowing the program to compile in that state) After repairing the format case changes it compiled fine. For now this method will save me a lot of time as I continue to refine my C BASIC keyword list. The fully converted testsprite.c example can be found in the C BASIC GUI thread.

FOR replace missteps
Code: [Select]
jrs@laptop:~/C_BASIC/xlate$ make -B -f Makefile.cbsr
gcc -g -O2 -D_GNU_SOURCE=1 -D_REENTRANT -DHAVE_OPENGL    xsprite.c   -o xsprite
xsprite.c: In function ‘LoadSprite’:
xsprite.c:43:13: error: ‘SDL_Surface’ has no member named ‘FORmat’
  IF ( sprite->FORmat->palette ) BEGIN
             ^
xsprite.c: In function ‘MoveSprites’:
xsprite.c:98:37: error: ‘SDL_Surface’ has no member named ‘FORmat’
    Uint32 color = SDL_MapRGB (screen->FORmat, 255, 0, 0);
                                     ^
xsprite.c: In function ‘main’:
xsprite.c:248:32: error: ‘SDL_Surface’ has no member named ‘FORmat’
  background = SDL_MapRGB(screen->FORmat, 0x00, 0x00, 0x00);
                                ^
xsprite.c:251:49: error: ‘SDL_Surface’ has no member named ‘FORmat’
  PRINT("Screen is at %d bits per pixel\n",screen->FORmat->BitsPerPixel);
                                                 ^
make: *** [xsprite] Error 1
jrs@laptop:~/C_BASIC/xlate$

jrs@laptop:~/C_BASIC/xlate$ make -B -f Makefile.cbsr
gcc -o xsprite xsprite.c -g -O2 -D_GNU_SOURCE=1 -D_REENTRANT -DHAVE_OPENGL -lSDL -lm
jrs@laptop:~/C_BASIC/xlate$

UltraEdit has a nice feature that allows for multiple copy buffers. This will help with the BEGIN/END second round make-over to give it the more traditional BASIC look. I'm pretty sure I can automate at least the REPLACE ALL steps with a SB script and do the FOR/TO/STEP changes. In all I would say this is a 10X improvement over how I was doing it before. (keyword by keyword) As it turned out, using Daniel's uCalc Transform tool for this would probably have been overkill.
« Last Edit: November 19, 2013, 01:08:42 AM by John »

Offline AIR

  • BASIC Developer
  • Posts: 628
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #3 on: November 19, 2013, 04:54:47 AM »
If it has the capability, tell it to search/replace FULL WORDS only.  This way, "format" would not be altered.

Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #4 on: November 19, 2013, 07:19:44 AM »
UE does support the whole word only option and I will give it a try with the next program.

Thanks for the hint!

I'm going to try to incorporate the REPLACE ALL keywords in a SB script to get that effort going and add to it as it makes sense. Who knows, I might be able to do this in a fully automated fashion after trying it on a few C code examples. (SDL, IUP, ...)

@AIR - Lets put our heads together on this and try to come up with a search and replace scheme that might fully automate this. If you can concentrate on the JADE version, we can adapt the minor keyword differences between the two variations and come up with something useful. Without a symbol translator, this project doesn't have any teeth.

« Last Edit: November 19, 2013, 08:15:30 AM by John »

Offline AIR

  • BASIC Developer
  • Posts: 628
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #5 on: November 19, 2013, 04:31:29 PM »
To be honest, I don't see the point behind building a translator of this kind.

I could see the merits in building a C to Basic translator (not that I would), targeting an existing Basic implementation, but for this I think it's overkill.

If you find some routines you want to use, you can just "plug them in" without having to do any sort of translation.  Use C Basic/Jade to write any additional code you would want (like glue code) and call it a day.

If you recall, very early on I said that at some point a parser would be needed, because you can only go so far with #defines.  You disagreed then, do you still feel the same now?

If you really want to do this, start with the standard ANSI C keywords, not code you've already translated by hand (it's harder to know what you might need if your code hasn't used it).  Once you have that, then proceed to check out the GCC extensions to C.  A starting point: http://www.programiz.com/c-programming/list-all-keywords-c-language


Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #6 on: November 19, 2013, 04:44:35 PM »
I'm better off than I was just using UltraEdit to do the replacements. It's a good tool to walk through a translation and see where an automated script would screwup your C program. I'm going to keep building on what I have to make things easier. The only way to improve on it is keep converting C programs until it does everything on its own. I don't know if it's feasible or not but fun trying.  :)

My C hit list.  ???

Keywords in C Programming
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
« Last Edit: November 19, 2013, 04:54:11 PM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #7 on: November 20, 2013, 04:21:22 PM »
Many of the above keywords I'm not touching. All I'm trying to do is make C look more like BASIC. C BASIC is just training wheels and a comfortable pair of jeans. Charles is adding the missing goodies BASIC programmers aren't willing to leave home for.

AIR made the comment that to do this right, a BASIC to C BASIC / JADE converter should be written. And which BASIC would that be? I wouldn't count on the PB boys showing any interest as Daniel has found with his uCalc Transform to C++ initiative. I can't even bare the thought of a VB to C effort so a BASIC converter makes no sense to me.

The only folks that might be interested in C BASIC / JADE are those with primarily BASIC programming skills now seeing the benefits of C/C++. I think taking the demo C programs that come with SDL and IUP and others and convert them to C BASIC is the most efficient way to turn BASIC programmers into C programmers. No one likes to read documentation when a readable program serves the same purpose.
 
« Last Edit: November 20, 2013, 04:23:31 PM by John »

Offline AIR

  • BASIC Developer
  • Posts: 628
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #8 on: November 21, 2013, 04:53:45 AM »
Quote from: AIR
If you recall, very early on I said that at some point a parser would be needed, because you can only go so far with #defines.

A PARSER, not a CONVERTER.  Converter has already been done (Bacon, BCX, ...)

Case in point:  SELECT (switch)

Can't directly use strings with it, because strings are not primitive types.

Offline John

  • Forum Support / SB Dev
  • Posts: 2622
    • ScriptBasic Open Source Project
Re: C/C++ to C BASIC/JADE convertor needed
« Reply #9 on: November 21, 2013, 08:33:39 AM »
SB doesn't have a SELECT/CASE structure and IF/ELSEIF/ELSE/ takes care of it. C has the same language structure. Once again, I'm just trying to make C look more like BASIC. We are programming in C/C++ with a little BASIC help. My thinking is that if BASIC programmers look at C BASIC versions of existing C demos and examples, changing or using code from them to create their own C BASIC programs should be much easier to do. C BASIC is transitional-ware.


« Last Edit: November 21, 2013, 10:55:00 AM by John »