/* MasAsm - written by Jared Bruni www.lostsidedead.com assembler, for the MAS bytecode written in the C programming language decided to change up my style for this one for practice */ #include "thehead.h" // variables char* sourcecode = NULL; int err_count = 0; struct ProgramHeader prog; char filepath[100]; // function prototypes void loadsource(const char *source); void assemble(); void printerrorf( const char *source, ...); void getname(); void getblocks(); void initblocks(); void clearblocks(); void getblock(int pos, char *data, char *name); void procblocks(); void procvariables(int i); void procvconst(); void procvdec(int i); void proccode(int i); BOOL procinc(char* inc, char *data); BOOL inctobyte(char *ins, char *op1, char *op2, int opnum, char *bytecode); void addvar(char *dec); void debugprintout(); void outputmve(); void getvarnamebydata(char* data,char* name); void getvarindexbydata(char* data, char* datastr); void constfix(); BOOL quotecheck(); BOOL blockcheck(); BOOL concheck(); BOOL varcheck(); BOOL outblockcheck(); BOOL outblockcheck2(); BOOL invalidcharcheck(); BOOL isvar(char *var); int varindexbyname(char* var); void getvarbyname(char *name, char *data); void getvarbyindex( int index, char *data); void setvarbyname(char *name, char *data); void setvarbyindex(int index, char *data); int varbyconst(char* con); int gettypebyname(char* name); // print a error found in source code void printerrorf( const char *source, ...) { va_list list; char* string; err_count++; string = malloc(strlen(source)+1); va_start(list, source); vsprintf((char*)string,source,list); va_end(list); printf("error: %s\n",string); free(string); string = 0; } // main function void main(int count, char** argument) { int last_s; printf("\nmasasm - assembler version %i\n\nwritten by Jared Bruni\n\nwww.lostsidedead.com\n\n",MASASM_VERSION); last_s = bfindstr(argument[0],"\\"); leftcopy(argument[0],filepath,last_s+1); // contains the last backslash if(count == 1) { printf("\nsyntax error: requires parameters\n\ncorrect syntax\n\nmasasm sourcename.mas\n\n\n"); system("pause"); return; } if(isfile(argument[1]) == FALSE) { printf ("\nfatal error: file (%s) not found!",argument[1]); printf ("\n\n\n\n"); system("pause"); return; } sourcecode = malloc (flen(argument[1]) + 1); initblocks(); loadsource(argument[1]); assemble(); // watch out for this one debugprintout(); if( err_count == 0 ) { printf("\n%s assemebled with (0) errors\n",argument[1]); // output file outputmve(); } else { printf("\n%s assembled with (%i) errors\n",argument[1],err_count); } // clean up after words if(sourcecode != NULL) { free(sourcecode); } clearblocks(); system("pause"); } // debug printout void debugprintout() { FILE* file; int i; char fname[100]; strcpy(fname,filepath); strcat(fname,"debugasm.html"); printf("\noutputing debug file to: %s",fname); file = fopen(fname,"w"); fprintf(file,"masasm assembler debug output, written by Jared Bruni

\n\nwww.lostsidedead.com
\n"); fprintf(file,"\n\n

variable list
\n\n"); if(prog.var != NULL) { for(i = 0; i < prog.voff; i++) { fprintf(file,"
variable name: %s value ( %s ) \n
",prog.var[i].name,prog.var[i].data); } } fprintf(file,"\n

code blocks

