/*************************************************************************** parse.c - parses each line, stores in temp space ------------------- Date : May 23 2000 Copyright : (C) 2000 by Daniel Bertrand Email : d.bertrand@ieee.ca ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include"types.h" #include"parse.h" #include"proto.h" /* This function parses the asm file calling appropriate functions to blow up macros, include files, define constants, keep track of equates, and handling assembler directives. This function is called on a line by line basis. normally returns value 0 except when "end" directive is encountered in which case it returns 1, the "endm" directive which return -1, or the "endfor" deirective which returns -2 */ extern char type_strings[GPR_TYPE_EQUATE+1][20]; extern int dbg_opt; extern char *listing,listtemp[60]; extern FILE *listfile; int parse( char line_string[MAX_LINE_LENGTH], char *line) { int tmp,i,arg[4]; static int defmacro=0; //set to 0 unless we're in a macro definition int op_num; char *leading_symbol=NULL, *op_name_ptr,*tmpc; extern char patch_name[PATCH_NAME_SIZE]; extern int ds_addr,ip,tram_addr,tram_delay_count,tram_table_count; extern unsigned int macro_depth; struct sym *sym; struct control *control; extern struct delay tram_delay[MAX_TANK_ADDR]; extern struct lookup tram_lookup[MAX_TANK_ADDR]; if( line_string[0]=='\0' || line_string[0]==';'||line_string[0]=='%'||line_string[0]=='*') return(0); //remove anything after a ; if one exist tmpc=line_string; while( *tmpc != ';' &&*tmpc != '\0') tmpc++; *tmpc='\0'; //check for a leading symbol if( line_string[0] != ' ' && line_string[0] != '\t'){ if(strlen(leading_symbol=strtok(line_string,": \t\n"))>MAX_SYM_LEN ){ printf("symbol \"%s\" is more than %d characters long\n",leading_symbol,MAX_SYM_LEN ); as_exit("Parse error"); } //address ref for skip command: if(*leading_symbol=='.'){ if( issymbol(leading_symbol,&sym)!=-1) (sym->data.value)+=ip-1; } op_name_ptr=strtok(NULL, " \t\n"); }else{ op_name_ptr=strtok(line_string, " \t\n"); } if(op_name_ptr==NULL) return(0); //check if it a macro: if((tmp=ismacro(op_name_ptr)) != -1 ){ if(defmacro==0) macro_expand(tmp,strtok(NULL,"")); return(0); } if( (op_num=op_decode(op_name_ptr))==-1) { printf("**Parse Error with op code field \"%s\"\n",op_name_ptr); as_exit("Parse Error: Bad neumonic"); } //check to see if we're defining a macro if(leading_symbol!=NULL && defmacro!=0 && op_num!=CON && op_num!=CONSTANT) as_exit("Parse error: Cannot define symbols inside of a macro"); switch(op_num){ case EQU: add_symbol(leading_symbol,GPR_TYPE_EQUATE,arg_decode(strtok(NULL, " \t\n"),0),0); return(0); case DS: printf("**Assembler warning: \"DS\" will be obsoleted\n"); case DYNAMIC: case DYN: add_symbol(leading_symbol,GPR_TYPE_DYNAMIC,ds_addr++,0); if( (tmpc=strtok(NULL, " \t\n"))==NULL) tmp=0; else if((tmp=arg_decode(tmpc,0)) <=0) tmp=1; for(i=1;isize = arg2long( strtok(NULL, " \t\n" ) ) +1; INIT_LIST_HEAD( &(tram_delay[tram_delay_count].tram ) ); strcpy((&tram_delay[tram_delay_count])->name,leading_symbol); if((dbg_opt&DBG_TRAM)) printf("Delay Line: %-16s, length: 0x%05x samples,\n",(&tram_delay[tram_delay_count])->name, (&tram_delay[tram_delay_count])->size); tram_delay_count++; return(0); case DT: add_symbol(leading_symbol,GPR_TYPE_EQUATE,tram_table_count,0); (&tram_lookup[tram_table_count])->size = arg2long( strtok(NULL, " \t\n" ) ); INIT_LIST_HEAD( &(tram_lookup[tram_table_count].tram) ); strcpy((&tram_lookup[tram_table_count])->name,leading_symbol); if((dbg_opt&DBG_TRAM)) printf("Lookup table: %-16s, length: 0x%05x samples\n",leading_symbol, (&tram_delay[tram_delay_count])->size); tram_table_count++; return(0); case DW: //two symbols are created, "symbol" -> addr:0x2xx ; value: tram id # // "symbol.a" -> addr:0x3xx ; value: write offset add_symbol(leading_symbol,TYPE_TRAM_DATA,tram_addr+0x200, arg_decode(tmpc=strtok(NULL, " \t," ),0) ); add_symbol( strcat(leading_symbol,".a") ,TYPE_TRAM_ADDR_WRITE, (tram_addr++)+0x300 , arg2long(strtok(NULL," \t\n"))); if(dbg_opt&DBG_TRAM) printf(", in segment: \"%s\"\n",tmpc); return(0); case DR: add_symbol(leading_symbol,TYPE_TRAM_DATA,tram_addr+0x200,arg_decode(tmpc=strtok(NULL, " \t," ),0) ); add_symbol(strcat(leading_symbol,".a"),TYPE_TRAM_ADDR_READ,(tram_addr++)+0x300, arg2long(strtok(NULL," \t\n"))); if(dbg_opt&DBG_TRAM) printf(", in segment: \"%s\"\n",tmpc); return(0); case CONTROL: if( (tmpc = strtok(NULL, "\t ,\n")) ==NULL) as_exit("Parse Error: missing operand(s)"); if( tmpc[0] == '&' ) tmp=arg2long(tmpc)<<11; //account for 11 bit shift of addresses else tmp=arg2long(tmpc); add_symbol(leading_symbol,GPR_TYPE_CONTROL,ds_addr++,tmp); issymbol(leading_symbol,(struct sym **)(&control)); if( (tmpc = strtok(NULL, "\t ,\n") )==NULL) as_exit("Parse Error: missing operand(s)"); if( tmpc[0] == '&' ) control->min=arg2long(tmpc)<<11; //account for 11 bit shift of addresses else control->min=arg2long(tmpc); if( (tmpc = strtok(NULL, "\t ,\n")) ==NULL) as_exit("Parse Error: missing operand(s)"); if( tmpc[0] == '&' ) control->max=arg2long(tmpc)<<11; //account for 11 bit shift of addresses else control->max=arg2long(tmpc); return(0); case ENDM: if(defmacro==1) { defmacro--; return(0); }else if(macro_depth!=0) return(-1); else as_exit("Error, stray ENDM directive"); case END: if(defmacro==1) as_exit("Error end directive in macro definition"); return(1); case INCLUDE: if(defmacro==1) as_exit("Error, cannot include file from within macro definition"); if(listing){ sprintf(listtemp,"including file"); fprintf(listfile,"%-50s || %s\n",listtemp,line); } asm_open(strtok(NULL, "\'\"")); return(-3); case NAME: advance_to_end(op_name_ptr); op_name_ptr++; advance_over_whites(op_name_ptr); if(dbg_opt) printf("Patch name:%s\n",op_name_ptr); // printf("%s\n",op_name_ptr); tmpc=strtok(op_name_ptr,"\""); if(tmpc==NULL) as_exit("Bad name string, did you remember quotes\"\""); if(strlen(tmpc)>PATCH_NAME_SIZE) as_exit("Error Patch name exceeds maximum allowed amount (16)"); memset(patch_name,0,PATCH_NAME_SIZE); strcpy(patch_name,tmpc); return(0); case FOR: if(listing){ sprintf(listtemp,"FOR LOOP"); fprintf(listfile,"%-50s || %s\n",listtemp,line); } for_handler(line,strtok(NULL,"")); return(-3); case ENDFOR: sprintf(listtemp,"FOR LOOP DONE"); return(-2); default: if(defmacro==0){ for(i=0;i<=3;i++) arg[i]=arg_decode(strtok(NULL,","),0); op(op_num,arg[0],arg[1],arg[2],arg[3]); return(0); }else return(0); } return(0); } //assembly-time for loop handling: void for_handler(char *begin, char *operand ) { char *ptr,*next,*line,string[MAX_LINE_LENGTH]; int start,end,i,done; int diff, incr=1; struct sym *sym; ptr=strtok(operand,"="); start= arg_decode(strtok(NULL,":"),0); end = arg_decode(strtok(NULL," \t"),0); if(end>start) diff=end-start; else{ diff=start-end; incr=-1; } if( (issymbol(ptr,&sym))!=-1) sym->data.address=start; else add_symbol(ptr,GPR_TYPE_EQUATE, start,0); issymbol(ptr,&sym); while(*begin!='\0') begin++; begin++; for(i=0;iMAX_LINE_LENGTH) as_exit("Parse error: Line exceeds allowable limit"); strcpy(&string[0],line); //printf("%s\n",string); done=parse(string, line); if(listing) if(done!=-2) fprintf(listfile,"%-50s || %s\n",listtemp,line); *next='\n'; if(done==-2) break; next++; line=next; } sym->data.address = start+(incr*(i+1)); } } int op_decode(char *op_name_ptr) { int op_num; for(op_num=0;op_numdata.name,symbol)==0){ if((*sym)->type!=TYPE_MACRO_ARG) return(0); else if( (*sym)->data.value==(macro_depth+1) ) return(0); } } return(-1); } //compares to words, the words can be terminated with a ' ', '\t', ',' or '\0' int symcmp (char *symbol1,char *symbol2) { while(1){ if(*symbol1!=*symbol2) return(-1); symbol1++; symbol2++; if(symend(symbol1) && symend(symbol2)) return(0); } } //copies a symbol, symbols can be terminated with a ' ' , '\t' , ',' , '\n' , a '\0' void symcpy (char *dest, char *source) { int i=0; for(i=0;i<=MAX_SYM_LEN;i++){ if(source[i]== ' ' || source[i]=='\0' ||source[i]==',' ||source[i]=='\n' || source[i]=='\t' ) { dest[i]='\0'; return; } dest[i]=source[i]; } as_exit("Error, Maximum symbol length exceeded"); }