divert(-1)dnl # ------------------------------------------------------------- # An attempt to create a minimal BASIC to C converter using M4. # (c) Peter van Eerten, August - December 2014 - GPL v3. # # Needs the Boehm Garbage Collector (libgc). # # Usage: m4 basic.m4 prog.bas | indent > prog.c # # Compilation: gcc -o prog prog.c -lm -lgc # # ------------------------------------------------------------- # Internal macro to flush all diversions define(_FC,`divert undivert') # Statements go here define(PRINT,`_FC define(FORMAT,`divert(-1) undivert(2) divert(2) `,' divert(1)') fprintf(stdout, divert(4)); divert(2)"%s", divert(3)') define(INPUT,`_FC divert(1)fgets( divert(3)=GC_malloc(_bufsize),_bufsize,stdin); divert(2)') define(NL,`_FC fprintf(stdout,"\n");') define(WHILE,`_FC define(DO,`_FC') while( divert(2)){ divert(1)') define(WEND,`_FC }') define(REPEAT,`_FC do{ divert(1)') define(UNTIL,`_FC } divert(2))); divert(1)while(!(') define(FOR,`_FC undefine(`TO') define(TO,`undefine(`STEP') define(STEP,`divert(-1) undivert(5) divert(5)') divert(3))') divert(5)1 divert(6)){ divert(1)for( divert(2)_FA(') define(_FA,`$1;divert(4);substr($1,0,index($1,=))+= divert(3)substr($1,0,index($1,=))<=') define(NEXT,`_FC } divert(-1)') define(BREAK,`_FC break;') define(CONTINUE,`_FC continue;') define(LET,`_FC divert(2); divert(1)') define(SET,`_FC pushdef(`_FC',`) divert(1) substr(_FB,0,index(_FB,=)) =GC_strdup( substr(_FB,eval(index(_FB,=)+1)) ); popdef(`_FC')') undefine(`_FB') define(_FB,') define(DECLARE,`_FC define(TYPE,`divert(-1) undivert(1) divert(1)') divert(3); divert(1)long divert(2)') define(STRING,`_FC pushdef(`_FC',`) popdef(`_FC') ') _SA(') define(_SA,`ifelse(index(`$@',`,'),-1,char* `$@' =GC_strdup("");,char* substr(`$@',0,index(`$@',`,')) =GC_strdup(""); `_SA(shift($@))' ) ') define(INTEGER,`_FC pushdef(`_FC',`) popdef(`_FC') ') undefine(`_TYPE') define(_TYPE,long) _VA(') define(FLOAT,`_FC pushdef(`_FC',`) popdef(`_FC') ') undefine(`_TYPE') define(_TYPE,double) _VA(') define(_VA,`ifelse(index(`$@',`,'),-1,_TYPE `$@'=0;, _TYPE substr(`$@',0,index(`$@',`,'))=0; `_VA(shift($@))' ) ') define(END,`_FC divert(2)+0); divert(1)exit(') define(IF,`_FC define(THEN,`_FC') if( divert(2)){ divert(1)') define(ELIF,`_FC define(THEN,`_FC') }else if( divert(2)){ divert(1)') define(ELSE,`_FC }else{') define(ENDIF,`_FC }') define(FI,`_FC }') define(INCR,`_FC pushdef(`_FC',`) popdef(`_FC')') undefine(`_INC') undefine(`_SUM') define(_INC,`++') define(_SUM,`+=') _IA(') define(DECR,`_FC pushdef(`_FC',`) popdef(`_FC')') undefine(`_INC') undefine(`_SUM') define(_INC,`--') define(_SUM,`-=') _IA(') define(_IA,`ifelse(index(`$@',`,'),-1, `$@'_INC;, substr(`$@',0,index(`$@',`,')) _SUM substr(`$@',eval(index(`$@',`,')+1)) ;)') define(GOTO,`_FC divert(2); divert(1)goto ') define(LABEL,`_FC divert(2):; divert(1)') define(CALL,`_FC divert(2); divert(1)') define(SYSTEM,`_FC divert(1)RETVAL=system( divert(3));if(WIFEXITED(RETVAL))RETVAL=WEXITSTATUS(RETVAL);divert(2)') define(OPEN,`_FC pushdef(`FOR',`divert(3),') define(AS,`popdef(`FOR') divert(1)') divert(4)); divert(2)=fopen(') define(CLOSE,`_FC fclose( divert(2)); divert(1)') define(READLN,`_FC define(FROM,`divert(4)') divert(1)fgets( divert(3)=GC_malloc(_bufsize),_bufsize, divert(5)); divert(2)') define(WRITELN,`_FC undefine(`TO') define(TO,`divert(1)') fprintf( divert(4)); divert(3),"%s",') define(REWIND,`_FC rewind( divert(2)); divert(1)') define(SEEK,`_FC define(OFFSET,divert(2)`,') divert(3)`,'SEEK_SET); divert(1)fseek(') define(SLEEP,`_FC usleep( divert(2)*1000); divert(1)') define(CONST,`_FC pushdef(`_FC',`) popdef(`_FC')') ` #define' _CT(') define(_CT,`substr($@,0,index($@,`=')) substr($@,eval(index($@,`=')+1))') define(DEFFN,`CONST') define(POKE,`_FC pushdef(`_FC',`) popdef(`_FC')') _PO(') define(_PO,`*(_MEMTYPE *)(substr(`$@',0,index(`$@',`,')) ) = (_MEMTYPE)(substr(`$@',eval(index(`$@',`,')+1))) ;') define(FREE,`_FC divert(2)); divert(1)GC_free((void*)') define(SUB,`_FC divert(2){ divert(1)void ') define(ENDSUB,`_FC }') define(FUNC,`_FC define(TYPE,`divert(-1) undivert(1) divert(1)') divert(3){ divert(1)int divert(2)') define(ENDFUNC,`_FC }') define(RETURN,`_FC divert(2)+0); divert(1)return(') define(CLEAR,`_FC fprintf(stdout,"\033[2J\033[0;0f");fflush(stdout);') define(GOTOXY,`_FC pushdef(`_FC',`) popdef(`_FC')') _GO(') define(_GO,`fprintf(stdout, "\033[%d;%dH",(int)(substr(`$@',eval(index(`$@',`,')+1))),(int)(substr(`$@',0,index(`$@',`,'))));fflush(stdout);') define(COLOR,`_FC undefine(`TO') define(TO,`divert(2)),(int)(') define(RESET,`divert(2)`0),(int)(0'') divert(3)));fflush(stdout); divert(1)fprintf(stdout,"\033[%d%dm",(int)(') define(MEMTYPE,`_FC #undef _MEMTYPE #define _MEMTYPE') define(REM,`_FC divert(2)*/ divert(1)/* ') # Functions go here define(ABS,((($1) < 0) ? -($1) : ($1)) ) define(ADDRESS,(long)(&$1)) define(AND,`&&') define(APPENDING,"a+") define(ASC,(long)(unsigned char)*$1) define(BACKGROUND,4) define(BLACK,0) define(BLUE,4) define(COS,cos((double)($1)) ) define(CYAN,6) define(ENDFILE,feof($1)) define(EQUAL,`(long)(($1) == NULL && ($2) == NULL ? 1 : (($1) == NULL || ($2) == NULL ? 0 : !strcmp($1,$2)))') define(EVEN,(((long)($1) % 2 == 0) ? 1 : 0) ) define(EXP,exp((double)$1)) define(FALSE,0) define(FILEEXISTS,($1 != NULL ? !access($1, F_OK) : 0)) define(FILEPTR,FILE*) define(FLOOR,(long)floor($1)) define(FOREGROUND,3) define(GETENV,(($1) != NULL ? (getenv($1) != NULL ? GC_strdup(getenv($1)) : "") : "") ) define(GREEN,2) define(INSTR,(long)($1 != NULL && $2 != NULL ? (strstr($1,$2)-$1)+1 : 0) ) define(INT,lrint((double)($1)) ) define(ISFALSE,(($1) == 0)) define(ISTRUE,(($1) != 0)) define(LEFT,`(char*)($1 != NULL && ($2) <= strlen($1) ? strncpy(GC_malloc(strlen($1)+1),$1,$2) : $1)') define(LEN,(($1) != NULL ? strlen($1) : 0)) define(LOG,log((double)($1)) ) define(MAGENTA,5) define(MEMORY,`(long)GC_malloc(($1)*sizeof(_MEMTYPE))') define(MID,`(char*)($1 != NULL && ($2+$3) <= strlen($1) ? strncpy(GC_malloc(strlen($1)+1),($1)+($2)-1,$3) : (($2) <= strlen($1) ? strcpy(GC_malloc(strlen($1)+1),$1+$2-1) : $1))') define(MOD,((long)($1) % (long)($2)) ) define(NOT,(!($1)) ) define(ODD,(((long)($1) % 2 != 0) ? 1 : 0) ) define(OR,`||') define(PEEK,*(_MEMTYPE*)($1)) define(PI,3.1415926536) define(POW,pow((double)($1),(double)($2)) ) define(RANDOM,(($1) != 0 ? random()/(RAND_MAX/($1)) : 0) ) define(READING,"r") define(READWRITE,"w+") define(RED,1) define(RIGHT,`(char*)($1 != NULL && ($2) <= strlen($1) ? strncpy(GC_malloc(strlen($1)+1),$1+strlen($1)-($2),$2) : $1)') define(ROUND,lrint((double)($1)) ) define(SGN,(($1) == 0 ? 0 : (($1) < 0 ? -1 : 1)) ) define(SIN,sin((double)($1)) ) define(SIZEOF,sizeof($1)) define(SQR,sqrt((double)($1)) ) define(TAN,tan((double)($1)) ) define(TELL,ftell($1)) define(TRUE,1) define(VAL,(($1) != NULL ? atof($1) : 0) ) define(WHITE,7) define(WRITING,"w") define(YELLOW,3) # These use the GNU extension 'statement expression' define(CHR,`({unsigned char _tmp = ++_ptr;_sbuf[_tmp]=GC_malloc(sizeof(char)*2);snprintf(_sbuf[_tmp],sizeof(char)*2,"%c",(int)($1));_sbuf[_tmp];})') define(COLUMNS,`({struct winsize _tmp;ioctl(STDOUT_FILENO,TIOCGWINSZ,&_tmp);_tmp.ws_col;})') define(CONCAT,`({unsigned char _tmp = ++_ptr; _sbuf[_tmp]=GC_malloc(1);_CO($@);_sbuf[_tmp];})') define(_CO,`if($1 != NULL){_sbuf[_tmp]=GC_realloc(_sbuf[_tmp],strlen(_sbuf[_tmp])+strlen($1)+1);strcat(_sbuf[_tmp],$1);} ifelse($#,1,,`_CO(shift($@))') ') define(DEC,`({unsigned int _tmp;if(sscanf(($1), "%X", &_tmp) == EOF) _tmp=0;_tmp;})') define(HEX,`({unsigned char _tmp = ++_ptr;_sbuf[_tmp]=GC_malloc(sizeof(char)*_maxdigit);snprintf(_sbuf[_tmp],_maxdigit,"%X",(unsigned int)($1));_sbuf[_tmp];})') define(ROWS,`({struct winsize _tmp;ioctl(STDOUT_FILENO,TIOCGWINSZ,&_tmp);_tmp.ws_row;})') define(STR,`({unsigned char _tmp = ++_ptr;_sbuf[_tmp]=GC_malloc(sizeof(char)*_maxdigit);(floor($1) == $1 ? snprintf(_sbuf[_tmp],_maxdigit,"%ld",(long)($1)) : snprintf(_sbuf[_tmp],_maxdigit,"%g",(double)($1)));_sbuf[_tmp];})') # Avoid M4 changing text in string literals changecom(`"',`"') divert(0)dnl #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <math.h> #include <time.h> #include <sys/ioctl.h> #include <gc.h> #define _MEMTYPE char #define _maxdigit 32 #define _bufsize 256 int main(int argc, char* argv[]){ int RETVAL; unsigned char _ptr = 0; char *_sbuf[256] = { NULL }; GC_INIT(); srandom((unsigned int)time(NULL)); m4wrap(`_FC return(0);}')dnl
Return to M4BASIC