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'
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.
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.
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;
}
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.
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.
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!).
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.
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.
... 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.
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;
}
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):
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.
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;
}
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
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?
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!
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.
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++.
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.
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! .
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.
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!
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!
...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.
Comments
Are you compiling with the -lm switch to include the maths library? Catalina doesn't include it by default.
Ross.
re the -lm switch, this is my batch file
I have #include <math.h> at the top of my C program. Do I need another switch somewhere?
Yes - change your command to: The reason I don't include -lm by default is that you could also use -lma or -lmb. The differences are:
-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!
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
any idea what might be wrong there?
the two string functions are
Great progress - can't see why that line doesn't compile - can you zip up the whole of BCX.c and post it?
Ross.
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.
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.
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.
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.
and another error with mid which calls this function and gives an error
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.
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.
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.
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.
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.
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?
A couple of things. First, you're correct, you cannot add a default value in a function prototype in C89. Replace that line with: 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!):
Next, you need to include string.h (and also declare your replacement strupr):
Now it compiles.
Ross.
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...
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.
and I ran this through BCX, then added some #includes, and added a line that Qt seems to need
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.
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.
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?
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!
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:)
Errr...Which is which? Nothing uncompliant about GCC.
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++.
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.
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:)
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:
Yep, thanks to the efforts of Dave Betz and Jazzed.
Yep, always have done.
Yep, Dave has that working in the latest Zog for C3 and GG_SDRAM boards.
Ah...You might have us there...
He's too busy trying to find an iceberg to sleep in to worry too much I think.
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.
No. BDSC is no new fangled standardized C. It is C as the Gods (Kernighan & Ritchie) intended it. Well almost.
As Leor Zolman says:
The first standard for C did not arrive until 1989.
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:
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:)