\n\n"); for(i = 1; i < prog.num; i++) { fprintf(file,"\n
code block (proc/con/var) %s \n
{
\n%s\n
}
\n",prog.blocks[i].name,prog.blocks[i].data); } fprintf(file,"
"); fclose(file); } // output mve (output the executable) void outputmve() { // produce the executable file with MAS bytecode FILE* ofile; char iname[100]; int i; sprintf(iname,"%s%s.mve",filepath,prog.name); printf("\n\nexecutable outputed to: %s\n\n",iname); killline(iname); ofile = fopen(iname,"w"); fprintf(ofile,"var{"); // print out variables, and constant variables for(i = 0; i < prog.voff; i++) { char mtype[10]; if(prog.var[i].type == TYPE_STRING) { strcpy(mtype,"$"); } else { if(prog.var[i].type == TYPE_REAL) { strcpy(mtype,"#"); } else { strcpy(mtype,"&"); } } if( i != prog.voff - 1 ) { fprintf(ofile,"%s%s:\"%s\",",prog.var[i].name,mtype,prog.var[i].data); } else { fprintf(ofile,"%s%s:\"%s\"",prog.var[i].name,mtype,prog.var[i].data); } } fprintf(ofile,"}"); // print out all the code blocks for(i = 1; i < prog.num; i++) { if(strcmp(prog.blocks[i].name,"variables") != 0) { fprintf(ofile,"%s{%s}",prog.blocks[i].name,prog.blocks[i].cdata); } } fclose(ofile); } // load up the source void loadsource(const char *source) { readfile(source,sourcecode); } // begin assembly proccess void assemble() { trimr(sourcecode); trimcomments(sourcecode); constfix(); // ensure data is valid for block proccessing if(quotecheck() == FALSE || blockcheck() == FALSE || concheck() == FALSE || varcheck() == FALSE || outblockcheck() == FALSE || outblockcheck2() == FALSE || invalidcharcheck() == FALSE) { return; } killwspace(sourcecode); lcase(sourcecode); getname(); getblocks(); procblocks(); } // fix the constants void constfix() { int i,len = strlen(sourcecode),pos = 0; BOOL go = FALSE; char* temp; temp = malloc(len + 1); for(i = 0; i < len; i++) { if(sourcecode[i] == '\"') { if(go == TRUE) { go = FALSE; } else { temp[pos] = sourcecode[i]; pos++; go = TRUE; continue; } } if(go == TRUE) { switch(sourcecode[i]) { case ' ': temp[pos] = 'µ'; break; case '\n': temp[pos] = '¶'; break; case '\r': temp[pos] = 'Ý'; break; default: temp[pos] = sourcecode[i]; break; } } else { temp[pos] = sourcecode[i]; } pos++; } temp[pos] = 0; strcpy(sourcecode,temp); free(temp); } // get the objects name void getname() { char name[100]; int mas; int obrace; mas = findstr(sourcecode,"mas object"); if(mas == -1) { printerrorf(" program missing mas object implementation"); return; } obrace = ifindstr(mas,sourcecode,"{"); if(obrace == -1) { printerrorf(" missing the first opening brace "); return; } midcopy(sourcecode,name,mas + 10,obrace); killspace(name); if(strlen(name) == 1) { printerrorf(" this mas object requires a name"); return; } strcpy(prog.name,name); } // get the opening code blocks void getblocks() { int ocount; int ccount; int i = 0, len = strlen(sourcecode); int blocks = 0; ocount = findoccourance(sourcecode,'{'); ccount = findoccourance(sourcecode,'}'); if(ocount != ccount) { printerrorf(" code blocks do not allign, your missing a { or a } somewere"); return; } // make room for the blocks prog.blocks = (struct CodeBlock*)malloc( ocount * sizeof (struct CodeBlock)); for(i = 0; i < len; i++) { if(sourcecode[i] == '{' ) { char *cblock = NULL; char cname[100]; cblock = malloc(strlen(sourcecode) + 1); getblock(i,cblock,cname); prog.blocks[blocks].data = malloc(strlen(sourcecode) + 1); strcpy(prog.blocks[blocks].data,cblock); strcpy(prog.blocks[blocks].name,cname); blocks++; if(cblock != NULL) { free(cblock); } } } prog.num = blocks; for(i = 0; i < blocks; i++) { prog.blocks[i].cdata = NULL; } } // get the block void getblock(int pos, char *block, char *blockname) { int oc = 0; int cc = 0; int i,len = strlen(sourcecode); int pr; int co; int de; int va; int cpos = 0; int open_b; int close_b; int noff = 0; for(i = pos-1; i < len; i++) { if(sourcecode[i] == '{') { oc++; if(oc == 1) { open_b = i; } } if(sourcecode[i] == '}') { cc++; if(oc == cc) { close_b = i; break; } } } midcopy(sourcecode,block,open_b+1,close_b); pr = ibfindstr(pos,sourcecode,"proc"); co = ibfindstr(pos,sourcecode,"constructor"); de = ibfindstr(pos,sourcecode,"deconstructor"); va = ibfindstr(pos,sourcecode,"var"); if(sourcecode[co-1] == 'e') { co = ibfindstr(co-1,sourcecode,"constructor"); } if(pr > co && pr > de && pr > va) { cpos = pr; } if( co > pr && co > de && co > va) { cpos = co; } if( de > co && de > pr && de > va) { cpos = de; } if( va > de && va > co && va > pr) { cpos = va; } midcopy(sourcecode,blockname,cpos,pos); nametrim(blockname); } // clear the blocks void clearblocks() { int i; for(i = 0; i < prog.num; i++) { free(prog.blocks[i].data); if(prog.blocks[i].cdata != NULL) { free(prog.blocks[i].cdata); } } if(prog.blocks != NULL) { free(prog.blocks); } for(i = 0; i < prog.vnum; i++) { if(prog.var[i].data != NULL) { free(prog.var[i].data); } } if(prog.var != NULL) { free(prog.var); } } // initilize the blocks void initblocks() { prog.blocks = NULL; prog.num = 0; prog.var = NULL; prog.vnum = 0; prog.voff = 0; } // check and see if quotes line up correctly BOOL quotecheck() { int oq; // find the occourance of quotes // then use the moduls operator, to see if it is a even value // if it is not, then print a error message oq = findoccourance(sourcecode,'"')%2; if(oq != 0) { printerrorf(" quotes do not allign, somewere your forgot a ending \" "); return FALSE; } return TRUE; } // check and see if the blocks are event, if not, we dont want to continue BOOL blockcheck() { int ob = findoccourance(sourcecode,'{'); int cb = findoccourance(sourcecode,'}'); if(ob == cb) { return TRUE; } printerrorf(" blocks to not allign, somewere you forgot a opening { or closing }"); return FALSE; } // check and see if nessicary code blocks, exisit (like var, and constructor) BOOL concheck() { int vchk; int cchk; int dchk; vchk = findstr(sourcecode,"variables"); cchk = findstr(sourcecode,"constructor"); dchk = findstr(sourcecode,"deconstructor"); if(vchk == NULLPOS) { printerrorf(" missing the variables code block "); return FALSE; } if(cchk == NULLPOS || sourcecode[cchk-1] == 'e') { printerrorf(" object missing constructor "); return FALSE; } if(dchk == NULLPOS) { printerrorf(" object missing deconstructor "); return FALSE; } vchk = ifindstr(vchk+1,sourcecode,"variables"); if(vchk != NULLPOS) { printerrorf(" more then one variables block in mas object"); return FALSE; } cchk = ifindstr(cchk+1,sourcecode,"constructor"); if(sourcecode[cchk-1] == 'e') { cchk = ifindstr(cchk+1,sourcecode,"constructor"); } if(cchk != NULLPOS) { printerrorf(" more then one constructor block in mas object"); return FALSE; } dchk = ifindstr(dchk+1,sourcecode,"deconstructor"); if(dchk != NULLPOS) { printerrorf(" more then one deconstructor block in mas object"); return FALSE; } return TRUE; } // ensure that variables , and variable declerations are alright BOOL varcheck() { int i = 0, len = strlen(sourcecode); for(i; i < len; i++) { if(sourcecode[i] == '\"' && sourcecode[i+1] == '\"') { char err[200]; int line; line = linebypos(sourcecode,i); sprintf(err," on line (%i) there is a null constant (2 quotes ""), .. null constants are illegal",line); printerrorf(err); return FALSE; } } return TRUE; } // ensure that there is no 'junk' data in invalid positions, unless they are comments BOOL outblockcheck() { int i, len = strlen(sourcecode),lo; BOOL igo = TRUE; lo = bfindstr(sourcecode,"}") + 1; // find the very last } // ensure that there is no invalid data after the last } for(i = lo; i < len; i++) { if(sourcecode[i] == ';') { igo = FALSE; continue; } if(sourcecode[i] == '\n') { igo = TRUE; } if(igo == TRUE) { if( sourcecode[i] != ' ' && sourcecode[i] != 10 && sourcecode[i] != 13 ) { int line = linebypos(sourcecode,i); printerrorf(" invalid character (%c) on line (%i) (why code after last })",sourcecode[i],line); return FALSE; } } } // search before the first { lo = findstr(sourcecode,"mas"); if(lo != -1) { lo -= 3; for(i = lo; i > 0; i--) { if(sourcecode[i] == ';') { igo = FALSE; continue; } if(sourcecode[i] == '\n') { igo = TRUE; } if(igo == TRUE) { if( sourcecode[i] != ' ' && sourcecode[i] != 10 && sourcecode[i] != 13 ) { int line = linebypos(sourcecode,i); printerrorf(" invalid character (%c) on line (%i) (why data before first block?)",sourcecode[i],line); return FALSE; } } } } return TRUE; } // check and sife if there is invalid out of place data inside of the mas objects blocks BOOL outblockcheck2() { // this is commented out because I have it automaticly truncate data outside of the blocks // in the wrong spots /* char* temp = NULL; int i, pos = 0, len = strlen(sourcecode); temp = malloc( strlen(sourcecode) + 1 ); // allocate data for(i = 0; i < len; i++) { if(sourcecode[i] != '\n' && sourcecode[i] != '\r') { temp[pos] = sourcecode[i]; pos++; } } temp[pos] = 0; free(temp); // free up allocated data */ /* int i = 0,z,q, len = bfindstr(sourcecode,"}"); for(i = findstr(sourcecode,"{") + 1; i < len; i++) { if(sourcecode[i] == '{') { for(z = i-1; z > 0; z--) { if(sourcecode[z] != ' ' && sourcecode[z] != 10 && sourcecode[z] != 13) { for(q = z; q > 0; q--) { char cx[1]; if(sourcecode[q] == '}') { break; } cx[0] = sourcecode[q]; cx[1] = 0; MessageBox(0,cx,"",0); } } } } }*/ return TRUE; } // search through the string, for any characters which are not accepted by the assembler // exclude those inside of "" BOOL invalidcharcheck() { int i , len = strlen(sourcecode); BOOL igo = TRUE; for(i = 0; i < len; i++) { if(sourcecode[i] == '\"') { if(igo == TRUE) { igo = FALSE; } else { igo = TRUE; } } if(igo == TRUE) { if(ismaschar(sourcecode[i]) == FALSE) { // here char err[100]; int line; line = linebypos(sourcecode,i); sprintf(err," invalid character (%c) on line (%i) was this an accident? ", sourcecode[i],line); printerrorf(err); return FALSE; } } } return TRUE; } // proccess the code blocks void procblocks() { int i; for(i = 1; i < prog.num; i++) { // ensure no there are nested code blocks if(findstr(prog.blocks[i].data,"}") != -1 || findstr(prog.blocks[i].data,"}") != -1) { char err[100]; sprintf(err," the code block (%s) contains invalid data ( a { or a }), you cannot nest blocks",prog.blocks[i].name); // error block contains invalid data printerrorf(err); return; } if(findstr(prog.blocks[i].name,"variables") != -1) { procvariables(i); } else { proccode(i); } } } // proccess the variables code block void procvariables(int i) { int qcount; int fpos; int j; // first lets find out exactly how many slots for variables, we will have fpos = findstr(prog.blocks[i].data,"var"); // find all " ", (locate all constant variables first) qcount = findoccourance( sourcecode, '"') / 2; if(fpos != -1) { qcount ++; } while(fpos != -1) { fpos = ifindstr(fpos+1,prog.blocks[i].data,"var"); if(fpos != -1) { qcount++; } } prog.var = (struct Variables*) malloc(qcount * sizeof(struct Variables)); for(j = 0; j < qcount; j++) { prog.var[j].data = NULL; } prog.vnum = qcount; // first add in all constant variables procvconst(); // then add in all variable declerations procvdec(i); // after all variable declerations have been added in // modify the source code, so that it contains the corret address } // load all the constant variables, into the variable table void procvconst() { int i,len = strlen(sourcecode); BOOL qopen = FALSE; char *temp; int tindex = 0; int cnum = 0; char tempname[20]; temp = malloc ( strlen( sourcecode ) ); for(i = 0; i < len; i++) { if(sourcecode[i] == '"') { if(qopen == TRUE) { qopen = FALSE; temp[tindex] = 0; tindex = 0; sprintf(tempname,"con%i",cnum); cnum++; strcpy(prog.var[prog.voff].name,tempname); prog.var[prog.voff].data = malloc ( strlen(temp) + 1); strcpy(prog.var[prog.voff].data,temp); prog.var[prog.voff].type = TYPE_STRING; prog.voff++; } else { qopen = TRUE; i++; } } if(qopen == TRUE) { temp[tindex] = sourcecode[i]; tindex++; } } temp[tindex] = 0; free(temp); } // load all the declared variables into the variable table void procvdec(int i) { int len = strlen(prog.blocks[i].data); int z; int lcopy = 0; char *temp; temp = malloc (strlen(sourcecode)+1); for(z = 0; z < len; z++) { if(prog.blocks[i].data[z] == '\n') { midcopy(prog.blocks[i].data,temp,lcopy,z); lcopy = z; killspace(temp); if(strlen(temp) > 1) { addvar(temp); } } } free(temp); } // add a variable, declared in variables section void addvar(char *dec) { int fvar; char name[25]; int atype = TYPE_NULL; int es,chk; if(strlen(dec) < 3) { printerrorf("invalid statement in variable code block\n"); return; } fvar = findstr(dec,"var"); if(fvar == -1) { printerrorf("invalid statement only variable declerations in variable code block!"); return; } if( dec[fvar+3] != '$' && dec[fvar+3] != '&' && dec[fvar+3] != '#') { printerrorf(" invalid variable decleration, missing variable type (&(unsigned long), #(double),$(string))"); return; } if( iop(dec) ) { printerrorf(" variable block contains invalid characters!"); return; } rightcopy( dec, name, fvar+4); // decide which variable type switch(dec[fvar+3]) { case '$': atype = TYPE_STRING; break; case '&': atype = TYPE_NUMERIC; break; case '#': atype = TYPE_REAL; break; } // my ode to pascal es = findstr(dec,":="); chk = findstr(dec,":"); if(dec[chk+1] != '=' && chk != -1) { printerrorf(" invalid variable decleration unknown character ':'"); return; } chk = findstr(dec,"="); if(dec[chk-1] != ':' && chk != -1) { printerrorf(" invalid variable decleration unknown character '='"); return; } if(es == FAIL) { if(checkvname(name) == FALSE) { printerrorf(" variable declerations, contain duplicate variable names", name); return; } strcpy(prog.var[prog.voff].name,name); prog.var[prog.voff].type = atype; prog.var[prog.voff].data = NULL; } else { char *temp; int epos; temp = malloc ( strlen(dec) + 1); rightcopy( dec, temp,es+2); if(atype == TYPE_NUMERIC) { killline(temp); if(findstr(temp,"\"") != FAIL) { printerrorf(" invalid delceration, trying to assign string to numeric variable"); goto ifree; } epos = findstr(name,":="); leftcopy(name,prog.var[prog.voff].name,epos); // variable name already exisits if(checkvname(prog.var[prog.voff].name) == FALSE) { printerrorf(" variable name (%s) already exisits!", prog.var[prog.voff].name); strcpy(prog.var[prog.voff].name,""); free(temp); return; } prog.var[prog.voff].data = malloc (strlen(temp)+1); strcpy(prog.var[prog.voff].data,temp); prog.var[prog.voff].type = TYPE_NUMERIC; } if(atype == TYPE_STRING) { printerrorf(" string data types, do not allow assignment operator :="); } if(atype == TYPE_REAL) { printerrorf(" real numbers cannot use the assignment operator := use mov on the constructor to assign a value"); } ifree: free(temp); } prog.voff++; } // check and see if a variable name already exisits BOOL checkvname(char *name) { int i; for(i = 0; i < prog.voff; i++) { // name already exisits if(strcmp(prog.var[i].name,name) == 0) { return FALSE; } } return TRUE; } // get the variable index by its name int getvarindexbyname(char* name) { int i; for(i = 0; i < prog.voff; i++) { if(strcmp(prog.var[i].name,name) == 0) { return i; } } return FAIL; // is not a variable } // get the variable index by its data void getvarindexbydata(char* data, char* datastr) { char* temp; char* tempdata; int i; tempdata = malloc (strlen(data) + 1); strcpy(tempdata,data); trimquotes(tempdata); killspace(tempdata); killline(tempdata); for(i = 0; i < prog.voff; i++) { temp = malloc( strlen(prog.var[i].data) + 1); strcpy(temp,prog.var[i].data); trimquotes(temp); killspace(temp); killline(temp); if(findstr(temp,tempdata) != -1) { strcpy(datastr,prog.var[i].name); free(temp); free(tempdata); return; } free(temp); } free(tempdata); strcpy(datastr,""); } // get a variable by its name void getvarbyname(char *name, char *data) { int i; for(i = 0; i < prog.voff; i++) { if( strcmp ( prog.var[i].name, name ) == 0 ) { strcpy (data, prog.var[i].data); return; } } strcpy( data, ""); return; } // get the name of this variable, by what is inside it void getvarnamebydata(char* data,char* name) { int i; for(i = 0; i < prog.voff; i++) { if( strcmp(prog.var[i].data,data) == 0) { strcpy(name,prog.var[i].name); return; } } strcpy(name,""); } // get a variable by its index void getvarbyindex(int index, char *data) { strcpy(data,prog.var[index].data); } // set variable by name void setvarbyname(char *name, char *data) { int i; for(i = 0; i < prog.voff; i++) { // copy into buffer if(strcmp(prog.var[i].name ,name) == 0) { if(prog.var[i].data != NULL) { free(prog.var[i].data); } prog.var[i].data = malloc ( strlen(data) + 1); strcpy(prog.var[i].data, data); return; } } return; // not found } // set variable by index void setvarbyindex(int index, char *data) { if(prog.var[index].data != NULL) { free(prog.var[index].data); } prog.var[index].data = malloc ( strlen(data) + 1); strcpy(prog.var[index].data,data); } // does this variable name exisit? BOOL isvar(char *var) { int i; for(i = 0; i < prog.voff; i++) { // yep it exisits if(strcmp(prog.var[i].name,var) == 0) { return TRUE; } } return FALSE; } // return the type of variable by its name int gettypebyname(char* name) { int i; for(i = 0; i < prog.voff; i++) { if(strcmp(prog.var[i].name,name) == 0) { return prog.var[i].type; } } return TYPE_NULL; } // proccess code block void proccode(int i) { // build up each code block for instructions int offpos = 0; int z = 0; int len = strlen(prog.blocks[i].data); char *temp; char *source; int first = 0; BOOL zgo = TRUE; source = malloc( strlen(sourcecode) * 2); // make it big just in case strcpy(source,""); temp = malloc( len + 1 ); for(z = 0; z < len; z++) { if(prog.blocks[i].data[z] == '\"') { if( zgo == TRUE ) { zgo = FALSE; } else { zgo = TRUE; } } if(zgo == FALSE) { continue; } if(prog.blocks[i].data[z] == '\n') { char *addinc = NULL; BOOL ok; midcopy(prog.blocks[i].data,temp,offpos,z); offpos = z; addinc = malloc(strlen(temp)+100); ok = procinc(temp,addinc); if(ok == TRUE) { // concatinate to exisiting string if(first == 1 && z != len) { strcat(source,","); } else { first++; } strcat(source,addinc); } free(addinc); } } // copy over into the correct buffer prog.blocks[i].cdata = malloc(strlen(source)+1); strcpy(prog.blocks[i].cdata,source); free(source); free(temp); } // translate a line of script into bytecode // this is a very important function BOOL procinc(char *script, char *bytecode) { inctrim(script); if(strlen(script) > 2) { int lchk; int i = 0; int il = strlen(script); BOOL igo = TRUE; // first things first // lets break this up into instruction, and operands // first illegal characters check if(cmdcheck(script)) { char errs[100]; sprintf(errs," line of code (%s) contains invalid characters",script); printerrorf(errs); return FALSE; } // ok we only have the characters we need // there instructions can be 2 things // a code label, or a instruction lchk = FAIL; // find the colon, without finding colons inside of the " " for(i = 0; i < il; i++) { if( script[i] == '\"' ) { if(igo == TRUE) { igo = FALSE; } else { igo = TRUE; } } if(igo == TRUE) { if(script[i] == ':') { lchk = i; break; } } } if(lchk != FAIL) { char *temp; temp = malloc ( strlen(script) + 1); leftcopy(script,temp,lchk); killspace(temp); killline(temp); // totaly ignore data on opposite site of : // pass this code label name, back to the assembler strcpy(bytecode,temp); free(temp); return TRUE; } else { int fcomma,fspace; char *ins = NULL; // the instruction char *op1 = NULL; // the first operand char *op2 = NULL; // the second operand int opnum = 0; // the number of operands BOOL iok; // was the instruction translation ok? int ic = 0; // counter variable int len = strlen(script); BOOL igo = TRUE; ins = malloc ( strlen(script) + 1); op1 = malloc ( strlen(script) + 1); op2 = malloc ( strlen(script) + 1); // its a instruction // that means it can have 2 forms // ethier // mov ax // or // mov ax,bx // fcomma = findoccourance(script,','); fcomma = 0; // special search, make sure not to count commas, inside of " " for(ic = 0; ic < len; ic++) { if( script[ic] == '\"' ) { if(igo == TRUE) { igo = FALSE; } else { igo = TRUE; } } if(igo == TRUE) { if( script[ic] == ',' ) { fcomma++; } } } if(findstr(script,"\"") != -1) { fcomma = 0; } if(fcomma > 1) { char str[100]; sprintf(str," error line of code (%s) contains more then one comma",script); printerrorf(str); goto endfail; } // fcomma = findstr(script,","); fcomma = quotesearch(0,script,','); fspace = findstr(script," "); leftcopy(script,ins,fspace); // only has one operand if(fcomma == FAIL) { opnum = 1; rightcopy(script,op1,fspace); } // has two operands else { opnum = 2; midcopy(script,op1,fspace,fcomma); rightcopy(script,op2,fcomma+1); } // pass to function, that proccesses a instruction, and // translates to bytecode if(strlen(ins) == 0) { char err[100]; sprintf(err," invalid instruction or unknown mnemoic (%s) ", script); printerrorf(err); return FALSE; } iok = inctobyte(ins,op1,op2,opnum,bytecode); free(ins); free(op1); free(op2); return iok; endfail: free(ins); free(op1); free(op2); return FALSE; } } return FALSE; } // instruction to bytecode BOOL inctobyte(char *ins, char *op1, char *op2, int opnum, char *bytecode) { int opcode; char opc[10]; if(strlen(ins) == 0) { printerrorf("invalid instruction"); return FALSE; } killline(ins); if(opnum >= 1) { killline(op1); } if(opnum >= 2) { killline(op2); } opcode = isins(ins); if(opcode == FAIL) { char err[75]; sprintf(err," invalid instruction (%s) ",ins); printerrorf(err); return FALSE; } itoa(opcode,opc,16); switch(opcode) { // instruction type [inc][var][var/const] case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: { int op1num; int op2num; char nop1[25]; char nop2[25]; BOOL vchk; BOOL nchk; BOOL vchk2; int vtype = TYPE_NULL; strcpy(bytecode,opc); strcat(bytecode,"!"); vchk = isvar(op1); if(opnum != 2) { printerrorf(" instruction requires only 2 operands"); return FALSE; } if(vchk == FALSE) { char err[100]; sprintf(err," on instruction (%s %s, %s) first operand requires a variable, you have a (%s)",ins,op1,op2,op1); printerrorf(err); return FALSE; } // make sure first operand's variable is of TYPE NUMERIC or TYPE REAL vtype = gettypebyname(op1); if(vtype == TYPE_REAL) { switch(opcode) { case 0x5: case 0x6: case 0x7: { char errorx[100]; sprintf(errorx," invalid type for instruction (%s), please use a unsigned long (&)",ins); printerrorf(errorx); return FALSE; } break; } // trying to use invalid instructions } if(vtype == TYPE_NUMERIC || vtype == TYPE_REAL) { } else { char err[100]; sprintf(err," on instruction (%s %s, %s) first operand requires type of NUMERIC (&) or REAL (#)",ins,op1,op2); printerrorf(err); return FALSE; } strcat(bytecode,"*"); op1num = getvarindexbyname(op1); itoa(op1num,nop1,16); strcat(bytecode,nop1); strcat(bytecode,":"); nchk = isnumeric(op2); vchk2 = isvar(op2); if(nchk == FALSE && vchk2 == FALSE) { char err[100]; sprintf(err," instruction (%s %s,%s) second operand contains invalid data", ins,op1,op2); printerrorf(err); return FALSE; } // it is a variable on the second operand lets get its type vtype = gettypebyname(op2); if(vtype == TYPE_STRING) { char err[100]; sprintf(err," instruction (%s %s,%s) second operand (%s) contains string varaible.. requres numeric or real ",ins,op1,op2,op2); printerrorf(err); return FALSE; } if(vtype != gettypebyname(op1) && nchk == FALSE) { char err[100]; sprintf(err," instruction (%s %s,%s) second operand (%s) contains type other then first operand ( both must be same type )", ins,op1,op2,op2); printerrorf(err); return FALSE; } // ok now // we need to check and see if the variable type is NUMERIC // that there is no DECIMAL point // and we also need to see if the variable type is REAL // that no hex digits exisit vtype = gettypebyname(op1); // operand 1 type switch(vtype) { case TYPE_NUMERIC: { int pchk; pchk = findstr(op2,"."); if(pchk != -1) { char err[150]; sprintf(err," instruction (%s %s,%s) second operand contains constant value containing a decimal point, however your variable type is Numeric & (unsigned long)",ins,op1,op2); printerrorf(err); return FALSE; } } break; case TYPE_REAL: { int j,jlen = strlen(op2); if(gettypebyname(op2) == TYPE_NULL) { for(j = 0; j < jlen; j++) { switch(op2[j]) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': { char err[150]; sprintf(err," instruction(%s %s,%s) second operand contains hexadecimal constant, however the first operand contains type of real (#) a double",ins,op1,op2); printerrorf(err); return FALSE; } break; } } } } break; } if(nchk == TRUE) { strcat(bytecode,op2); } else { strcat(bytecode,"*"); op2num = getvarindexbyname(op2); itoa(op2num,nop2,16); strcat(bytecode,nop2); } return TRUE; } break; // instruction type name [ax] case 0x20: case 0x21: case 0x22: { BOOL vchk; char vstr[50]; int vnum; if(opnum != 1) { char err[50]; sprintf(err," this instruction (%s) requires only 1 operand",ins); printerrorf(err); return FALSE; } vchk = isvar(op1); if(vchk == FALSE) { char err[50]; sprintf(err," operand contains a unknown variable/value (%s)", op1); printerrorf(err); return FALSE; } vnum = getvarindexbyname(op1); itoa(vnum,vstr,16); strcpy(bytecode,opc); strcat(bytecode,"!"); strcat(bytecode,"*"); strcat(bytecode,vstr); strcat(bytecode,":"); strcat(bytecode,"(null)"); return TRUE; } break; // string algorithms operand type 1 case 0x40:// smov ax,bx case 0x41:// scat var,"" { // ensure that the variables are strings char varname[100]; int varadd1;// variable 1 int varadd2;// variable 2 char vadd1[25]; // string for varaible address 1 char vadd2[25]; // string for variable address 2 if(opnum != 2) { char err[50]; sprintf(err," instruction (%s) contains a invalid number of operands",ins); printerrorf(err); return FALSE; } if(findstr(op1,"\"") != -1) { char err[50]; sprintf(err," instruction (%s) cannot take constant as first operand",ins); printerrorf(err); return FALSE; } if(isvar(op1) == FALSE) { char err[50]; sprintf(err," instruction (%s) operand 1 contains unknown variable (%s)",ins,op1); return FALSE; } varadd1 = getvarindexbyname(op1); // second operand is a variable if(findstr(op2,"\"") != -1) { trimquotes(op2); // get variable index by data getvarindexbydata(op2,varname); varadd2 = getvarindexbyname(varname); } else { if(isvar(op2) == FALSE) { char err[50]; sprintf(err,"instruction (%s) operand 2 contains a unknown variable (%s)",ins,op2); printerrorf(err); return FALSE; } varadd2 = getvarindexbyname(op2); } itoa(varadd1,vadd1,16); itoa(varadd2,vadd2,16); strcpy(bytecode,opc); strcat(bytecode,"!"); strcat(bytecode,"*"); strcat(bytecode,vadd1); strcat(bytecode,":"); strcat(bytecode,"*"); strcat(bytecode,vadd2); return TRUE; } break; // string algorithms, with only 1 operand (mprint/minput/miline) case 0x60: case 0x61: case 0x62: case 0x63: { int varadd; char svaradd[50]; char svarname[50]; // not sure why opnum comes up as 2 if(opnum != 1) { char err[50]; sprintf(err," instruction (%s) has a invalid number of operands", ins); printerrorf(err); return FALSE; } if(findstr(op1,"\"") != -1) { getvarindexbydata(op1,svarname); varadd = getvarindexbyname(svarname); } else { if(isvar(op1) == FALSE) { char err[50]; sprintf(err," instruction (%s) contains a invalid variable name (%s)",ins,op1); printerrorf(err); return FALSE; } varadd = getvarindexbyname(op1); } itoa(varadd,svaradd,16); strcpy(bytecode,opc); strcat(bytecode,"!"); strcat(bytecode,"*"); strcat(bytecode,svaradd); strcat(bytecode,":(null)"); return TRUE; } break; } return TRUE; }