/* syntax.c syntax module for vasm */ /* (c) in 2002 by Volker Barthelmann */ #include "vasm.h" /* The syntax module parses the input (read_next_line), handles assembly-directives (section, data-storage etc.) and parses mnemonics. Assembly instructions are split up in mnemonic name, qualifiers and operands. new_inst returns a matching instruction, if one exists. Routines for creating sections and adding atoms to sections will be provided by the main module. */ char *syntax_copyright="vasm test syntax module (c) 2002 Volker Barthelmann"; hashtable *dirhash; char commentchar=';'; char *defsectname = NULL; char *defsecttype = NULL; char *skip(char *s) { while (isspace((unsigned char )*s)) s++; return s; } /* check for end of line, issue error, if not */ void eol(char *s) { s = skip(s); if (!ISEOL(s)) syntax_error(6); } char *skip_operand(char *s) { int par_cnt=0; while(1){ if(*s=='(') par_cnt++; if(*s==')'){ if(par_cnt>0) par_cnt--; else syntax_error(3); } if(ISEOL(s)||(*s==','&&par_cnt==0)) break; s++; } if(par_cnt!=0) syntax_error(4); return s; } static void prident(char *p,int len) { int olen=len; while(len--) putchar(*p++); printf("(len=%d)",olen); } static void handle_section(char *s) { char *name,*attr; if(*s!='\"'){ name=s; if(!ISIDSTART(*s)){ syntax_error(10); return; } while(ISIDCHAR(*s)) s++; name=cnvstr(name,s-name); s=skip(s); }else{ s++; name=s; while(*s&&*s!='\"') s++; name=cnvstr(name,s-name); s=skip(s+1); } if(*s==','){ s=skip(s+1); attr=s; if(*s!='\"') syntax_error(7); else s++; attr=s; while(*s&&*s!='\"') s++; attr=cnvstr(attr,s-attr); s=skip(s+1); }else attr=""; new_section(name,attr,1); switch_section(name,attr); eol(s); } static char *string(char *s,dblock **result) { dblock *db=new_dblock(); taddr size; char *p,esc; if(*s!='\"') ierror(0); else s++; p=s; size=0; while(*s&&*s!='\"'){ if(*s=='\\') s=escape(s,&esc); else s++; size++; } db->size=size; db->data=mymalloc(db->size); s=p; p=db->data; while(*s&&*s!='\"'){ if(*s=='\\') s=escape(s,p++); else *p++=*s++; } *result=db; if(*s=!'\"') syntax_error(7); else s++; return s; } static void handle_data(char *s,int size,int noalign,int zeroterm) { expr *tree; dblock *db; do{ char *opstart=s; operand *op; if(size==8&&*s=='\"'){ s=string(s,&db); add_atom(0,new_data_atom(db,1)); }else{ op=new_operand(); s=skip_operand(s); if(!parse_operand(opstart,s-opstart,op,DATA_OPERAND(size))){ syntax_error(8); }else{ atom *a=new_datadef_atom(size,op); if(noalign) a->align=1; add_atom(0,a); } } s=skip(s); if(*s==','){ s=skip(s+1); }else if(*s) syntax_error(9); }while(*s); if(zeroterm){ if(size!=8) ierror(0); db=new_dblock(); db->size=1; db->data=mymalloc(1); *db->data=0; add_atom(0,new_data_atom(db,1)); } eol(s); } static void handle_global(char *s) { symbol *sym; char *name; name=s; if(!(name=parse_identifier(&s))){ syntax_error(10); return; } sym=new_import(name); sym->flags|=EXPORT; myfree(name); eol(s); } static void handle_align(char *s) { taddr align=parse_constexpr(&s); atom *a=new_space_atom(number_expr(0),1,0); a->align=1<0 if(ip){ for(i=0;iqualifiers[i]=cnvstr(ext[i],ext_len[i]); for(;iqualifiers[i]=0; } #endif if(ip){ add_atom(0,new_inst_atom(ip)); }else ; } } char *const_prefix(char *s,int *base) { if(isdigit((unsigned char)*s)){ *base=10; return s; } if(*s=='$'){ *base=16; return s+1; } if(*s=='%'){ *base=2; return s+1; } *base=0; return s; } char *const_suffix(char *start,char *end) { return end; } char *get_local_label(char **start) { return NULL; } char *parse_macro_arg(struct macro *m,char *s, struct namelen *param,struct namelen *arg) { /* no macro support */ return s; } int expand_macro(source *src,char **line,char *d,int dlen) { return 0; } int init_syntax() { size_t i; hashdata data; dirhash=new_hashtable(0x200); /*FIXME: */ for(i=0;i