#include #include #include char outfilename[255] = "bf-default.asm"; //name of the outputfile char infilename[255]; //name of the inputfile int parsepos = 0; //current position in file int arraysize = 0; //arraysize of bfCode (variable) int* bfCode = NULL; //array of bfCode int whilecount = 0; //counts the while-loops int lastchar = 0; //for optimization int charcount = 0; //for optimization /* * validate commandline arguments, set global variables as required or inform user of usage and quit the program */ int validateArguments(int argc, char *argv[]) { switch(argc){ //fall ohne angabe des outfile case 2: { strcpy(infilename, argv[1]); return 1; } //fall mit angabe des outfile case 4: { if(!strcmp(argv[1], "-o")){ strcpy(outfilename, argv[2]); strcpy(infilename, argv[3]); return 1; } } default: { printf("invalid arguments!\n"); return 0; } } } int checkChar(int command){ switch(command){ case 43: // + case 45: // - case 62: // > case 60: // < case 46: // . case 44: // , case 91: // [ case 93: // ] return 1; break; default: return 0; } } int checkSimpleCommand(int command){ switch(command){ case 43: // + case 45: // - case 62: // > case 60: // < case 46: // . case 44: // , return 1; break; default: return 0; } } int parseSimpleCommand(){ if(checkSimpleCommand(bfCode[parsepos])){ return 1; } printf("Error: Not a simple command!\n"); return 0; } int parseWhileCommand(){ if( bfCode[parsepos] != '['){ printf("Error: While not started!\n"); return 0; } parsepos++; //skip [ while( bfCode[parsepos] != ']') { if(parseCommand() != 1){ return 0; } if(parsepos++ >= arraysize){ printf("Error: While not ended!\n"); return 0; } } return 1; } int parseCommand(){ if(bfCode[parsepos] == 0){ printf("Compiling File %s succesfull!\n", infilename); arraysize = parsepos; return 1; } if( bfCode[parsepos] == '['){ return parseWhileCommand(); } return parseSimpleCommand(); } int parseProgram(){ while( parsepos < arraysize ) { if(parseCommand() == 0){ return 0; } parsepos++; } } //Some functions for assemblercode void generateHead(FILE * pFile){ //Head fputs( ".data\n" , pFile); fputs( "\t curStackPos: .long 0\n" , pFile); fputs( "\t datafield: .long 0\n" , pFile); fputs( "\t\t\t .align 65536\n" , pFile); fputs( "\t maxStack:\t.long 65536\n" , pFile); fputs( "\t intout:\t.string \"%c\"\n" , pFile); fputs( "\t endofline:\t.string \"\\n\"\n" , pFile); fputs( "\n" , pFile); fputs( ".text\n" , pFile); fputs( ".globl main\n" , pFile); fputs( "\n" , pFile); //Main fputs( "main:\n" , pFile); fputs( "\t call bfCode\n" , pFile); fputs( "\t jmp end\n" , pFile); fputs( "\n" , pFile); //End fputs( "end:\n" , pFile); fputs( "\t pushl $endofline\n" , pFile); fputs( "\t call printf\n" , pFile); fputs( "\t movl $1, %eax\n" , pFile); fputs( "\t int $0x80\n" , pFile); fputs( "\n" , pFile); //Check Stack, ends Programm if > MaxStack fputs( "checkStack:\n" , pFile); fputs( "\t movl curStackPos, %ebx\n" , pFile); fputs( "\t movl maxStack, %ecx\n" , pFile); fputs( "\t cmp %ecx, %ebx\n" , pFile); fputs( "\t jge end\n" , pFile); fputs( "\t ret\n" , pFile); fputs( "\n" , pFile); //Get Stack @ curStackPos; result = %eax fputs( "getStack:\n" , pFile); fputs( "\t call checkStack\n" , pFile); fputs( "\t movl curStackPos, %ecx\n" , pFile); fputs( "\t movl datafield(, %ecx, 4), %eax\n" , pFile); fputs( "\t ret\n" , pFile); fputs( "\n" , pFile); //Set Stack @ curStackPos; input = %eax fputs( "setStack:\n" , pFile); fputs( "\t call checkStack\n" , pFile); fputs( "\t movl curStackPos, %ecx\n" , pFile); fputs( "\t movl %eax, datafield(, %ecx, 4)\n" , pFile); fputs( "\t ret\n" , pFile); fputs( "\n" , pFile); //ReadInput, reads from terminal fputs( "readInput:\n" , pFile); fputs( "\t xor %ecx, %ecx\n" , pFile); //Register nullen fputs( "\t xor %edi, %edi\n" , pFile); //sys_READ : fputs( "\t movl $0, %ebx\n" , pFile); // was soll gemacht werden? (0 -> STDIN) fputs( "\t pushl $0\n" , pFile); fputs( "\t leal (%esp), %ecx\n" , pFile); // %ecx beinhaltet Adresse von Speicherziel (Speicherziel: datafield( (%edi = 0), 4) fputs( "\t movl $3, %eax\n" , pFile); // syscalltyp (3 -> sys_read) fputs( "\t movl $1, %edx\n" , pFile); // Länge der Eingabe (hier 8 = 1byte) fputs( "\t int $0x80\n" , pFile); // eigentlicher syscall fputs( "\t popl %eax\n" , pFile); fputs( "\t pushl $0\n" , pFile); fputs( "\t addl $4, %esp\n" , pFile); fputs( "\t ret\n" , pFile); fputs( "\n" , pFile); //WriteOutput, writes to terminal fputs( "writeOutput:\n" , pFile); fputs( "\t pushl %eax\n" , pFile); fputs( "\t pushl $intout\n" , pFile); fputs( "\t call printf\n" , pFile); fputs( "\t popl %eax\n" , pFile); fputs( "\t popl %eax\n" , pFile); fputs( "\t pushl $0\n" , pFile); fputs( "\t pushl $0\n" , pFile); fputs( "\t addl $8, %esp\n" , pFile); fputs( "\t ret\n" , pFile); fputs( "\n" , pFile); //Bf-Code fputs( "\n" , pFile); fputs( "bfCode:\n" , pFile); fputs( "\n" , pFile); } void generatePlus(FILE * pFile, int count){ fprintf(pFile, "# Plus (%d mal):\n" , count); fputs( "\t call getStack\n" , pFile); fprintf(pFile, "\t movl $%d, %%ebx\n" , count); fputs( "\t addl %ebx, %eax\n" , pFile); fputs( "\t call setStack\n" , pFile); fputs( "\n", pFile); } void generateMinus(FILE * pFile, int count){ fprintf(pFile, "# Minus (%d mal):\n" , count); fputs( "\t call getStack\n" , pFile); fprintf(pFile, "\t movl $%d, %%ebx\n" , count * -1); fputs( "\t addl %ebx, %eax\n" , pFile); fputs( "\t call setStack\n" , pFile); fputs( "\n" , pFile); } void generateGroesser(FILE * pFile, int count){ fprintf(pFile, "# Groesser (%d mal):\n" , count); fputs( "\t movl curStackPos, %eax\n" , pFile); fprintf(pFile, "\t addl $%d, %%eax\n" , count);; fputs( "\t movl %eax, curStackPos\n" , pFile); fputs( "\n" , pFile); } void generateKleiner(FILE * pFile, int count){ fprintf(pFile, "# Kleiner (%d mal):\n" , count); fputs( "\t movl curStackPos, %eax\n" , pFile); fprintf(pFile, "\t subl $%d, %%eax\n" , count);; fputs( "\t movl %eax, curStackPos\n" , pFile); fputs( "\n" , pFile); } void generatePunkt(FILE * pFile, int count){ fputs( "# Punkt:\n" , pFile); while(count > 0){ fputs( "\t call getStack\n" , pFile); fputs( "\t call writeOutput\n" , pFile); count--; } } void generateKomma(FILE * pFile, int count){ fputs( "# Komma:\n", pFile); while(count > 0){ fputs( "\t call readInput\n" , pFile); fputs( "\t call setStack\n" , pFile); count--; } } void generateWhileStart(FILE * pFile, int whileNo){ fprintf(pFile, "# WhileBegin%d:\n" , whileNo); fprintf(pFile, "WhileBegin%d:\n" , whileNo); fputs( "\tcall getStack\n" , pFile); fputs( "\tcmp $0, %eax\n" , pFile); fprintf(pFile, "je WhileEnd%d\n" , whileNo); fputs("\n", pFile); } void generateWhileEnd(FILE * pFile, int whileNo){ fprintf(pFile, "# WhileEnd%d:\n" , whileNo); fprintf(pFile, "jmp WhileBegin%d\n" , whileNo); fprintf(pFile, "WhileEnd%d:\n" , whileNo); } int generateSimpleCommandCode(FILE * pFile){ if(lastchar != 0){ switch(lastchar){ case 43: // + generatePlus(pFile,charcount); break; case 45: // - generateMinus(pFile,charcount); break; case 62: // > generateGroesser(pFile,charcount); break; case 60: // < generateKleiner(pFile,charcount); break; case 46: // . generatePunkt(pFile,charcount); break; case 44: // , generateKomma(pFile,charcount); break; default: printf("ERROR: Not a Simple Command\n"); return 0; } } lastchar = 0; charcount = 0; return 1; } int generateSimpleCommand(FILE * pFile){ if(bfCode[parsepos] == lastchar){ charcount++; } else { generateSimpleCommandCode(pFile); lastchar = bfCode[parsepos]; charcount = 1; } return 1; } int generateWhileCommand(FILE * pFile){ if( bfCode[parsepos] != '['){ printf("Error: While not Started\n"); return 0; } parsepos++; //skip [ int myWhileCount = whilecount++; generateWhileStart(pFile, myWhileCount); while( bfCode[parsepos] != ']') { if(generateCommand(pFile) != 1){ return 0; } if(parsepos++ >= arraysize){ printf("Error: While not Ended\n"); return 0; } } generateSimpleCommandCode(pFile); generateWhileEnd(pFile, myWhileCount); return 1; } int generateCommand(FILE * pFile){ if( bfCode[parsepos] == '['){ generateSimpleCommandCode(pFile); return generateWhileCommand(pFile); } return generateSimpleCommand(pFile); } int generateCode(){ FILE * pFile; pFile = fopen(outfilename, "w"); parsepos = 0; generateHead(pFile); while( parsepos < arraysize ) { if(generateCommand(pFile) == 0){ return 0; } parsepos++; } if(charcount != 0){ generateSimpleCommandCode(pFile); } fputs("\t ret", pFile); return 1; } int scanner(const char *file){ FILE * pFile; // open file pFile = fopen(file, "r"); //file opend? if (pFile == NULL){ printf("Error: Could not open Inputfile\n"); return 0; } //int fürs aktuelle Zeichen int lc; //how many chars did we read? int i = 0; //Sind wir im linecomment? int linecomment = 0; while((lc = fgetc(pFile)) != EOF){ if(lc == ';'){ linecomment = 1; continue; } if(lc == '\n'){ linecomment = 0; continue; } if( !linecomment && checkChar(lc) != 0){ if(arraysize <= i+1){ //Resize Array if needed arraysize = (arraysize*2 + 1); //+ 1 for arraysize = 0 bfCode = (int*) realloc(bfCode,arraysize * sizeof(int)); } bfCode[i] = lc; i++; } } //DEBUG //int j; //for(j = 0; j <= 8; j++){ //printf("%d\n", bfCode[j]);} //done fclose(pFile); return 1; } int main (int argc, char *argv[]) { //checks arguments and sets in- / outfilename if(validateArguments(argc, argv)){ //Scanns in the file, strips all non-bf-chars if(scanner(infilename)){ //Check Syntax if(parseProgram()){ //Generate asm Code if(generateCode()){ return 1; //SUCCESS } else {return 0;} //Generate Error } else {return 0;} //Syntax Error } else {return 0;} //Scanner Error } else {return 0;} //Arguments Error }