Guest User

Untitled

a guest
Aug 28th, 2018
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.11 KB | None | 0 0
  1. #include "assembler.h"
  2.  
  3. char *buf;
  4. size_t buf_n=128;
  5. FILE *asmfile=0,*outfile=0;
  6.  
  7. void processDataSect(int pos);
  8. void processTextSect(int pos);
  9.  
  10. size_t parseVarArgs(void **data,char *str,char length){
  11.     size_t offset=0;
  12.     char *commentptr=0;
  13.     if((commentptr=strstr(str,"//"))) *commentptr=0; //Strip comment.
  14.     loop:
  15.     while(*str==' ' || *str=='\t') str++; //Trim leading whitespace.
  16.     char *strend=str+(strlen(str)-1);
  17.     while(*strend==' ' || *strend=='\t' || *strend=='\n') strend--;
  18.     *(strend+1)=0; //Trim trailing whitespace.
  19.     if(isdigit(*str)){ //Element is integer literal.
  20.         char *endptr=0;
  21.         int v=strtol(str,&endptr,0);
  22.         *data=realloc(*data,(offset+1)*length);
  23.         if(length==1){ //Integer is 8 bit.
  24.             ((char*)*data)[offset]=(char)v;
  25.             offset++;
  26.         }
  27.         else{ //Integer is 32 bit.
  28.             char *datap=((char*)*data)+offset;
  29.             *((int32_t*)datap)=(int32_t)v;
  30.             offset+=sizeof(uint32_t);
  31.         }
  32.         str=endptr+1;
  33.         if(*endptr==',') goto loop;
  34.         else if(*endptr!=0) throwerror(1,"Missing comma\n");
  35.         return offset; //End of string, return.
  36.     }
  37.     else if(*str=='\''){ //Element is character literal.
  38.         str++;
  39.         while(*str!='\''){
  40.             *data=realloc(*data,(offset+1)*length);
  41.             if(length==1){ //Character is 8 bit.
  42.                 ((char*)*data)[offset]=(char)*str;
  43.                 offset++;
  44.             }
  45.             else{ //Character is 32 bit.
  46.                 char *datap=((char*)*data)+offset;
  47.                 *((int32_t*)datap)=(int32_t)*str;
  48.                 offset+=2;
  49.             }
  50.             str++;
  51.         }
  52.         str+=2;
  53.         if(*(str-1)==',') goto loop;
  54.         else if(*(str-1)!=0) throwerror(1,"Missing comma\n");
  55.         return offset; //End of string, return.
  56.     }
  57.     else if(*str=='#'){ //Element is large data segment.
  58.         str++;
  59.         if(!isdigit(*str)) throwerror(1,"Invalid value\n");
  60.         char *endptr=0;
  61.         int size=strtol(str,&endptr,0);
  62.         *data=realloc(*data,offset+(size*length));
  63.         memset(((char*)*data)+offset,0,size*length);
  64.         offset+=(size*length);
  65.         str=endptr+1;
  66.         if(*endptr==',') goto loop;
  67.         else if(*endptr!=0) throwerror(1,"Missing comma\n");
  68.         return offset; //End of string, return.
  69.     }
  70.     else if(*str=='@'){ //Element is a file embed.
  71.         str++;
  72.         if(*str!='"') throwerror(1,"Expected opening double-quote\n");
  73.         str++;
  74.         char *endptr=strchr(str,'"');
  75.         if(!endptr) throwerror(1,"Expected closing double-quotes\n");
  76.         else{ //Satisfy clang-static-analyzer.
  77.             *endptr=0;
  78.             FILE *fp=fopen(str,"rb");
  79.             if(!fp) throwerror(1,"%s: Could not open file for embedding\n",str);
  80.             fseek(fp,0,SEEK_END);
  81.             size_t size=ftell(fp);
  82.             fseek(fp,0,SEEK_SET);
  83.             *data=realloc(*data,offset+size);
  84.             fread(((char*)*data)+offset,1,size,fp);
  85.             offset+=size;
  86.             fclose(fp);
  87.             str=endptr+2;
  88.             if(*(str-1)==',') goto loop;
  89.             else if(*str!=0) throwerror(1,"Missing comma\n");
  90.             return offset; //End of string, return.
  91.         }
  92.     }
  93.     else throwerror(1,"Invalid value:\n%s\n",str);
  94.     return offset;
  95. }
  96.  
  97. void processDataSect(int pos){
  98.     fseek(asmfile,pos,SEEK_SET);
  99.     while(!feof(asmfile)){
  100.         memset(buf,0,buf_n);
  101.         getline(&buf,&buf_n,asmfile);
  102.         line_n++;
  103.         if(!strcmp(buf,"sect .text\n")) break;
  104.         char *lineptr=buf;
  105.         while(*lineptr=='\t' || *lineptr==' ' || *lineptr=='\n') lineptr++; //Trim leading whitespace.
  106.         if(*lineptr=='/') continue;
  107.         if(!*lineptr) continue;
  108.         int n;
  109.         char name[32];
  110.         char length;
  111.         sscanf(lineptr,"%s %c %n\n",name,&length,&n);
  112.         length=length=='b'?1:sizeof(uint32_t);
  113.         size_t symbol_n=strlen(name)-1;
  114.         if(name[symbol_n]==':') name[symbol_n]=0;
  115.         variable *var=calloc(sizeof(variable),1);
  116.         symbol *l=0;
  117.         char isallocd=0;
  118.         derefSymbol(name,&l);
  119.         if(l==0 || l->type!=SYMBOL_TYPE_GLOBAL){
  120.             l=calloc(sizeof(symbol),1);
  121.             isallocd=1;
  122.         }
  123.         strncpy(l->name,name,32);
  124.         var->length=length;
  125.         var->data_n=parseVarArgs(&var->data,lineptr+n,length);
  126.         l->address=addr;
  127.         l->line=line_n;
  128.         addr+=var->data_n;
  129.         table_add(vt,var,sizeof(*var));
  130.         if(l->type==SYMBOL_TYPE_LOCAL) table_add(st,l,sizeof(*l));
  131.         else if(isallocd) free(l);
  132.     }
  133.     return;
  134. }
  135.  
  136. void processTextSect(int pos){
  137.     fseek(asmfile,pos,SEEK_SET);
  138.     while(!feof(asmfile)){
  139.         memset(buf,0,buf_n);
  140.         getline(&buf,&buf_n,asmfile);
  141.         line_n++;
  142.         if(!strcmp(buf,"sect .data\n")) break;
  143.         char *lineptr=buf;
  144.         while(*lineptr=='\t' || *lineptr==' ' || *lineptr=='\n') lineptr++; //Trim leading whitespace.
  145.         if(!*lineptr) continue;
  146.         char opcode[32];
  147.         memset(opcode,0,32);
  148.         int n;
  149.         sscanf(lineptr,"%s%n",opcode,&n);
  150.         if(opcode[0]=='/') continue;
  151.         if(strchr(opcode,':')){
  152.             opcode[strlen(opcode)-1]=0;
  153.             symbol *l=0;
  154.             char isallocd=0;
  155.             derefSymbol(opcode,&l);
  156.             if(l==0 || l->type!=SYMBOL_TYPE_GLOBAL){
  157.                 l=calloc(sizeof(symbol),1);
  158.                 isallocd=1;
  159.             }
  160.             strncpy(l->name,opcode,32);
  161.             l->address=addr;
  162.             l->line=line_n;
  163.             if(l->type==SYMBOL_TYPE_LOCAL) table_add(st,(void*)l,sizeof(*l));
  164.             else if(isallocd) free(l);
  165.             continue;
  166.         }
  167.         instruction *op;
  168.         int32_t size=parseInstruction(&op,opcode,lineptr+n+1);
  169.         addr+=size;
  170.         table_add(ot,op,sizeof(*op));
  171.     }
  172.     return;
  173. }
  174.  
  175. void cleanup(){
  176.     int i;
  177.     if(vt){
  178.         for(i=0;i<vt->n;i++){
  179.             free(((variable*)vt->objects[i])->data);
  180.             free(vt->objects[i]);
  181.         }
  182.         free(vt->objects);
  183.         free(vt);
  184.     }
  185.     if(ot){
  186.         for(i=0;i<ot->n;i++){
  187.             free(ot->objects[i]);
  188.         }
  189.         free(ot->objects);
  190.         free(ot);
  191.     }
  192.     if(st){
  193.         for(i=0;i<st->n;i++){
  194.             free(st->objects[i]);
  195.         }
  196.         free(st->objects);
  197.         free(st);
  198.     }
  199.     if(srefs){
  200.         for(i=0;i<srefs->n;i++){
  201.             free(srefs->objects[i]);
  202.         }
  203.         free(srefs->objects);
  204.         free(srefs);
  205.     }
  206.     if(ft && modexit){
  207.         free(ft->objects);
  208.         free(ft);
  209.     }
  210.     free(buf);
  211.     free(h);
  212.     if(opts && modexit) free(opts);
  213.   if(asmfile>(FILE*)0) fclose(asmfile);
  214. }
  215.  
  216. void parseArgs(char **args){
  217.     while(*args){
  218.         if(!strcmp(*args,"-v")) opts->verbose=1;
  219.         else table_add(ft,(void*)*args,sizeof(*args));
  220.         args++;
  221.     }
  222. }
  223.  
  224. int parseExternGlobal(char *str){
  225.     char keyword[32];
  226.     char name[32];
  227.     memset(keyword,0,32);
  228.     memset(name,0,32);
  229.     sscanf(str,"%s %s",keyword,name);
  230.     if(!strcmp(keyword,"extern")){ //Is external.
  231.         symbol *s=0;
  232.         if(derefSymbol(name,&s)!=-1 && s->type!=SYMBOL_TYPE_LOCAL) throwerror(1,"%s: Symbol already defined\n",name);
  233.         s=calloc(sizeof(symbol),1);
  234.         strncpy(s->name,name,32);
  235.         s->line=line_n;
  236.         s->type=SYMBOL_TYPE_EXTERN;
  237.         table_add(st,(void*)s,sizeof(*s));
  238.     }
  239.     else if(!strcmp(keyword,"global")){ //Is global.
  240.         symbol *s=0;
  241.         if(derefSymbol(name,&s)!=-1 && s->type!=SYMBOL_TYPE_LOCAL) throwerror(1,"%s: Symbol already defined\n",name);
  242.         s=calloc(sizeof(symbol),1);
  243.         strncpy(s->name,name,32);
  244.         s->line=line_n;
  245.         s->type=SYMBOL_TYPE_GLOBAL;
  246.         table_add(st,(void*)s,sizeof(*s));
  247.     }
  248.     else return 1;
  249.     return 0;
  250. }
  251.  
  252. int main(int argc,char **argv){
  253.     if(argc<2){
  254.         printf("Syntax: %s FILENAME [FILENAME 2 ...] [OPTIONS]\n",argv[0]);
  255.         return 1;
  256.     }
  257.     optable=regtable=0;
  258.     ft=calloc(sizeof(table),1);
  259.     atexit(cleanup);
  260.     opts=calloc(sizeof(options),1);
  261.     parseArgs(argv+1);
  262.     for(int fi=0;fi<ft->n;fi++){
  263.         outfile=0;
  264.         modexit=0;
  265.         cleanup();
  266.         asmfile=fopen(((char**)ft->objects)[fi],"r");
  267.         if(!asmfile){
  268.             printf("Error opening file: %s\n",((char**)ft->objects)[fi]);
  269.             return 1;
  270.         }
  271.         strncpy(opts->asmfilename,((char**)ft->objects)[fi],32);
  272.         strncpy(opts->outfilename,((char**)ft->objects)[fi],32);
  273.         char *extptr=0;
  274.         if((extptr=strstr(opts->outfilename,".vs"))) extptr[2]='o';
  275.         else strncpy(opts->outfilename+(strlen(opts->outfilename)),".vo",4);
  276.         line_n=addr=0;
  277.         buf=calloc(128,1);
  278.         h=calloc(sizeof(header),1);
  279.         vt=calloc(sizeof(table),1);
  280.         ot=calloc(sizeof(table),1);
  281.         st=calloc(sizeof(table),1);
  282.         srefs=calloc(sizeof(table),1);
  283. #ifdef __APPLE__
  284.     size_t sectsize=0;
  285.         optable=getsectdata("binary","opcodes_table",&sectsize);
  286.         regtable=getsectdata("binary","registers_table",&sectsize);
  287. #else //GNU/Linux
  288.     optable=&_binary_opcodes_table_start;
  289.     regtable=&_binary_registers_table_start;
  290. #endif
  291.         int datapos=0,textpos=0,textline=0,dataline=0;
  292.         while(getline(&buf,&buf_n,asmfile)!=-1){
  293.             line_n++;
  294.             char *bufp=buf;
  295.             while(isspace(*bufp)) bufp++; //Strip leading whitespace.
  296.             char *bufend=bufp+strlen(buf)-1;
  297.             while(isspace(*bufend)) bufend--; //Strip trailing whitespace.
  298.             bufend[1]=0;
  299.             if(bufp[0]!='/'){
  300.                 if(!strcmp(bufp,"sect .data")){
  301.                     datapos=ftell(asmfile);
  302.                     dataline=line_n;
  303.                 }
  304.                 if(!strcmp(bufp,"sect .text")){
  305.                     textpos=ftell(asmfile);
  306.                     textline=line_n;
  307.                 }
  308.                 else parseExternGlobal(buf);
  309.             }
  310.         }
  311.         line_n=textline;
  312.         processTextSect(textpos);
  313.         line_n=dataline;
  314.         processDataSect(datapos);
  315.         outfile=fopen(opts->outfilename,"w");
  316.         if(!outfile) throwerror(0,"Could not create output file\n");
  317.         fwrite("VO",1,2,outfile);
  318.         fwrite(opts->asmfilename,1,strlen(opts->asmfilename)+1,outfile);
  319.         int pos=ftell(outfile);
  320.         fseek(outfile,pos+sizeof(header),SEEK_SET);
  321.         h->symboltablesize=writeSymbolTable(outfile,st);
  322.         h->textsectsize=writeTextSect(outfile,ot);
  323.         h->datasectsize=writeDataSect(outfile,vt);
  324.         fseek(outfile,pos,SEEK_SET);
  325.         writeHeader(outfile,h);
  326.         fclose(outfile);
  327.         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);
  328.     }
  329.     //Clean up.
  330.     modexit=1;
  331.   exit(0);
  332. }
Add Comment
Please, Sign In to add comment