static void handle_text(char *s) { char *opstart = s; operand *op; dblock *db = NULL; if (db = parse_string(&opstart,*s,8)) { add_atom(0,new_data_atom(db,1)); s = opstart; } if (!db) { op = new_operand(); s = skip_operand(s); if (parse_operand(opstart,s-opstart,op,DATA_OPERAND(8))) { atom *a; a = new_datadef_atom(8,op); a->align = 1; add_atom(0,a); } else syntax_error(8); /* invalid data operand */ } eol(s); }
static void handle_stabs(char *s) { char *name; int t,o,d; if (*s++ == '\"') { name = s; while (*s && *s!='\"') s++; name = cnvstr(name,s-name); } else { syntax_error(7); /* " expected */ return; } s++; t = comma_constexpr(&s); o = comma_constexpr(&s); d = comma_constexpr(&s); s = skip(s); if (*s == ',') { s = skip(s+1); stab_entry(name,t,o,d,s); s = skip_operand(s); } else syntax_error(9); eol(s); }
static void handle_datadef(char *s,int sz) { for (;;) { char *opstart = s; operand *op; dblock *db = NULL; if (OPSZ_BITS(sz)==8 && (*s=='\"' || *s=='\'')) { if (db = parse_string(&opstart,*s,8)) { add_atom(0,new_data_atom(db,1)); s = opstart; } } if (!db) { op = new_operand(); s = skip_operand(s); if (parse_operand(opstart,s-opstart,op,DATA_OPERAND(sz))) add_atom(0,new_datadef_atom(OPSZ_BITS(sz),op)); else syntax_error(8); /* invalid data operand */ } s = skip(s); if (*s == ',') s = skip(s+1); else break; } }
static void handle_data_offset(char *s,int size,int offset) { for (;;) { char *opstart = s; operand *op; dblock *db = NULL; if (size==8 && (*s=='\"' || *s=='\'')) { if (db = parse_string(&opstart,*s,8)) { if (offset != 0) { int i; for (i=0; i<db->size; i++) db->data[i] = db->data[i] + offset; } add_atom(0,new_data_atom(db,1)); s = opstart; } } if (!db) { op = new_operand(); s = skip_operand(s); if (parse_operand(opstart,s-opstart,op,DATA_OPERAND(size))) { atom *a; if (offset != 0) op->value = make_expr(ADD,number_expr(offset),op->value); a = new_datadef_atom(abs(size),op); a->align = 1; add_atom(0,a); } else syntax_error(8); /* invalid data operand */ } s = skip(s); if (*s == ',') { s = skip(s+1); } else if (*s == commentchar) { break; } else if (*s) { syntax_error(9); /* , expected */ return; } else break; } eol(s); }
static void handle_stabn(char *s) { int t,o,d; t = parse_constexpr(&s); o = comma_constexpr(&s); d = comma_constexpr(&s); s = skip(s); if (*s == ',') { s = skip(s+1); stab_entry(NULL,t,o,d,s); s = skip_operand(s); } else syntax_error(9); eol(s); }
static void stab_entry(char *name,int type,int othr,int desc,char *s) { section *stabs; if (!(stabs = find_section(stabname,stabattr))) { section *str; dblock *db; stabs = new_section(stabname,stabattr,4); if (!(str = find_section(stabstrname,stabstrattr))) { str = new_section(stabstrname,stabstrattr,1); } else { if (str->pc != 0) ierror(0); } /* first byte of .stabstr is 0 */ add_atom(str,new_space_atom(number_expr(1),1,0)); /* compilation unit header has to be patched by output module */ new_stabstr(getfilename()); db = new_dblock(); db->size = 12; db->data = mymalloc(12); add_atom(stabs,new_data_atom(db,1)); } add_const_datadef(stabs,name?new_stabstr(name):0,32,1); add_const_datadef(stabs,type,8,1); add_const_datadef(stabs,othr,8,1); add_const_datadef(stabs,desc,16,1); if (s) { operand *op = new_operand(); int len = oplen(skip_operand(s),s); if (parse_operand(s,len,op,DATA_OPERAND(32))) { atom *a = new_datadef_atom(32,op); a->align = 1; add_atom(stabs,a); } else syntax_error(8); } else add_atom(stabs,new_space_atom(number_expr(4),1,0)); /* no value */ }
/* parse next macro argument */ char *parse_macro_arg(struct macro *m,char *s, struct namelen *param,struct namelen *arg) { arg->len = 0; /* cannot select specific named arguments */ param->name = s; if (*s=='\"' || *s=='\'') { s = skip_string(s,*s,NULL); param->len = s - param->name; } else { s = skip_operand(s); param->len = s - param->name; } return s; }
static void handle_data(char *s,int size,int noalign) { for (;;) { char *opstart = s; operand *op; dblock *db = NULL; if ((size==8 || size==16) && *s=='\"') { if (db = parse_string(&opstart,*s,size)) { add_atom(0,new_data_atom(db,1)); s = opstart; } } if (!db) { op = new_operand(); s = skip_operand(s); if (parse_operand(opstart,s-opstart,op,DATA_OPERAND(size))) { atom *a; a = new_datadef_atom(size,op); if (noalign) a->align=1; add_atom(0,a); } else syntax_error(8); /* invalid data operand */ } s = skip(s); if (*s == ',') { s = skip(s+1); } else if (*s==commentchar) break; else if (*s) { syntax_error(9); /* , expected */ return; } else break; } eol(s); }
static long skip_operand(long ib, int size) { int c = get_byte(ib++); switch (c >> 4) { /* mode */ case 4: /* indexed */ ib = skip_operand(ib, 0); break; case 9: /* autoincrement deferred */ if (c == 0x9f) { /* pc: immediate deferred */ /* * addresses are always longwords! */ ib += 4; } break; case 8: /* autoincrement */ if (c == 0x8f) { /* pc: immediate ==> special syntax */ ib += size; } break; case 11: /* byte displacement deferred/ relative deferred */ case 10: /* byte displacement / relative mode */ ib++; break; case 13: /* word displacement deferred */ case 12: /* word displacement */ ib += 2; break; case 15: /* long displacement referred */ case 14: /* long displacement */ ib += 4; break; } return ib; }
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); }
/* Very simple, very incomplete. */ void parse(void) { char *s,*line,*inst,*ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1],*op[MAX_OPERANDS]; int inst_len,ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1],op_len[MAX_OPERANDS]; int i,ext_cnt,op_cnt,par_cnt; instruction *ip; while(line=read_next_line()){ s=line; if(isalnum((unsigned char)*s)){ /* Handle labels at beginning of line */ char *labname,*equ; symbol *label; while(*s&&!isspace((unsigned char)*s)&&*s!=':') s++; labname=cnvstr(line,s-line); s=skip(s+1); if(!strncmp(s,"equ",3)&&isspace((unsigned char)s[3])){ s=skip(s+3); label=new_abs(labname,parse_expr(&s)); }else{ label=new_labsym(0,labname); add_atom(0,new_label_atom(label)); } free(labname); } s=parse_cpu_special(s); if(handle_directive(s)) continue; /* skip spaces */ s=skip(s); if(!*s) continue; /* read mnemonic name */ inst=s; if(!ISIDSTART(*s)){ syntax_error(10); continue; } #if MAX_QUALIFIERS==0 while(*s&&!isspace((unsigned char)*s)) s++; #else while(*s&&*s!='.'&&!isspace((unsigned char)*s)) s++; #endif inst_len=s-inst; /* read qualifiers */ ext_cnt=0; while(*s=='.'&&ext_cnt<MAX_QUALIFIERS){ s++; ext[ext_cnt]=s; while(*s&&*s!='.'&&!isspace((unsigned char)*s)) s++; ext_len[ext_cnt]=s-ext[ext_cnt]; if(ext_len[ext_cnt]<=0) syntax_error(1); else ext_cnt++; } if(!isspace((unsigned char)*s)) syntax_error(2); /* read operands, terminated by comma (unless in parentheses) */ s=skip(s); op_cnt=0; while(*s&&op_cnt<MAX_OPERANDS){ op[op_cnt]=s; s=skip_operand(s); op_len[op_cnt]=s-op[op_cnt]; if(op_len[op_cnt]<=0) syntax_error(5); else op_cnt++; s=skip(s); if(*s!=','){ break; }else{ s=skip(s+1); } } s=skip(s); if(*s!=0) syntax_error(6); ip=new_inst(inst,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if(ip){ for(i=0;i<ext_cnt;i++) ip->qualifiers[i]=cnvstr(ext[i],ext_len[i]); for(;i<MAX_QUALIFIERS;i++) ip->qualifiers[i]=0; } #endif if(ip){ add_atom(0,new_inst_atom(ip)); }else ; } }
void parse(void) { char *s,*line,*ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1],*op[MAX_OPERANDS]; char *labname,*start; int inst_len,ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1],op_len[MAX_OPERANDS]; int ext_cnt,op_cnt; instruction *ip; while (line=read_next_line()){ if (clev >= MAXCONDLEV) syntax_error(16,clev); /* nesting depth exceeded */ if (!cond[clev]) { /* skip source until ELSE or ENDIF */ int idx; s = line; idx = check_directive(&s); if (idx >= 0) { if (!strncmp(directives[idx].name,"if",2)) { ifnesting++; } else if (ifnesting==0 && !strncmp(directives[idx].name,"else",4)) { cond[clev] = 1; } else if (directives[idx].func == handle_endif) { if (ifnesting == 0) { if (clev > 0) clev--; else syntax_error(14); /* endif without if */ } else ifnesting--; } } continue; } s=skip(line); if(handle_directive(s)) continue; /* skip spaces */ s=skip(s); if(!*s||*s==commentchar) continue; /* check for label */ start=s; if(labname=get_local_label(&s)){ /* local label? */ if(*s!=':'){ s=start; myfree(labname); labname=NULL; } } else if(ISIDSTART(*s)){ /* or global label? */ s++; while(ISIDCHAR(*s)) s++; if(*s!=':') s=start; else labname=cnvstr(start,s-start); } if(labname){ /* we have found a valid global or local label */ add_atom(0,new_label_atom(new_labsym(0,labname))); s=skip(s+1); myfree(labname); } if(!*s||*s==commentchar) continue; s=skip(parse_cpu_special(s)); if(*s==0||*s==commentchar) continue; if(handle_directive(s)) continue; /* read mnemonic name */ start=s; ext_cnt=0; if(!ISIDSTART(*s)){ syntax_error(10); continue; } #if MAX_QUALIFIERS==0 while(*s&&!isspace((unsigned char)*s)) s++; inst_len=s-start; #else s=parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif s=skip(s); if(execute_macro(start,inst_len,ext,ext_len,ext_cnt,s,clev)) continue; /* read operands, terminated by comma (unless in parentheses) */ op_cnt=0; while(*s&&*s!=commentchar&&op_cnt<MAX_OPERANDS){ op[op_cnt]=s; s=skip_operand(s); op_len[op_cnt]=oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if(op_len[op_cnt]<=0) syntax_error(5); else #endif op_cnt++; s=skip(s); if(*s!=','){ break; }else{ s=skip(s+1); } } s=skip(s); if(*s!=0&&*s!=commentchar) syntax_error(6); ip=new_inst(start,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if(ip){ int i; for(i=0;i<ext_cnt;i++) ip->qualifiers[i]=cnvstr(ext[i],ext_len[i]); for(;i<MAX_QUALIFIERS;i++) ip->qualifiers[i]=0; } #endif if(ip){ add_atom(0,new_inst_atom(ip)); }else ; } if (clev > 0) syntax_error(15); /* if without endif */ }
void parse(void) { char *s,*line,*inst; char *ext[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; char *op[MAX_OPERANDS]; int ext_len[MAX_QUALIFIERS?MAX_QUALIFIERS:1]; int op_len[MAX_OPERANDS]; int ext_cnt,op_cnt,inst_len; instruction *ip; while (line = read_next_line()) { if (!cond_state()) { /* skip source until ELSE or ENDIF */ int idx = -1; s = skip(line); if (labname = parse_labeldef(&s,1)) { if (*s == ':') s++; /* skip double-colon */ myfree(labname); s = skip(s); } else { if (inst = skip_identifier(s)) { inst = skip(inst); idx = check_directive(&inst); } } if (idx < 0) idx = check_directive(&s); if (idx >= 0) { if (directives[idx].func == handle_if) cond_skipif(); else if (directives[idx].func == handle_else) cond_else(); else if (directives[idx].func == handle_endif) cond_endif(); } continue; } s = skip(line); again: if (*s=='\0' || *line=='*' || *s==commentchar) continue; if (labname = parse_labeldef(&s,1)) { /* we have found a valid global or local label */ symbol *sym = new_labsym(0,labname); if (*s == ':') { /* double colon automatically declares label as exported */ sym->flags |= EXPORT; s++; } add_atom(0,new_label_atom(sym)); myfree(labname); s = skip(s); } else { /* there can still be a sym. in the 1st fld and an assignm. directive */ inst = s; labname = parse_symbol(&s); if (labname == NULL) { syntax_error(10); /* identifier expected */ continue; } s = skip(s); /* Now we have labname pointing to the first field in the line and s pointing to the second. Find out where the directive is. */ if (!ISEOL(s)) { #ifdef PARSE_CPU_LABEL if (PARSE_CPU_LABEL(labname,&s)) { myfree(labname); continue; } #endif if (handle_directive(s)) { myfree(labname); continue; } } /* directive or mnemonic must be in the first field */ myfree(labname); s = inst; } if (!strnicmp(s,".iif",4) || !(strnicmp(s,"iif",3))) { /* immediate conditional assembly: parse line after ',' when true */ s = skip(*s=='.'?s+4:s+3); if (do_cond(&s)) { s = skip(s); if (*s == ',') { s = skip(s+1); goto again; } else syntax_error(0); /* malformed immediate-if */ } continue; } /* check for directives */ s = parse_cpu_special(s); if (ISEOL(s)) continue; if (handle_directive(s)) continue; /* read mnemonic name */ inst = s; ext_cnt = 0; if (!ISIDSTART(*s)) { syntax_error(10); /* identifier expected */ continue; } #if MAX_QUALIFIERS==0 while (*s && !isspace((unsigned char)*s)) s++; inst_len = s - inst; #else s = parse_instruction(s,&inst_len,ext,ext_len,&ext_cnt); #endif if (!isspace((unsigned char)*s) && *s!='\0') syntax_error(2); /* no space before operands */ s = skip(s); if (execute_macro(inst,inst_len,ext,ext_len,ext_cnt,s)) continue; /* read operands, terminated by comma or blank (unless in parentheses) */ op_cnt = 0; while (!ISEOL(s) && op_cnt<MAX_OPERANDS) { op[op_cnt] = s; s = skip_operand(s); op_len[op_cnt] = oplen(s,op[op_cnt]); #if !ALLOW_EMPTY_OPS if (op_len[op_cnt] <= 0) syntax_error(5); /* missing operand */ else #endif op_cnt++; s = skip(s); if (*s != ',') break; else s = skip(s+1); } eol(s); ip = new_inst(inst,inst_len,op_cnt,op,op_len); #if MAX_QUALIFIERS>0 if (ip) { int i; for (i=0; i<ext_cnt; i++) ip->qualifiers[i] = cnvstr(ext[i],ext_len[i]); for(; i<MAX_QUALIFIERS; i++) ip->qualifiers[i] = NULL; } #endif if (ip) add_atom(0,new_inst_atom(ip)); } cond_check(); /* check for open conditional blocks */ }
long skip_opcode(long ib) { u_int opc; int size; const char *argp; /* pointer into argument-list */ opc = get_byte(ib++); if (opc >= 0xfd) { /* two byte op-code */ opc = opc << 8; opc += get_byte(ib++); argp = vax_inst2[INDEX_OPCODE(opc)].argdesc; } else argp = vax_inst[opc].argdesc; if (argp == NULL || *argp == '\0') return ib; while (*argp) { switch (*argp) { case 'b': /* branch displacement */ switch (*(++argp)) { case 'b': ib++; break; case 'w': ib += 2; break; case 'l': ib += 4; break; } break; case 'a': /* absolute addressing mode */ /* FALLTHROUGH */ default: switch (*(++argp)) { case 'b': /* Byte */ size = 1; break; case 'w': /* Word */ size = 2; break; case 'l': /* Long-Word */ case 'f': /* F_Floating */ size = 4; break; case 'q': /* Quad-Word */ case 'd': /* D_Floating */ case 'g': /* G_Floating */ size = 8; break; case 'o': /* Octa-Word */ case 'h': /* H_Floating */ size = 16; break; default: size = 0; } ib = skip_operand(ib, size); } if (!*argp || !*++argp) break; if (*argp++ != ',') break; } return ib; }