Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "assembler.h"
- char *buf;
- size_t buf_n=128;
- FILE *asmfile=0,*outfile=0;
- void processDataSect(int pos);
- void processTextSect(int pos);
- size_t parseVarArgs(void **data,char *str,char length){
- size_t offset=0;
- char *commentptr=0;
- if((commentptr=strstr(str,"//"))) *commentptr=0; //Strip comment.
- loop:
- while(*str==' ' || *str=='\t') str++; //Trim leading whitespace.
- char *strend=str+(strlen(str)-1);
- while(*strend==' ' || *strend=='\t' || *strend=='\n') strend--;
- *(strend+1)=0; //Trim trailing whitespace.
- if(isdigit(*str)){ //Element is integer literal.
- char *endptr=0;
- int v=strtol(str,&endptr,0);
- *data=realloc(*data,(offset+1)*length);
- if(length==1){ //Integer is 8 bit.
- ((char*)*data)[offset]=(char)v;
- offset++;
- }
- else{ //Integer is 32 bit.
- char *datap=((char*)*data)+offset;
- *((int32_t*)datap)=(int32_t)v;
- offset+=sizeof(uint32_t);
- }
- str=endptr+1;
- if(*endptr==',') goto loop;
- else if(*endptr!=0) throwerror(1,"Missing comma\n");
- return offset; //End of string, return.
- }
- else if(*str=='\''){ //Element is character literal.
- str++;
- while(*str!='\''){
- *data=realloc(*data,(offset+1)*length);
- if(length==1){ //Character is 8 bit.
- ((char*)*data)[offset]=(char)*str;
- offset++;
- }
- else{ //Character is 32 bit.
- char *datap=((char*)*data)+offset;
- *((int32_t*)datap)=(int32_t)*str;
- offset+=2;
- }
- str++;
- }
- str+=2;
- if(*(str-1)==',') goto loop;
- else if(*(str-1)!=0) throwerror(1,"Missing comma\n");
- return offset; //End of string, return.
- }
- else if(*str=='#'){ //Element is large data segment.
- str++;
- if(!isdigit(*str)) throwerror(1,"Invalid value\n");
- char *endptr=0;
- int size=strtol(str,&endptr,0);
- *data=realloc(*data,offset+(size*length));
- memset(((char*)*data)+offset,0,size*length);
- offset+=(size*length);
- str=endptr+1;
- if(*endptr==',') goto loop;
- else if(*endptr!=0) throwerror(1,"Missing comma\n");
- return offset; //End of string, return.
- }
- else if(*str=='@'){ //Element is a file embed.
- str++;
- if(*str!='"') throwerror(1,"Expected opening double-quote\n");
- str++;
- char *endptr=strchr(str,'"');
- if(!endptr) throwerror(1,"Expected closing double-quotes\n");
- else{ //Satisfy clang-static-analyzer.
- *endptr=0;
- FILE *fp=fopen(str,"rb");
- if(!fp) throwerror(1,"%s: Could not open file for embedding\n",str);
- fseek(fp,0,SEEK_END);
- size_t size=ftell(fp);
- fseek(fp,0,SEEK_SET);
- *data=realloc(*data,offset+size);
- fread(((char*)*data)+offset,1,size,fp);
- offset+=size;
- fclose(fp);
- str=endptr+2;
- if(*(str-1)==',') goto loop;
- else if(*str!=0) throwerror(1,"Missing comma\n");
- return offset; //End of string, return.
- }
- }
- else throwerror(1,"Invalid value:\n%s\n",str);
- return offset;
- }
- void processDataSect(int pos){
- fseek(asmfile,pos,SEEK_SET);
- while(!feof(asmfile)){
- memset(buf,0,buf_n);
- getline(&buf,&buf_n,asmfile);
- line_n++;
- if(!strcmp(buf,"sect .text\n")) break;
- char *lineptr=buf;
- while(*lineptr=='\t' || *lineptr==' ' || *lineptr=='\n') lineptr++; //Trim leading whitespace.
- if(*lineptr=='/') continue;
- if(!*lineptr) continue;
- int n;
- char name[32];
- char length;
- sscanf(lineptr,"%s %c %n\n",name,&length,&n);
- length=length=='b'?1:sizeof(uint32_t);
- size_t symbol_n=strlen(name)-1;
- if(name[symbol_n]==':') name[symbol_n]=0;
- variable *var=calloc(sizeof(variable),1);
- symbol *l=0;
- char isallocd=0;
- derefSymbol(name,&l);
- if(l==0 || l->type!=SYMBOL_TYPE_GLOBAL){
- l=calloc(sizeof(symbol),1);
- isallocd=1;
- }
- strncpy(l->name,name,32);
- var->length=length;
- var->data_n=parseVarArgs(&var->data,lineptr+n,length);
- l->address=addr;
- l->line=line_n;
- addr+=var->data_n;
- table_add(vt,var,sizeof(*var));
- if(l->type==SYMBOL_TYPE_LOCAL) table_add(st,l,sizeof(*l));
- else if(isallocd) free(l);
- }
- return;
- }
- void processTextSect(int pos){
- fseek(asmfile,pos,SEEK_SET);
- while(!feof(asmfile)){
- memset(buf,0,buf_n);
- getline(&buf,&buf_n,asmfile);
- line_n++;
- if(!strcmp(buf,"sect .data\n")) break;
- char *lineptr=buf;
- while(*lineptr=='\t' || *lineptr==' ' || *lineptr=='\n') lineptr++; //Trim leading whitespace.
- if(!*lineptr) continue;
- char opcode[32];
- memset(opcode,0,32);
- int n;
- sscanf(lineptr,"%s%n",opcode,&n);
- if(opcode[0]=='/') continue;
- if(strchr(opcode,':')){
- opcode[strlen(opcode)-1]=0;
- symbol *l=0;
- char isallocd=0;
- derefSymbol(opcode,&l);
- if(l==0 || l->type!=SYMBOL_TYPE_GLOBAL){
- l=calloc(sizeof(symbol),1);
- isallocd=1;
- }
- strncpy(l->name,opcode,32);
- l->address=addr;
- l->line=line_n;
- if(l->type==SYMBOL_TYPE_LOCAL) table_add(st,(void*)l,sizeof(*l));
- else if(isallocd) free(l);
- continue;
- }
- instruction *op;
- int32_t size=parseInstruction(&op,opcode,lineptr+n+1);
- addr+=size;
- table_add(ot,op,sizeof(*op));
- }
- return;
- }
- void cleanup(){
- int i;
- if(vt){
- for(i=0;i<vt->n;i++){
- free(((variable*)vt->objects[i])->data);
- free(vt->objects[i]);
- }
- free(vt->objects);
- free(vt);
- }
- if(ot){
- for(i=0;i<ot->n;i++){
- free(ot->objects[i]);
- }
- free(ot->objects);
- free(ot);
- }
- if(st){
- for(i=0;i<st->n;i++){
- free(st->objects[i]);
- }
- free(st->objects);
- free(st);
- }
- if(srefs){
- for(i=0;i<srefs->n;i++){
- free(srefs->objects[i]);
- }
- free(srefs->objects);
- free(srefs);
- }
- if(ft && modexit){
- free(ft->objects);
- free(ft);
- }
- free(buf);
- free(h);
- if(opts && modexit) free(opts);
- if(asmfile>(FILE*)0) fclose(asmfile);
- }
- void parseArgs(char **args){
- while(*args){
- if(!strcmp(*args,"-v")) opts->verbose=1;
- else table_add(ft,(void*)*args,sizeof(*args));
- args++;
- }
- }
- int parseExternGlobal(char *str){
- char keyword[32];
- char name[32];
- memset(keyword,0,32);
- memset(name,0,32);
- sscanf(str,"%s %s",keyword,name);
- if(!strcmp(keyword,"extern")){ //Is external.
- symbol *s=0;
- if(derefSymbol(name,&s)!=-1 && s->type!=SYMBOL_TYPE_LOCAL) throwerror(1,"%s: Symbol already defined\n",name);
- s=calloc(sizeof(symbol),1);
- strncpy(s->name,name,32);
- s->line=line_n;
- s->type=SYMBOL_TYPE_EXTERN;
- table_add(st,(void*)s,sizeof(*s));
- }
- else if(!strcmp(keyword,"global")){ //Is global.
- symbol *s=0;
- if(derefSymbol(name,&s)!=-1 && s->type!=SYMBOL_TYPE_LOCAL) throwerror(1,"%s: Symbol already defined\n",name);
- s=calloc(sizeof(symbol),1);
- strncpy(s->name,name,32);
- s->line=line_n;
- s->type=SYMBOL_TYPE_GLOBAL;
- table_add(st,(void*)s,sizeof(*s));
- }
- else return 1;
- return 0;
- }
- int main(int argc,char **argv){
- if(argc<2){
- printf("Syntax: %s FILENAME [FILENAME 2 ...] [OPTIONS]\n",argv[0]);
- return 1;
- }
- optable=regtable=0;
- ft=calloc(sizeof(table),1);
- atexit(cleanup);
- opts=calloc(sizeof(options),1);
- parseArgs(argv+1);
- for(int fi=0;fi<ft->n;fi++){
- outfile=0;
- modexit=0;
- cleanup();
- asmfile=fopen(((char**)ft->objects)[fi],"r");
- if(!asmfile){
- printf("Error opening file: %s\n",((char**)ft->objects)[fi]);
- return 1;
- }
- strncpy(opts->asmfilename,((char**)ft->objects)[fi],32);
- strncpy(opts->outfilename,((char**)ft->objects)[fi],32);
- char *extptr=0;
- if((extptr=strstr(opts->outfilename,".vs"))) extptr[2]='o';
- else strncpy(opts->outfilename+(strlen(opts->outfilename)),".vo",4);
- line_n=addr=0;
- buf=calloc(128,1);
- h=calloc(sizeof(header),1);
- vt=calloc(sizeof(table),1);
- ot=calloc(sizeof(table),1);
- st=calloc(sizeof(table),1);
- srefs=calloc(sizeof(table),1);
- #ifdef __APPLE__
- size_t sectsize=0;
- optable=getsectdata("binary","opcodes_table",§size);
- regtable=getsectdata("binary","registers_table",§size);
- #else //GNU/Linux
- optable=&_binary_opcodes_table_start;
- regtable=&_binary_registers_table_start;
- #endif
- int datapos=0,textpos=0,textline=0,dataline=0;
- while(getline(&buf,&buf_n,asmfile)!=-1){
- line_n++;
- char *bufp=buf;
- while(isspace(*bufp)) bufp++; //Strip leading whitespace.
- char *bufend=bufp+strlen(buf)-1;
- while(isspace(*bufend)) bufend--; //Strip trailing whitespace.
- bufend[1]=0;
- if(bufp[0]!='/'){
- if(!strcmp(bufp,"sect .data")){
- datapos=ftell(asmfile);
- dataline=line_n;
- }
- if(!strcmp(bufp,"sect .text")){
- textpos=ftell(asmfile);
- textline=line_n;
- }
- else parseExternGlobal(buf);
- }
- }
- line_n=textline;
- processTextSect(textpos);
- line_n=dataline;
- processDataSect(datapos);
- outfile=fopen(opts->outfilename,"w");
- if(!outfile) throwerror(0,"Could not create output file\n");
- fwrite("VO",1,2,outfile);
- fwrite(opts->asmfilename,1,strlen(opts->asmfilename)+1,outfile);
- int pos=ftell(outfile);
- fseek(outfile,pos+sizeof(header),SEEK_SET);
- h->symboltablesize=writeSymbolTable(outfile,st);
- h->textsectsize=writeTextSect(outfile,ot);
- h->datasectsize=writeDataSect(outfile,vt);
- fseek(outfile,pos,SEEK_SET);
- writeHeader(outfile,h);
- fclose(outfile);
- for(int i=0;i<srefs->n;i++) if(derefSymbol(((symbol**)srefs->objects)[i]->name,0)==-1) throwerror(0,"%s: %s: Implicit declaration\n",opts->asmfilename,((symbol**)srefs->objects)[i]->name);
- }
- //Clean up.
- modexit=1;
- exit(0);
- }
Add Comment
Please, Sign In to add comment