M4BASIC - basic.m4
Not logged in
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