Shop OBEX P1 Docs P2 Docs Learn Events
Catalina 2.9 - Page 2 — Parallax Forums

Catalina 2.9

2456715

Comments

  • RossHRossH Posts: 5,547
    edited 2011-02-05 17:22
    Dr_Acula wrote: »
    Yes it is an unsigned character. I'll try that.

    Can you help with some maths. I get an error with "sin undefined"
    #include <math.h>
    static double  number1;
    printf("% .15G\n",(double)sin(number1));
    

    Are you compiling with the -lm switch to include the maths library? Catalina doesn't include it by default.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-05 17:29
    That typedef fixed the UCHAR! That means we can do a lot more functions.

    re the -lm switch, this is my batch file
    @echo off
    echo.
    echo    ===================
    echo    SETTING UP CATALINA
    echo    ===================
    echo.
    PATH=C:\Program Files\Catalina\bin;%PATH%
    Call catalina_env.bat()
    catalina -lcx -x5 -M 128k -D DRACBLADE -D HIRES_VGA BCX.C
    pause
    

    I have #include <math.h> at the top of my C program. Do I need another switch somewhere?
  • RossHRossH Posts: 5,547
    edited 2011-02-05 17:35
    Hi Dr_A,

    Yes - change your command to:
    catalina -lcx -lm -x5 -M 128k -D DRACBLADE -D HIRES_VGA BCX.C
    
    The reason I don't include -lm by default is that you could also use -lma or -lmb. The differences are:
    -lm : no extra cogs used. All maths operations done in software. Slow!

    -lma : one extra cog used (for the Float_A plugin). All functions not implemented in Float_A implemented in software. Faster!

    -lmb : two extra cogs used (for the Float_A and Float_B plugins). Fastest!
    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-05 18:10
    Ok, I'll add that in.

    Lots of things working:
    Strings - you can define the size of the array with Dim mystring$ as string * 80
    For loop working
    Do loops working
    While/Wend working
    Select case working
    Asc function working
    File access working
    functions and subroutines working
    String arrays working

    Would need to just strip off the start of the file with all those windows headers.

    So .. next little task - can I write the program to strip off the header in BCX basic, translate it to C and run it?

    Why do this? Well C89 seems to be the common language that Unix and Windows people can run. More universal than, say VB.NET.

    Plus I like a little intellectual challenge. To do this needs file access, program loops, subroutines, and string manipulation.

    I have all of those working except strings, which is coming unstuck on just one line
      char *strtmp = BCX_TmpStr(tmplen);
    

    any idea what might be wrong there?
    BCX.C:139: illegal statement termination
    BCX.C:139: skipping `char'
    BCX.C:139: undeclared identifier `strtmp'
    BCX.C:139: type error: pointer expected
    BCX.C:139: operands of = have illegal types `int' and `pointer to char'
    

    the two string functions are
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    char *left (char *S, int length)
    {
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      char *strtmp = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
  • RossHRossH Posts: 5,547
    edited 2011-02-05 18:17
    Hi Dr_Acula,

    Great progress - can't see why that line doesn't compile - can you zip up the whole of BCX.c and post it?

    Ross.
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-05 18:22
    char *left (char *S, int length)
    {
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      [COLOR="red"]char *strtmp[/COLOR] = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
    Can you try moving that variable declaration to the top of the function and only use it down there? Some compilers - depending on standard - are picky about this kind of detail.
    char *left (char *S, int length)
    {
      [COLOR="red"]char *strtmp;[/COLOR]
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      [COLOR="red"]strtmp[/COLOR] = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
    I don't know if this applies here but the problem exists in general.
  • RossHRossH Posts: 5,547
    edited 2011-02-05 18:24
    kuroneko wrote: »
    char *left (char *S, int length)
    {
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      [COLOR="red"]char *strtmp[/COLOR] = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
    Can you try moving that variable declaration to the top of the function and only use it down there? Some compilers - depending on standard - are picky about this kind of detail.
    char *left (char *S, int length)
    {
      [COLOR="red"]char *strtmp;[/COLOR]
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      [COLOR="red"]strtmp[/COLOR] = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    

    Aha! Well spotted kuroneko!

    Dr_A - C89 does not allow variable declarations after statements. This was introduced in C99. You can fix that in the way kuroneko suggested.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-05 18:29
    kuroneko has nailed it!

    might have to be a manual fix for that one in the precompiler. Still, we can search for that entire string and just replace it.

    This code is messy, it is just adding each function etc as we go.
    '$Source
    ' prints the original basic code as comments in the C code
    
    dim a as integer
    for a=1 to 10
        print "hello world";
        print a
    next a
    ' file test copied from bcx examples - files work - commented out for speed 
    
    'print "Opening file for output"
    
    'DIM MyFileHandle@ ' BCX Reserves @ for "C" FILE* data types
    'OPEN "new.txt" FOR OUTPUT  AS  FP1
    'MyFileHandle@ = FP1
    'FPRINT MyFileHandle@, "This is a test"
    'CLOSE FP1
    'print "Closing file"
    
    ' ASC function 
    
    DIM Mystring$ as string * 80 ' 80 characters
    DIM RetVal%
    Mystring$="A"
    print Mystring$
    RetVal% = ASC(Mystring$) 'this line fails with UCHAR not recognised
    PRINT RetVal%
    
    ' Test some inline C code - pass a value in myarray, C changes it, print the return value
    
    dim myarray[10] as integer
    myarray[1]=100
    print myarray[1]
    call TestCCode
    print myarray[1]
    
    ' test a string ' produces one error in the runtime libraries that catalina won't compile.   char *strtmp = BCX_TmpStr(tmplen);
    
    dim Lineoftext1$ as string * 80 ' strings must end in $ otherwise compiler doesn't copy properly
    dim Lineoftext2$ as string * 80
    lineoftext1$="Hello World"
    lineoftext2$=left$(lineoftext1$,4)
    print lineoftext2$
    
    ' test a string array
    
    dim stringarray[5] as string * 80 ' 80 characters
    stringarray[1]="Hello"
    stringarray[2]="World"
    print stringarray[2]
    
    
    ' test program control loops - FOR is already tested above
    a=1
    do
        print a
       a=a+1
    loop until a=5
    print "Do loop finished"
    
    a=1
    while a <5
        print a
        incr(a)' translates to a++ in C
    wend
    print "Wend loop finished"
    
    a=5
    select case a
        case 1
          print "1"
        case > 1 and < 6
          print "more than 1 and less than six"  
        case else
          print "something else"
    end select
    
    ' test functions
    
      print addnumbers(5,6)
      
    ' test some maths with floating point numbers
    
    dim number1 as double
    number1=1.2345
    print number1
    'print sin(number1)
    
    
    
    
    
    
    $CCODE
    while(1); // loop instead of finishing
    $CCODE
    
    ' and exitprocess does not work on the propeller. So don't use END for the moment
    
    ' subroutines and functions
    
    function addnumbers(a as integer, b as integer)
      dim returnvalue as integer
      returnvalue = a + b
      function=returnvalue
    end function
    
    sub TestCCode
     $CCODE
      // declare the variables:
      int nNumber;
      int *pPointer;
      // now, give a value to them:
      nNumber = 15;
      pPointer = &nNumber;
      // print out the value of nNumber:
      printf("nNumber is equal to : %d\n", nNumber);
      // now, alter nNumber through pPointer:
      *pPointer = 25;
      // prove that nNumber has changed as a result of the above
      // by printing its value again:
      printf("nNumber is equal to : %d\n", nNumber);
      
      myarray[1]=110;
      
     $CCODE
    end sub
    
    #include <stdio.h>
    #include <math.h>
    
                                                                         // *************************************************
                                                                         //            User Global Variables
                                                                         // *************************************************
    
    static int     a;
    static int     RetVal;
    static double  number1;
    static char    Mystring[80];
    static int     myarray[10];
    static char    stringarray[5][80];
    static char    lineoftext1[80];
    static char    lineoftext2[80];
    
    
                                                                         // *************************************************
                                                                         //               Standard Prototypes
                                                                         // *************************************************
    
    typedef unsigned char UCHAR;
    char*   BCX_TmpStr(size_t);
    char*   left (char*,int);
    
                                                                         // *************************************************
                                                                         //               User Prototypes
                                                                         // *************************************************
    
    void  clearscreen ();
    void    TestCCode (void);
    
    
                                                                         // *************************************************
                                                                         //                  Main Program
                                                                         // *************************************************
    
    int main(int argc, char *argv[])
    {
    
    
           clearscreen();
           for(a=1; a<=10; a+=1)
           {
                  printf("%s","hello world");
                  printf("% d\n",(int)a);
           }
    
    strcpy(Mystring,"A");
    printf("%s\n",Mystring);
    RetVal=(UCHAR)*(Mystring); 
    printf("% d\n",(int)RetVal);
    
    strcpy(lineoftext1,"Hello World");
    strcpy(lineoftext2,left(lineoftext1,4));
    printf("%s\n",lineoftext2);
    
    
    strcpy(stringarray[1],"Hello");
    strcpy(stringarray[2],"World");
    printf("%s\n",stringarray[2]);
    
           myarray[1]=100;
           printf("% d\n",(int)myarray[1]);
           TestCCode();
           printf("% d\n",(int)myarray[1]);
           
           a=1;
           for(;;)
           {
                  a+=1;
                  printf("% d\n",(int)a);
                  if(a==5)
                  {
                         break;
                  }
           }
           printf("%s\n","Do loop finished");
           
           a=1;
           while(a<5)
           {
                  printf("% d\n",(int)a);
                  (a)++;
           }
           printf("%s\n","Wend loop finished");
           
           a=5;
           for(;;)
           {
                  if(a==1)
                  {
                         printf("%s\n","1");
                         break;
                  }
                  if(a>1&&a<6)
                  {
                         printf("%s\n","more than 1 and less than six");
                         break;
                  }
                                                                         // case else
                  {
                         printf("%s\n","something else");
                  }
                  break;
           }
           
           
           
    	printf("% d\n",(int)addnumbers(5,6));
    
    
    number1=1.2345;
    printf("% .15G\n",(double)number1);
    
    
    while(1); // loop instead of finishing
    return(0);
    }
                                                                         // *************************************************
                                                                         //                 Runtime Functions
                                                                         // *************************************************
    
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    char *left (char *S, int length)
    {
      char *strtmp;
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      strtmp = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
    
    
                                                                         // ************************************
                                                                         //       User Subs and Functions
                                                                         // ************************************
    
    void clearscreen()                                                   // white text on dark blue background
    {
           int i;
           for (i=0;i<40;i++)
           {
                  t_setpos(0,0,i);                                       // move cursor to next line
                  t_color(0,0x08FC);                                     // RRGGBBxx eg dark blue background 00001000 white text 11111100
           }
    }
    
    int addnumbers (int a, int b)
    {
      static   int      returnvalue;
      memset(&returnvalue,0,sizeof(returnvalue));
      returnvalue=a+b;
      return returnvalue;
    }
    
    
    void TestCCode (void)
    {
                                                                         // declare the variables:
           int nNumber;
           int *pPointer;
                                                                         // now, give a value to them:
           nNumber = 15;
           pPointer = &nNumber;
                                                                         // print out the value of nNumber:
           printf("nNumber is equal to : %d\n", nNumber);
                                                                         // now, alter nNumber through pPointer:
           *pPointer = 25;
                                                                         // prove that nNumber has changed as a result of the above
                                                                         // by printing its value again:
           printf("nNumber is equal to : %d\n", nNumber);
           myarray[1]=110;
           
    }
    
  • RossHRossH Posts: 5,547
    edited 2011-02-05 18:33
    Dr_Acula wrote: »
    might have to be a manual fix for that one in the precompiler. Still, we can search for that entire string and just replace it.

    Dr_A,

    At some point (when you have proven the concept, which can't be too far off!) it would be better to modify the BCX source (which is itself written in Basic) and recompile that.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-05 19:08
    Yes that could well be an option.

    I got the Sin() working just now. The propeller is calculating to 15 decimal places. In Basic and in C. And just for good measure I threw in a "log" and that works too.

    In fact, if we are prepared to accept a subset of BCX that does not include all the GUI code, I think this could be quite a feasible project.

    A general question for Ross - I presume if we put in the -lm switch, it uses up more memory? Is -lm therefore more suitable for external memory applications?

    I tried adding some more string functions. Got a couple of errors.
    BCX.C:161: illegal return type; found `int' expected `pointer to char'
    BCX.C:180: illegal return type; found `int' expected `pointer to char'
    
    char *right (char *S, int length)
    {
      int tmplen = strlen(S);
      char *BCX_RetStr = BCX_TmpStr(tmplen);
      tmplen -= length;
      if (tmplen<0) tmplen = 0;
      return strcpy(BCX_RetStr, &S[tmplen]); // ********************** this line returns an error **************8
    }
    
    
    char *mid (char *S, int start, int length)
    {
      char *strtmp;
      register int tmplen = strlen(S);
      if(start>tmplen||start<1) return BCX_TmpStr(1);
      if (length<0 || length>(tmplen-start)+1)
        length = (tmplen-start)+1;
      strtmp = BCX_TmpStr(length);
      return (char*)memcpy(strtmp,&S[start-1],length);
    }
    
    
    char *ucase (char *S)
    {
      register char *strtmp = BCX_TmpStr(strlen(S));
      return strupr(strcpy(strtmp,S)); // *************************** this line returns an error *****************
    }
    

    and another error with mid
    strcpy(lineoftext2,mid(lineoftext1,5,4));
    
    which calls this function
    char *mid (char *S, int start, int length)
    {
      char *strtmp;
      register int tmplen = strlen(S);
      if(start>tmplen||start<1) return BCX_TmpStr(1);
      if (length<0 || length>(tmplen-start)+1)
        length = (tmplen-start)+1;
      strtmp = BCX_TmpStr(length);
      return (char*)memcpy(strtmp,&S[start-1],length);
    }
    
    and gives an error
    BCX.C:166: warning: declaration of `mid' does not match previous declaration at BCX.C:59
    

    There are some other similar errors coming up with other string functions so I am hoping the solution for one will be the solution for others.

    addit Interesting that mid has " char *strtmp;" on a separate line - but left and right don't. Almost as if it is worth looking at the BCX source code.
  • RossHRossH Posts: 5,547
    edited 2011-02-05 19:24
    Hi Dr_A,

    Yes, in general -lm is bigger than -lma, which is bigger than -lmb. Speed is the opposite. But you can use them in normal LMM applications - it depends how many functions you call (there is no overhead including -lm if you never use any of the maths functions!).

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-05 19:59
    Sounds fine. The math functions sure are useful.

    Sorry, I post edited post #41 with some more questions about the C code.

    If anyone else wants to give this a try, download BCX, and if you run it a little yellow BCX icon appears in the tray. Right click on that and use "Jfe Editor" for editing the Basic files. Run BC.EXE to convert (I'm not using any command line parameters), and it is a bit quicker if you create a small batch file to do this. I'm reading this into Code::Blocks for the C editing. If you keep code::blocks open, and have run BC, code::blocks recognises the new file and you can just click "yes" to load it. I'm then copying and pasting the relevant text into a notepad file BCX.C, which is essentially the C code with all the windows defines stripped out, and also a few subtle changes to the C code as noted above.

    Then run catalina to compile and download.

    The above should be possible to automate further.
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-05 20:09
    BCX.C:161: illegal return type; found `int' expected `pointer to char'
    BCX.C:180: illegal return type; found `int' expected `pointer to char'
    
    Odd, strcpy() is supposed to return destination so maybe your prototype is wrong. Can you attach BCX.C? And how is strcpy() defined (may be in a different (header) file)?
    BCX.C:166: warning: declaration of `mid' does not match previous declaration at BCX.C:59
    
    Same here, usually it's due to being defined one way but used in a completely different way.
  • RossHRossH Posts: 5,547
    edited 2011-02-05 22:47
    kuroneko wrote: »
    ... usually it's due to being defined one way but used in a completely different way.

    Or not being defined at all. You don't have to define functions before you use them in C - the first time the C compiler sees a function that has not been defined, it simply assumes the function returns an int. If the function is later defined as something else (e.g. returning a char *) the C compiler then throws a wobbly.

    Ross.
  • kuronekokuroneko Posts: 3,623
    edited 2011-02-05 22:51
    RossH wrote: »
    Or not being defined at all.
    Yes, which seems to be the most likely reason here (hence my question where strcpy() is defined).
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-05 23:31
    My bad, I forgot to copy over a couple of the "standard prototypes", ie the definitions of the functions. There is now an error with this line
    char*   mid (char*, int, int=-1);
    

    where I don't think you can both set the type of variable and set its value as part of the declaration. And there are two more errors. Warts and all, this is the code. Thanks++ for all the help here. I think if I keep making notes of where things fall over, we can build up a list of syntax changes that need to be made. These will probably be fixed sorts of lines, eg you will get a line like the one above and it will either be there exactly as it is, or it won't be there because strings were not used. So it should be possible to search for lines in their entirety and replace then with a different syntax.
    #include <stdio.h>
    #include <math.h>
    
                                                                         // *************************************************
                                                                         //            User Global Variables
                                                                         // *************************************************
    
    static int     a;
    static int     RetVal;
    static double  number1;
    static char    Mystring[80];
    static int     myarray[10];
    static char    stringarray[5][80];
    static char    lineoftext1[80];
    static char    lineoftext2[80];
    
    
                                                                         // *************************************************
                                                                         //               Standard Prototypes
                                                                         // *************************************************
    
    typedef unsigned char UCHAR;
    char*   BCX_TmpStr(size_t);
    char*   left (char*,int);
    char*   ucase (char*);
    char*   mid (char*, int, int=-1);
    char*   right (char*,int);
    
                                                                         // *************************************************
                                                                         //               User Prototypes
                                                                         // *************************************************
    
    void  clearscreen ();
    void    TestCCode (void);
    
    
                                                                         // *************************************************
                                                                         //                  Main Program
                                                                         // *************************************************
    
    int main(int argc, char *argv[])
    {
    
    
           clearscreen();
           for(a=1; a<=10; a+=1)
           {
                  printf("%s","hello world");
                  printf("% d\n",(int)a);
           }
    
    strcpy(Mystring,"A");
    printf("%s\n",Mystring);
    RetVal=(UCHAR)*(Mystring); 
    printf("% d\n",(int)RetVal);
    
    // string functions
    strcpy(lineoftext1,"Hello World");
    strcpy(lineoftext2,left(lineoftext1,4));
    printf("%s\n",lineoftext2);
    strcpy(lineoftext2,mid(lineoftext1,5,4));
    printf("%s\n",lineoftext2);
    //strcpy(lineoftext2,ucase(lineoftext1));
    printf("%s\n",lineoftext2);
    //strcpy(lineoftext2,right(lineoftext1,3));
    printf("%s\n",lineoftext2);
    
    
    strcpy(stringarray[1],"Hello");
    strcpy(stringarray[2],"World");
    printf("%s\n",stringarray[2]);
    
           myarray[1]=100;
           printf("% d\n",(int)myarray[1]);
           TestCCode();
           printf("% d\n",(int)myarray[1]);
           
           a=1;
           for(;;)
           {
                  a+=1;
                  printf("% d\n",(int)a);
                  if(a==5)
                  {
                         break;
                  }
           }
           printf("%s\n","Do loop finished");
           
           a=1;
           while(a<5)
           {
                  printf("% d\n",(int)a);
                  (a)++;
           }
           printf("%s\n","Wend loop finished");
           
           a=5;
           for(;;)
           {
                  if(a==1)
                  {
                         printf("%s\n","1");
                         break;
                  }
                  if(a>1&&a<6)
                  {
                         printf("%s\n","more than 1 and less than six");
                         break;
                  }
                                                                         // case else
                  {
                         printf("%s\n","something else");
                  }
                  break;
           }
           
           
           
    	printf("% d\n",(int)addnumbers(5,6));
    
    
    number1=1.2345;
    printf("% .15G\n",(double)number1);
    printf("% .15G\n",(double)sin(number1));
    printf("% .15G\n",(double)log(number1));
    
    
    while(1); // loop instead of finishing
    return(0);
    }
                                                                         // *************************************************
                                                                         //                 Runtime Functions
                                                                         // *************************************************
    
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    char *left (char *S, int length)
    {
      char *strtmp;
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      strtmp = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
    char *right (char *S, int length)
    {
      int tmplen = strlen(S);
      char *BCX_RetStr = BCX_TmpStr(tmplen);
      tmplen -= length;
      if (tmplen<0) tmplen = 0;
      return strcpy(BCX_RetStr, &S[tmplen]);
    }
    
    
    char *mid (char *S, int start, int length)
    {
      char *strtmp;
      register int tmplen = strlen(S);
      if(start>tmplen||start<1) return BCX_TmpStr(1);
      if (length<0 || length>(tmplen-start)+1)
        length = (tmplen-start)+1;
      strtmp = BCX_TmpStr(length);
      return (char*)memcpy(strtmp,&S[start-1],length);
    }
    
    
    char *ucase (char *S)
    {
      register char *strtmp = BCX_TmpStr(strlen(S));
      return strupr(strcpy(strtmp,S));
    }
    
    
                                                                         // ************************************
                                                                         //       User Subs and Functions
                                                                         // ************************************
    
    void clearscreen()                                                   // white text on dark blue background
    {
           int i;
           for (i=0;i<40;i++)
           {
                  t_setpos(0,0,i);                                       // move cursor to next line
                  t_color(0,0x08FC);                                     // RRGGBBxx eg dark blue background 00001000 white text 11111100
           }
    }
    
    int addnumbers (int a, int b)
    {
      static   int      returnvalue;
      memset(&returnvalue,0,sizeof(returnvalue));
      returnvalue=a+b;
      return returnvalue;
    }
    
    
    void TestCCode (void)
    {
                                                                         // declare the variables:
           int nNumber;
           int *pPointer;
                                                                         // now, give a value to them:
           nNumber = 15;
           pPointer = &nNumber;
                                                                         // print out the value of nNumber:
           printf("nNumber is equal to : %d\n", nNumber);
                                                                         // now, alter nNumber through pPointer:
           *pPointer = 25;
                                                                         // prove that nNumber has changed as a result of the above
                                                                         // by printing its value again:
           printf("nNumber is equal to : %d\n", nNumber);
           myarray[1]=110;
           
    }
    

    Errors are in line 27 char* mid (char*, int, int=-1);
    line 164 return strcpy(BCX_RetStr, &S[tmplen]);
    and 183 return strupr(strcpy(strtmp,S));


    I'm not quite sure about the strcpy thing, because strcpy is used quite a few times in the 'main' as well and no errors there.

    addit: below is the unchanged output from BCX - this won't compile as it is but maybe I forgot to copy something over?
    // *********************************************************************
    // Created with BCX32 - BASIC To C/C++ Translator (V) 6.1.6 (2010/08/02)
    //                 BCX (c) 1999 - 2009 by Kevin Diggins
    // *********************************************************************
    //              Translated for compiling with a C Compiler
    // *********************************************************************
    #include <windows.h>    // Win32 Header File 
    #include <windowsx.h>   // Win32 Header File 
    #include <commctrl.h>   // Win32 Header File 
    #include <commdlg.h>    // Win32 Header File 
    #include <mmsystem.h>   // Win32 Header File 
    #include <shellapi.h>   // Win32 Header File 
    #include <shlobj.h>     // Win32 Header File 
    #include <richedit.h>   // Win32 Header File 
    #include <wchar.h>      // Win32 Header File 
    #include <objbase.h>    // Win32 Header File 
    #include <ocidl.h>      // Win32 Header File 
    #include <winuser.h>    // Win32 Header File 
    #include <olectl.h>     // Win32 Header File 
    #include <oaidl.h>      // Win32 Header File 
    #include <ole2.h>       // Win32 Header File 
    #include <oleauto.h>    // Win32 Header File 
    #include <conio.h>
    #include <direct.h>
    #include <ctype.h>
    #include <io.h>
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #include <stddef.h>
    #include <stdlib.h>
    #include <setjmp.h>
    #include <time.h>
    #include <stdarg.h>
    #include <process.h>
    
    
    // ***************************************************
    // Compiler Defines
    // ***************************************************
    
    // C++
    #if defined( __cplusplus )
      #define overloaded
      #define C_EXPORT EXTERN_C __declspec(dllexport)
      #define C_IMPORT EXTERN_C __declspec(dllimport)
    #else
      #define C_EXPORT __declspec(dllexport)
      #define C_IMPORT __declspec(dllimport)
    #endif
    
    // Open Watcom defs
    #if defined( __WATCOM_CPLUSPLUS__ ) || defined( __TINYC__ )
      #define atanl atan
      #define sinl  sin
      #define cosl  cos
      #define tanl  tan
      #define asinl asin
      #define acosl acos
      #define log10l log10
      #define logl   log
      #define _fcloseall fcloseall
    #endif
    
    // Borland C++ 5.5.1 defs - bcc32.exe
    #if defined( __BCPLUSPLUS__ )
      // ===== Borland Libraries ==========
      #include <dos.h>
      #pragma comment(lib,"import32.lib")
      #pragma comment(lib,"cw32.lib")
      // ==================================
    #endif
    
    // Microsoft VC++
    #ifndef DECLSPEC_UUID
      #if (_MSC_VER >= 1100) && defined ( __cplusplus )
        #define DECLSPEC_UUID(x)    __declspec(uuid(x))
      #else
        #define DECLSPEC_UUID(x)
      #endif
    #endif
    
    
    #if !defined( __LCC__ )
    // *************************************************
    // Instruct Linker to Search Object/Import Libraries
    // *************************************************
    #pragma comment(lib,"kernel32.lib")
    #pragma comment(lib,"user32.lib")
    #pragma comment(lib,"gdi32.lib")
    #pragma comment(lib,"comctl32.lib")
    #pragma comment(lib,"advapi32.lib")
    #pragma comment(lib,"winspool.lib")
    #pragma comment(lib,"shell32.lib")
    #pragma comment(lib,"ole32.lib")
    #pragma comment(lib,"oleaut32.lib")
    #pragma comment(lib,"uuid.lib")
    #pragma comment(lib,"odbc32.lib")
    #pragma comment(lib,"odbccp32.lib")
    #pragma comment(lib,"winmm.lib")
    #pragma comment(lib,"comdlg32.lib")
    #pragma comment(lib,"imagehlp.lib")
    #pragma comment(lib,"version.lib")
    #else
    #pragma lib <winspool.lib>
    #pragma lib <shell32.lib>
    #pragma lib <ole32.lib>
    #pragma lib <oleaut32.lib>
    #pragma lib <uuid.lib>
    #pragma lib <odbc32.lib>
    #pragma lib <odbccp32.lib>
    #pragma lib <winmm.lib>
    #pragma lib <imagehlp.lib>
    #pragma lib <version.lib>
    // *************************************************
    // End of Object/Import Libraries To Search
    // *************************************************
    #endif
    // *************************************************
    //                System Variables
    // *************************************************
    
    
    // *************************************************
    //            User Global Variables
    // *************************************************
    
    static int     a;
    static int     RetVal;
    static double  number1;
    static char    Mystring[80];
    static int     myarray[10];
    static char    Lineoftext1[80];
    static char    Lineoftext2[80];
    static char    stringarray[5][80];
    
    
    
    // *************************************************
    //               Standard Prototypes
    // *************************************************
    
    char*   BCX_TmpStr(size_t);
    char*   ucase (char*);
    char*   mid (char*, int, int=-1);
    char*   left (char*,int);
    char*   right (char*,int);
    
    // *************************************************
    //               User Prototypes
    // *************************************************
    
    int     addnumbers (int, int);
    void    TestCCode (void);
    
    
    // *************************************************
    //            User Global Initialized Arrays
    // *************************************************
    
    
    // *************************************************
    //                  Main Program
    // *************************************************
    
    int main(int argc, char *argv[])
    {
    for(a=1; a<=10; a+=1)
      {
        printf("%s","hello world");
        printf("% d\n",(int)a);
      }
    strcpy(Mystring,"A");
    printf("%s\n",Mystring);
    RetVal=(UCHAR)*(Mystring);
    printf("% d\n",(int)RetVal);
    myarray[1]=100;
    printf("% d\n",(int)myarray[1]);
    TestCCode();
    printf("% d\n",(int)myarray[1]);
    strcpy(lineoftext1,"Hello World");
    strcpy(lineoftext2,left(lineoftext1,4));
    printf("%s\n",lineoftext2);
    strcpy(lineoftext2,mid(lineoftext1,5,4));
    printf("%s\n",lineoftext2);
    //strcpy(lineoftext2,ucase(lineoftext1));
    printf("%s\n",lineoftext2);
    //strcpy(lineoftext2,right(lineoftext1,3));
    printf("%s\n",lineoftext2);
    strcpy(stringarray[1],"Hello");
    strcpy(stringarray[2],"World");
    printf("%s\n",stringarray[2]);
    a=1;
    for(;;)
      {
        printf("% d\n",(int)a);
        a+=1;
        if(a==5)
          {
            break;
          }
      }
    printf("%s\n","Do loop finished");
    a=1;
    while(a<5)
      {
        printf("% d\n",(int)a);
        (a)++;
      }
    printf("%s\n","Wend loop finished");
    a=5;
    for(;;)
    {
      if(a==1)
        {
          printf("%s\n","1");
          break;
        }
      if(a>1&&a<6)
        {
          printf("%s\n","more than 1 and less than six");
          break;
        }
        // case else
        {
          printf("%s\n","something else");
        }
      break;
    }
    printf("% d\n",(int)addnumbers(5,6));
    number1=1.2345;
    printf("% .15G\n",(double)number1);
    printf("% .15G\n",(double)sin(number1));
    printf("% .15G\n",(double)log(number1));
    while(1); // loop instead of finishing
      return 0;   //  End of main program
    }
    
    // *************************************************
    //                 Runtime Functions
    // *************************************************
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    char *left (char *S, int length)
    {
      register int tmplen = strlen(S);
      if(length<1) return BCX_TmpStr(1);
      if(length<tmplen) tmplen=length;
      char *strtmp = BCX_TmpStr(tmplen);
      return (char*)memcpy(strtmp,S,tmplen);
    }
    
    
    char *right (char *S, int length)
    {
      int tmplen = strlen(S);
      char *BCX_RetStr = BCX_TmpStr(tmplen);
      tmplen -= length;
      if (tmplen<0) tmplen = 0;
      return strcpy(BCX_RetStr, &S[tmplen]);
    }
    
    
    char *mid (char *S, int start, int length)
    {
      char *strtmp;
      register int tmplen = strlen(S);
      if(start>tmplen||start<1) return BCX_TmpStr(1);
      if (length<0 || length>(tmplen-start)+1)
        length = (tmplen-start)+1;
      strtmp = BCX_TmpStr(length);
      return (char*)memcpy(strtmp,&S[start-1],length);
    }
    
    
    char *ucase (char *S)
    {
      register char *strtmp = BCX_TmpStr(strlen(S));
      return strupr(strcpy(strtmp,S));
    }
    
    
    
    // ************************************
    //       User Subs and Functions
    // ************************************
    
    
    int addnumbers (int a, int b)
    {
      static   int      returnvalue;
      memset(&returnvalue,0,sizeof(returnvalue));
      returnvalue=a+b;
      return returnvalue;
    }
    
    
    void TestCCode (void)
    {
      // declare the variables:
      int nNumber;
      int *pPointer;
      // now, give a value to them:
      nNumber = 15;
      pPointer = &nNumber;
      // print out the value of nNumber:
      printf("nNumber is equal to : %d\n", nNumber);
      // now, alter nNumber through pPointer:
      *pPointer = 25;
      // prove that nNumber has changed as a result of the above
      // by printing its value again:
      printf("nNumber is equal to : %d\n", nNumber);
    
      myarray[1]=110;
    
    }
    
  • RossHRossH Posts: 5,547
    edited 2011-02-05 23:44
    Hi Dr_Acula,

    A couple of things. First, you're correct, you cannot add a default value in a function prototype in C89. Replace that line with:
    char*   mid (char*, int, int);
    
    If it is ever called without the third parameter, you're in trouble - but cross that bridge when you come to it.

    Next, strupr is not an ANSI function - but here is a "workalike" (untested!):
    char *strupr(char *string) {
       int i, len;
       len = strlen(string);
       for (i = 0; i < len; i++) {
          if (!isupper(string[i])) {
             string[i] = toupper(string[i]);
          }
       }
       return string;
    }
    
    Next, you need to include string.h (and also declare your replacement strupr):
    #include <string.h>
    char *strupr(char *);
    

    Now it compiles.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-06 03:32
    Awesome. Now it works.

    I think even if the code is not correct, what is going to be produced is going to be consistent, so if if is a matter of searching for a function, and replacing with a new function, that ought to be entirely possible. Or rewrite BCX??

    One issue might be to think about the #include directives. If you add one string function in Basic, that will need string.h There are probably going to be some 'essential' .h files and maybe some others that are not needed so often.

    I think the marketing niche of this program is "Big Basic" and because we already have several other Basic programs for the propeller, I suspect that this one belongs on boards with external memory. So - there is not such a cost with putting in .h files. I wonder about just including an essential set of .h files regardless? It may be easier to code this way, though I suppose you could search for certain functions that are only associated with certain .h files and then include the .h files selectively.

    Next little job is to start the process of writing a pre-processor. I think I'll write this in BCX Basic and see if it will compile. Three reasons. One is that by finding each of these problems one at a time we can solve them. Second, it would be kind of cool to be able to run the preprocessor on the propeller itself. And third, I think it ought to generate code that linux users can use too.

    I think the general concept here is sound. We can compile a lot of Basic code, and we can do so with only minor changes. And we can leverage off the amazing power of Catalina running on the propeller.

    Addit - Found and downloaded the Tiny C Compiler. Well this is rather nice, having a console program running the same program as on the Propeller on the next screen. This will make debugging a lot easier, as it will be very quick to test things out.

    So - on with writing the pre processor...
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-07 18:11
    Hi RossH,

    TinyC compiler works, but there has been some activity on another thread suggesting that we should try to all use the same compiler so we can use different platforms. One could debate this for ever I guess, but from a practical point of view I'd like to try to code using C89 as much as possible.

    So, to this end, I am writing a program to convert the output of BCX into C89. I need to open text files, modify them and close the files. Much of the above discussion was about the building blocks to do this.

    I know how to do this in Basic, and now I need to translate that Basic into C. And ideally into a C dialect we can all use. I'm still not sure of the best approach - TinyC, or Qt, or even the possibly not so crazy idea of sending the file to a propeller board and running it on Catalina?!

    Anyway, I have a bootstrapping problem, as I need the first few lines working in order to process more lines. This is my original Basic program - just read in a text file until it ends and print each line.
    Dim Filename$ as string * 80
    dim Lineoftext$ as string * 80
    
    Filename$="input.c"
    
    OPEN Filename$ FOR INPUT AS fp1
    WHILE NOT EOF(fp1)
        LINE INPUT fp1, Lineoftext$
        print Lineoftext$
     WEND
     CLOSE fp1
    

    and I ran this through BCX, then added some #includes, and added a line that Qt seems to need
        QCoreApplication a(argc, argv);
    

    and then fixed some errors, moved a few things around, and got it down to just three errors.
    status = loadinput(); loadinput was not declared in this scope (in the main function - I thought I declared it above??)
    if(StrFunc[StrCnt]) free (StrFunc[StrCnt]); free was not declared in this scope (is this a non C89 function??)
    return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char)); calloc was not declared in this scope (ditto?)

    advice would be most appreciated.
    #include <QtCore/QCoreApplication>
    #include <stdio.h>
    #include <math.h>
    #include <strings.h>
    
    // *************************************************
    //            User Global Variables
    // *************************************************
    
    static FILE   *fp1;
    static char    Filename[80];
    static char    Lineoftext[80];
    
    // *************************************************
    //               Standard Prototypes
    // *************************************************
    
    int     EoF (FILE*);
    char*   BCX_TmpStr(size_t);
    int     loadfile(void);
    
    // *************************************************
    //            User Global Initialized Arrays
    // *************************************************
    
    
    // *************************************************
    //                  Main Program
    // *************************************************
    
    int main(int argc, char *argv[])
    {
        int status;
        QCoreApplication a(argc, argv);
        printf("BCX to C89. Run BC.EXE and rename your .c file to input.c\n");
        printf("Loading input.c\n");
        status = loadinput();
        return a.exec();
    }
    
    
    // *************************************************
    //                 Runtime Functions
    // *************************************************
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    int EoF (FILE* stream)
    {
      register int c, status = ((c = fgetc(stream)) == EOF);
      ungetc(c,stream);
      return status;
    }
    
    // *************************************************
    //                 User Functions
    // *************************************************
    int loadfile(void)
    {
      int status;
      strcpy(Filename,"input.c");
    if((fp1=fopen(Filename,"r"))==0)
     {
        fprintf(stderr,"Can't open file %s\n",Filename);
        status = false;
     }
    while(!EoF(fp1))
      {
        Lineoftext[0]=0;
        fgets(Lineoftext,1048576,fp1);
        if(Lineoftext[strlen(Lineoftext)-1]==10)Lineoftext[strlen(Lineoftext)-1]=0;
        printf("%s\n",Lineoftext);
      }
    if(fp1)
     {
       fclose(fp1);
       fp1=NULL;
       status = true;
     }
     return status;
    }
    
  • RossHRossH Posts: 5,547
    edited 2011-02-07 18:52
    Hi Dr_A,

    Is someone porting TinyC to the Propeller? Seems a bit pointless - I iniitally ported LCC because there was no C compiler available - and now we have one fully compliant one, and two partially-compliant ones!

    In my view, your best bet for portability is to stick to C89 (aka C90, aka ISO/IEC 9899:1990, aka ANSI C,aka ANSI X3.159-1989 - and before the pedants jump in, yes I know these terms are all slightly different, but they all essentially refer to the same language). That will at least make the result compatible between most C compilers, including Catalina, GNU and (posibly) TinyC.

    As to your three errors - are you sure you posted the correct source? The source you posted won''t compile - it refers to QtCore/QCoreApplication and strings.h. I don't know what these are, but they certainly won't compile under Catalina! Did you perhaps mean string.h?

    Also, loadinput is not defined anywhere, so this error is not surprising, and if you want to use calloc and free you need to include stdlib.h

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-07 19:10
    Thanks ++ Ross. See, this is where your expert opinion spots things that I would never see. The answer is to include "stdlib.h". And I changed strings.h to string.h

    And the one with loadinput - well, my bad, because I changed the name to loadfile in another place. So that works and now it compiles.

    In terms of standards, the qcoreapplication seems to be the thing that puts the command box on the screen. So I guess it could go but it might be useful for debugging.

    I'm looking for some code to do the pre-processing of BCX output. From my point of view I'd prefer to do this in vb.net, but as others have said, that cuts out a number of propeller users. So the aim is to find a language we can all use, and a program we can all use.

    Qt does seem to fit the bill. I'll be programming in C89, but the IDE that Andrey is writing will of course be in Qt C++.

    Just out of interest, what is your C compiler, and what operating system do you use?
  • RossHRossH Posts: 5,547
    edited 2011-02-07 19:32
    Hi Dr_A

    I use gcc on both Windows and Linux. At one stage I used lcc, but there is no debugger for it (or rather there are two - one called cdb and one called ldb - but I didn't have much luck with either). It's kind of funny that Catalina now comes with a better debugger than lcc - maybe I should 'back-port' blackbox to Windows!
  • Heater.Heater. Posts: 21,230
    edited 2011-02-08 00:34
    RossH,

    Pedant here:)
    I iniitally ported LCC because there was no C compiler available
    I'd just like to point out that the first C code was run on the Prop some months before Catalina. It was compiled with BDS C and ran under the PropAltair 8080 emulator running CP/M

    To this day:
    1) It's the only way to compile C code actually on the Propeller, self hosting.
    2) It produces the smallest executables.

    I know, I know, emulating an 8080 is not running native on the Prop. For the sake of my argument neither is LMM. An LMM kernel is just a very small virtual machine:)
    and now we have one fully compliant one, and two partially-compliant ones!
    Errr...Which is which? Nothing uncompliant about GCC.
  • Heater.Heater. Posts: 21,230
    edited 2011-02-08 00:48
    Dr_A,
    Qt does seem to fit the bill. I'll be programming in C89, but the IDE that Andrey is writing will of course be in Qt C++
    You seem to be confusing a few things here.

    On the one hand, you, Andrey, anyone wants to write tools for the Prop that run on a PC. Here something like Qt is an excellent choice. In which case those tools will be written in C++. (See note below).

    On the other hand you have something like BCX and intending for it to generate code to actually run on the Propeller. (I guess). Given the absence of C++ or any C++ libs on the Prop (Qt libs) then C++ is not an option for the output of BCX.

    So...You could end up with an IDE written in C++ that is used to create code in regular C.


    Note: It is possible to write GUI apps using Qt in other languages. Python for example. Which for many may be easier than using C++.
  • RossHRossH Posts: 5,547
    edited 2011-02-08 01:29
    Heater. wrote: »
    RossH,

    Pedant here:)

    I'd just like to point out that the first C code was run on the Prop some months before Catalina. It was compiled with BDS C and ran under the PropAltair 8080 emulator running CP/M

    To this day:
    1) It's the only way to compile C code actually on the Propeller, self hosting.
    2) It produces the smallest executables.

    I know, I know, emulating an 8080 is not running native on the Prop. For the sake of my argument neither is LMM. An LMM kernel is just a very small virtual machine:)
    Ah, Is this the right room for an argument?
    An LMM kernel is not a virtual machine - it directly executes PASM instructions loaded from Hub RAM. It uses self-modifying code to do so, but then so do many "native" Propeller programs.

    If you are going to argue over the particular LMM kernel that Catalina uses, then you are essentially arguing over just the LMM "primitives" it implements - but I could have easily produced a version of Catalina that doesn't need these at all - just by executing the same sequence of instructions loaded from Hub RAM each time. The main reason this is not done is that all it would do is make the executables larger (and slower). It is more akin to linking a program to a dynamic library rather than including a static copy of the same library functions.
    Heater. wrote: »

    Errr...Which is which? Nothing uncompliant about GCC.
    Until you get all your ANSI-mandated library functions in place, gcc is non-compliant. Can you access the file system from a gcc-compiled program yet? Do you suport malloc & free? What about setjmp and longjmp? Or signal handling? If so, you are compliant. I have not followed Zog closely enough to know the answer to this, so if you can do so then I apologize for the unintended slight - and may Zog forgive me! :smile:.
    Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-02-08 01:53
    RossH,
    An LMM kernel is not a virtual machine
    I have to regroup and think about that one. Or perhaps we have had this debate enough times already:)

    Either way C, on the Prop was first done with PropAltair:)
    Until you get all your ANSI-mandated library functions in place, gcc is non-compliant.
    Well, yes and no.
    I make a distinction between the language and it's libraries. Even if the standards orgs disagree. After all plenty of people are using standards compliant C compilers for their micro-controller projects, PIC, AVR, ARM etc without any file system or stdio on the target or memory allocator (malloc/free) etc.

    Re: Zog:
    Can you access the file system from a gcc-compiled program yet?
    Yep, thanks to the efforts of Dave Betz and Jazzed.
    Do you suport malloc & free?
    Yep, always have done.
    What about setjmp and longjmp?
    Yep, Dave has that working in the latest Zog for C3 and GG_SDRAM boards.
    Or signal handling?
    Ah...You might have us there...
    ..may Zog forgive me!
    He's too busy trying to find an iceberg to sleep in to worry too much I think.
  • RossHRossH Posts: 5,547
    edited 2011-02-08 02:21
    Heater. wrote: »
    RossH,

    Either way C, on the Prop was first done with PropAltair:)

    Ok - I'll grant your PropAltair "first C compiler to compile code on the Propeller". I'm not sure if it's ANSI compliant, but if it is then you can add "ANSI compliant" as well.

    But I reserve "first ANSI compliant C compiler to generate native code for the Propeller " for Catalina. Even if I can't convince you that an LMM kernel is not a virtual machine, then since every instruction it executes is a PASM instruction, the machine it virtualizes is ... (wait for it) ... a Propeller! - so the code is still native!

    Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-02-08 02:31
    RossH,
    I'll grant your PropAltair "first C compiler to compile code on the Propeller". I'm not sure if it's ANSI compliant, but if it is then you can add "ANSI compliant" as well.
    No. BDSC is no new fangled standardized C. It is C as the Gods (Kernighan & Ritchie) intended it. Well almost.

    As Leor Zolman says:
    In 1979, I wrote a compiler for a subset of the pre-Standard ("K&R Classic") C Programming Language.
    The first standard for C did not arrive until 1989.
    Even if I can't convince you that an LMM kernel is not a virtual machine, then since every instruction it executes is a PASM instruction, the machine it virtualizes is ... (wait for it) ... a Propeller! - so the code is still native!
    There you go with that Zen thing again:)
  • RossHRossH Posts: 5,547
    edited 2011-02-08 02:46
    Heater. wrote: »

    There you go with that Zen thing again:)

    Ah!, brings back fond memories of one of the koans my old Zen master used to teach:
    What is the sound of one cog spinning?
    Ross.
  • Heater.Heater. Posts: 21,230
    edited 2011-02-08 04:09
    RossH,
    An LMM kernel is not a virtual machine.
    Yes it is.
    ...it directly executes PASM instructions loaded from Hub RAM.
    Yes, but...

    This is a particularly pointless argument but that has never stopped me in the past:) Besides the legitimacy of the Zog system as a "C for the Propeller" depends on it so here goes:

    In order to run an LLM program, for example a binary produced by Catalina or any other system, on the Propeller one needs at least:

    1) To be able to execute those PASM instructions. Well fair enough they are native PASM directly executed by a COG. When they get there.

    2) A Program Counter pointing into HUB (Ignore external memory for now). This is required so as know where the next instruction comes from. Manipulation of the PC is required for conditional execution and function calls. The Prop does not have such a Program Counter in hardware, it must be implemented in software (in the LMM kernel) i.e. virtualized.

    3) A mechanism for fetching instructions from HUB into the CPU (COG) for execution. The Prop does not support such an instruction fetch mechanism in hardware, it must be implemented in software i.e. virtualized. That is the basic LMM loop.

    3) A Stack Pointer pointing into HUB. Potentially a C compiler could get away without a dedicated SP register but I'm sure Catalina's LMM kernel for example has one. Again the Prop does not have such a Stack Pointer in hardware and it must be implemented in software i.e. virtualized. Along with the software implemented PUSH, POP, CALL, RET etc.

    4) I could probably go on.

    As we see there is a lot of virtualization going in in the simple LMM kernel. Even just the basic, and tiny, instruction fetch loop, ergo an LMM kernel is a virtual machine.

    Further, if you take away the LMM kernel the LMM binary cannot be run therefore that binary is not "native" PASM.

    Further, there are many possible LMM kernels. Including the bizarre kernel that fetches and executes instructions in reverse order for extra speed. (Sorry I forgot who came up with that one.) Clearly the binaries that run under these different kernels cannot all be "native" propeller code.

    When we look at the situation with executing code from external memory (XMM) things get even more virtual, now we have to have a software implementation of instruction/data fetch over an external bus which the Prop does not support directly in hardware.

    I rest my case. For now:)
Sign In or Register to comment.