void append_type(struct prog_info *pi, char *name, int c, char *value) { int p, l; struct def *def; p = strlen(name); name[p++] = '_'; if(c == 0) { name[p++] = 'v'; name[p] = '\0'; return; } l = strlen(value); if ((l==2 || l==3) && (tolower(value[0])=='r') && isdigit(value[1]) && (l==3?isdigit(value[2]):1) && (atoi(&value[1])<32)) { itoa((c*8),&name[p],10); return; } for(def = pi->first_def; def; def = def->next) if(!nocase_strcmp(def->name, value)) { itoa((c*8),&name[p],10); return; } name[p++] = 'i'; name[p] = '\0'; }
struct macro *get_macro(struct prog_info *pi, char *name) { struct macro *macro; for(macro = pi->first_macro; macro; macro = macro->next) if(!nocase_strcmp(macro->name, name)) return(macro); return(NULL); }
struct device *get_device(struct prog_info *pi, char *name) { int i = 1; LastDevice = 0; if(name == NULL) { def_dev(pi); return(&device_list[0]); } while(device_list[i].name) { if(!nocase_strcmp(name, device_list[i].name)) { LastDevice=i; def_dev(pi); return(&device_list[i]); } i++; } def_dev(pi); return(NULL); }
int parse_line(struct prog_info *pi, char *line) { char *ptr=NULL; int k; int flag=0, i; int global_label = False; char temp[LINEBUFFER_LENGTH]; struct label *label = NULL; struct macro_call *macro_call; while(IS_HOR_SPACE(*line)) line++; /* At first remove leading spaces / tabs */ if(IS_END_OR_COMMENT(*line)) /* Skip comment line or empty line */ return(True); /* Filter out .stab debugging information */ /* .stabs sometimes contains colon : symbol - might be interpreted as label */ if(*line == '.') { /* minimal slowdown of existing code */ if(strncmp(temp,".stabs ",7) == 0 ) { /* compiler output is always lower case */ strcpy(temp,line); /* TODO : Do we need this temp variable ? Please check */ return parse_stabs( pi, temp ); } if(strncmp(temp,".stabn ",7) == 0 ) { strcpy(temp,line); return parse_stabn( pi, temp ); } } /* Meta information translation */ ptr=line; k=0; while((ptr=strchr(ptr, '%')) != NULL) { if(!strncmp(ptr, "%MINUTE%", 8) ) { /* Replacement always shorter than tag -> no length check */ k=strftime(ptr,3,"%M", localtime(&pi->time)); strcpy(ptr+k,ptr+8); ptr+=k; continue; } if(!strncmp(ptr, "%HOUR%", 6) ) { k=strftime(ptr,3,"%H", localtime(&pi->time)); strcpy(ptr+k,ptr+6); ptr+=k; continue; } if(!strncmp(ptr, "%DAY%", 5) ) { k=strftime(ptr,3,"%d", localtime(&pi->time)); strcpy(ptr+k,ptr+5); ptr+=k; continue; } if(!strncmp(ptr, "%MONTH%", 7) ) { k=strftime(ptr,3,"%m", localtime(&pi->time)); strcpy(ptr+k,ptr+7); ptr+=k; continue; } if(!strncmp(ptr, "%YEAR%", 6) ) { k=strftime(ptr,5,"%Y", localtime(&pi->time)); strcpy(ptr+k,ptr+6); ptr+=k; continue; } ptr++; } // if(pi->pass == PASS_2) // TODO : Test // strcpy(pi->list_line, line); strcpy(pi->fi->scratch,line); for(i = 0; IS_LABEL(pi->fi->scratch[i]) || (pi->fi->scratch[i] == ':'); i++) if(pi->fi->scratch[i] == ':') { /* it is a label */ pi->fi->scratch[i] = '\0'; if(pi->pass == PASS_1) { for(macro_call = pi->macro_call; macro_call; macro_call = macro_call->prev_on_stack) { for(label = pi->macro_call->first_label; label; label = label->next) { if(!nocase_strcmp(label->name, &pi->fi->scratch[0])) { print_msg(pi, MSGTYPE_ERROR, "Can't redefine local label %s", &pi->fi->scratch[0]); break; } } } if(test_label(pi,&pi->fi->scratch[0],"Can't redefine label %s")!=NULL) break; if(test_variable(pi,&pi->fi->scratch[0],"%s have already been defined as a .SET variable")!=NULL) break; if(test_constant(pi,&pi->fi->scratch[0],"%s has already been defined as a .EQU constant")!=NULL) break; label = malloc(sizeof(struct label)); if(!label) { print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL); return(False); } label->next = NULL; label->name = malloc(strlen(&pi->fi->scratch[0]) + 1); if(!label->name) { print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL); return(False); } strcpy(label->name, &pi->fi->scratch[0]); switch(pi->segment) { case SEGMENT_CODE: label->value = pi->cseg_addr; break; case SEGMENT_DATA: label->value = pi->dseg_addr; break; case SEGMENT_EEPROM: label->value = pi->eseg_addr; break; } if(pi->macro_call && !global_label) { if(pi->macro_call->last_label) pi->macro_call->last_label->next = label; else pi->macro_call->first_label = label; pi->macro_call->last_label = label; } else { if(pi->last_label) pi->last_label->next = label; else pi->first_label = label; pi->last_label = label; } } i++; while(IS_HOR_SPACE(pi->fi->scratch[i]) && !IS_END_OR_COMMENT(pi->fi->scratch[i])) i++; if(IS_END_OR_COMMENT(pi->fi->scratch[i])) { if((pi->pass == PASS_2) && pi->list_on) { // Diff tilpassing fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } return(True); } strcpy(pi->fi->scratch, &pi->fi->scratch[i]); break; } #if 0 if(pi->fi->scratch[0] == '.') { #else if((pi->fi->scratch[0] == '.') || (pi->fi->scratch[0] == '#')) { #endif pi->fi->label = label; flag = parse_directive(pi); if((pi->pass == PASS_2) && pi->list_on && pi->list_line) { // Diff tilpassing fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } return(flag); } else { return parse_mnemonic(pi); } } /* * Get the next token, and terminate the last one. * Termination identifier is specified. */ char *get_next_token(char *data, int term) { int i = 0, j, anti_comma = False; switch(term) { case TERM_END: // while(!IS_END_OR_COMMENT(data[i])) i++; Problems with 2. operand == ';' while( ((data[i] != ',') || anti_comma) && !(((data[i] == ';') && !anti_comma) || IS_ENDLINE(data[i])) ) { if((data[i] == '\'') || (data[i] == '"')) anti_comma = anti_comma ? False : True; i++; } break; case TERM_SPACE: while(!IS_HOR_SPACE(data[i]) && !IS_END_OR_COMMENT(data[i])) i++; break; case TERM_DASH: while((data[i] != '-') && !IS_END_OR_COMMENT(data[i])) i++; break; case TERM_COLON: while((data[i] != ':') && !IS_ENDLINE(data[i])) i++; break; case TERM_DOUBLEQUOTE: while((data[i] != '"') && !IS_ENDLINE(data[i])) i++; break; case TERM_COMMA: while(((data[i] != ',') || anti_comma) && !(((data[i] == ';') && !anti_comma) || IS_ENDLINE(data[i])) ) { if((data[i] == '\'') || (data[i] == '"')) anti_comma = anti_comma ? False : True; i++; } break; case TERM_EQUAL: while((data[i] != '=') && !IS_END_OR_COMMENT(data[i])) i++; break; } if(IS_END_OR_COMMENT(data[i])) { data[i--] = '\0'; while(IS_HOR_SPACE(data[i])) data[i--] = '\0'; return(0); } j = i - 1; while(IS_HOR_SPACE(data[j])) data[j--] = '\0'; data[i++] = '\0'; while(IS_HOR_SPACE(data[i]) && !IS_END_OR_COMMENT(data[i])) i++; if(IS_END_OR_COMMENT(data[i])) return(0); return(&data[i]); }
int parse_directive(struct prog_info *pi) { int directive, pragma; int ok = True; int i; char *next, *data, buf[140]; struct file_info *fi_bak; struct def *def; struct data_list *incpath, *dl; next = get_next_token(pi->fi->scratch, TERM_SPACE); my_strupr(pi->fi->scratch); directive = lookup_keyword(directive_list, pi->fi->scratch + 1, True); if(directive == -1) { print_msg(pi, MSGTYPE_ERROR, "Unknown directive: %s", pi->fi->scratch); return(True); } switch(directive) { case DIRECTIVE_BYTE: if (!next) { print_msg(pi, MSGTYPE_ERROR, ".BYTE needs a size operand"); return(True); } if (pi->segment == pi->cseg) print_msg(pi, MSGTYPE_ERROR, ".BYTE directive cannot be used within the code segment (.CSEG)"); get_next_token(next, TERM_END); if (!get_expr(pi, next, &i)) return(False); if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) { fprintf(pi->list_file, "%c:%06x %s\n", pi->segment->ident, pi->segment->addr, pi->list_line); pi->list_line = NULL; } if (i > 0) { fix_orglist(pi->segment); advance_ip(pi->segment, i); def_orglist(pi->segment); } break; case DIRECTIVE_CSEG: fix_orglist(pi->segment); def_orglist(pi->cseg); break; case DIRECTIVE_CSEGSIZE: break; case DIRECTIVE_DB: if((pi->pass == PASS_2) && pi->list_line && pi->list_on) { fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } return(parse_db(pi, next)); // break; /* Directive .def */ case DIRECTIVE_DEF: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".DEF needs an operand"); return(True); } data = get_next_token(next, TERM_EQUAL); if(!(data && (tolower(data[0]) == 'r') && isdigit(data[1]))) { print_msg(pi, MSGTYPE_ERROR, "%s needs a register (e.g. .def BZZZT = r16)", next); return(True); } i = atoi(&data[1]); /* check range of given register */ if(i > 31) print_msg(pi, MSGTYPE_ERROR, "R%d is not a valid register", i); /* check if this reg is already assigned */ for(def = pi->first_def; def; def = def->next) { if(def->reg == i && pi->pass == PASS_1 && !pi->NoRegDef) { print_msg(pi, MSGTYPE_WARNING, "r%d is already assigned to '%s'!", i, def->name); return(True); } } /* check if this regname is already defined */ for(def = pi->first_def; def; def = def->next) { if(!nocase_strcmp(def->name, next)) { if(pi->pass == PASS_1 && !pi->NoRegDef) { print_msg(pi, MSGTYPE_WARNING, "'%s' is already assigned as r%d but will now be set to r%i!", next, def->reg, i); } def->reg = i; return(True); } } /* B.A.: Check, if symbol is already defined as a label or constant */ if(pi->pass == PASS_2) { if(get_label(pi,next,NULL)) print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a label", next); if(get_constant(pi,next,NULL)) print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a constant", next); } def = malloc(sizeof(struct def)); if(!def) { print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL); return(False); } def->next = NULL; if(pi->last_def) pi->last_def->next = def; else pi->first_def = def; pi->last_def = def; def->name = malloc(strlen(next) + 1); if(!def->name) { print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL); return(False); } strcpy(def->name, next); def->reg = i; break; case DIRECTIVE_DEVICE: if(pi->pass == PASS_2) return(True); if(!next) { print_msg(pi, MSGTYPE_ERROR, ".DEVICE needs an operand"); return(True); } if (pi->device->name != NULL) { /* B.A.: Check for multiple device definitions */ print_msg(pi, MSGTYPE_ERROR, "More than one .DEVICE definition"); } if (pi->cseg->count || pi->dseg->count || pi->eseg->count) { /* B.A.: Check if something was already assembled */ print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any code lines"); } else { if ((pi->cseg->addr != pi->cseg->lo_addr ) || (pi->dseg->addr != pi->dseg->lo_addr ) || (pi->eseg->addr != pi->eseg->lo_addr )) { /* B.A.: Check if something was already assembled XXX probably redundant */ print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any .ORG directive"); } } get_next_token(next, TERM_END); pi->device = get_device(pi,next); if (!pi->device) { print_msg(pi, MSGTYPE_ERROR, "Unknown device: %s", next); pi->device = get_device(pi,NULL); /* B.A.: Fix segmentation fault if device is unknown */ } /* Now that we know the device type, we can * start memory allocation from the correct offsets. */ fix_orglist(pi->segment); rewind_segments(pi); def_orglist(pi->segment); break; case DIRECTIVE_DSEG: fix_orglist(pi->segment); def_orglist(pi->dseg); if (pi->dseg->hi_addr == 0) { /* XXX move to emit */ print_msg(pi, MSGTYPE_ERROR, "Can't use .DSEG directive because device has no RAM"); } break; case DIRECTIVE_DW: if (pi->segment->flags & SEG_BSS_DATA) { print_msg(pi, MSGTYPE_ERROR, "Can't use .DW directive in data segment (.DSEG)"); return(True); } while (next) { data = get_next_token(next, TERM_COMMA); if(pi->pass == PASS_2) { if(!get_expr(pi, next, &i)) return(False); if((i < -32768) || (i > 65535)) print_msg(pi, MSGTYPE_WARNING, "Value %d is out of range (-32768 <= k <= 65535). Will be masked", i); } if (pi->pass == PASS_2) { if (pi->list_line && pi->list_on) { fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; fprintf(pi->list_file, "%c:%06x %04x\n", pi->segment->ident, pi->segment->addr, i); } if (pi->segment == pi->eseg) { write_ee_byte(pi, pi->eseg->addr, (unsigned char)i); write_ee_byte(pi, pi->eseg->addr + 1, (unsigned char)(i >> 8)); } if (pi->segment == pi->cseg) { write_prog_word(pi, pi->cseg->addr, i); } } if (pi->segment == pi->eseg) advance_ip(pi->eseg, 2); if (pi->segment == pi->cseg) advance_ip(pi->cseg, 1); next = data; } break; case DIRECTIVE_ENDM: case DIRECTIVE_ENDMACRO: print_msg(pi, MSGTYPE_ERROR, "No .MACRO found before .ENDMACRO"); break; case DIRECTIVE_EQU: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".EQU needs an operand"); return(True); } data = get_next_token(next, TERM_EQUAL); if(!data) { print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .EQU BZZZT = 0x2a)", next); return(True); } get_next_token(data, TERM_END); if(!get_expr(pi, data, &i)) return(False); if(test_label(pi,next,"%s have already been defined as a label")!=NULL) return(True); if(test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL) return(True); /* B.A. : New. Forward references allowed. But check, if everything is ok ... */ if(pi->pass==PASS_1) { /* Pass 1 */ if(test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL) return(True); if(def_const(pi, next, i)==False) return(False); } else { /* Pass 2 */ int j; if(get_constant(pi, next, &j)==False) { /* Defined in Pass 1 and now missing ? */ print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next); return(False); } if(i != j) { print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i); return(False); } /* OK. Definition is unchanged */ } if((pi->pass == PASS_2) && pi->list_line && pi->list_on) { fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } break; case DIRECTIVE_ESEG: fix_orglist(pi->segment); def_orglist(pi->eseg); if(pi->device->eeprom_size == 0) { /* XXX */ print_msg(pi, MSGTYPE_ERROR, "Can't use .ESEG directive because device has no EEPROM"); } break; case DIRECTIVE_EXIT: pi->fi->exit_file = True; break; /*** .include ***/ case DIRECTIVE_INCLUDE: if(!next) { print_msg(pi, MSGTYPE_ERROR, "Nothing to include"); return(True); } next = term_string(pi, next); if((pi->pass == PASS_2) && pi->list_line && pi->list_on) { fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } // Test if include is in local directory ok = test_include(next); data = NULL; if(!ok) for(incpath = GET_ARG_LIST(pi->args, ARG_INCLUDEPATH); incpath && !ok; incpath = incpath->next) { i = strlen(incpath->data); if(data) free(data); data = malloc(i + strlen(next) + 2); if(!data) { print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL); return(False); } strcpy(data, incpath->data); if((data[i - 1] != '\\') && (data[i - 1] != '/')) data[i++] = '/'; strcpy(&data[i], next); //printf("testing: %s\n", data); ok = test_include(data); } if(ok) { fi_bak = pi->fi; ok = parse_file(pi, data ? data : next); pi->fi = fi_bak; } else print_msg(pi, MSGTYPE_ERROR, "Cannot find include file: %s", next); if(data) free(data); break; /*** .includepath ***/ case DIRECTIVE_INCLUDEPATH: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand"); return(True); } data = get_next_token(next, TERM_SPACE); if(data) { print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand!!!"); get_next_token(data, TERM_END); if(!get_expr(pi, data, &i)) return(False); } next = term_string(pi, next); /* get arg list start pointer */ incpath = GET_ARG_LIST(pi->args, ARG_INCLUDEPATH); /* search for last element */ if(incpath == NULL) { dl = malloc(sizeof(struct data_list)); data = malloc(strlen(next)+1); if(dl && data) { dl->next = NULL; strcpy(data, next); dl->data = data; SET_ARG_LIST(pi->args, ARG_INCLUDEPATH, dl); } else { printf("Error: Unable to allocate memory\n"); return(False); } } else add_arg(&incpath, next); break; case DIRECTIVE_LIST: if(pi->pass == PASS_2) if(pi->list_file) pi->list_on = True; break; case DIRECTIVE_LISTMAC: if(pi->pass == PASS_2) SET_ARG_I(pi->args, ARG_LISTMAC, True); break; case DIRECTIVE_MACRO: return(read_macro(pi, next)); // break; case DIRECTIVE_NOLIST: if(pi->pass == PASS_2) pi->list_on = False; break; case DIRECTIVE_ORG: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".ORG needs an operand"); return(True); } get_next_token(next, TERM_END); if(!get_expr(pi, next, &i)) return(False); fix_orglist(pi->segment); pi->segment->addr = i; /* XXX advance */ def_orglist(pi->segment); if(pi->fi->label) pi->fi->label->value = i; if((pi->pass == PASS_2) && pi->list_line && pi->list_on) { fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } break; case DIRECTIVE_SET: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".SET needs an operand"); return(True); } data = get_next_token(next, TERM_EQUAL); if(!data) { print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .SET BZZZT = 0x2a)", next); return(True); } get_next_token(data, TERM_END); if(!get_expr(pi, data, &i)) return(False); if(test_label(pi,next,"%s have already been defined as a label")!=NULL) return(True); if(test_constant(pi,next,"%s have already been defined as a .EQU constant")!=NULL) return(True); return(def_var(pi, next, i)); // break; case DIRECTIVE_DEFINE: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".DEFINE needs an operand"); return(True); } data = get_next_token(next, TERM_SPACE); if(data) { get_next_token(data, TERM_END); if(!get_expr(pi, data, &i)) return(False); } else i = 1; if(test_label(pi,next,"%s have already been defined as a label")!=NULL) return(True); if(test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL) return(True); /* B.A. : New. Forward references allowed. But check, if everything is ok ... */ if(pi->pass==PASS_1) { /* Pass 1 */ if(test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL) return(True); if(def_const(pi, next, i)==False) return(False); } else { /* Pass 2 */ int j; if(get_constant(pi, next, &j)==False) { /* Defined in Pass 1 and now missing ? */ print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next); return(False); } if(i != j) { print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i); return(False); } /* OK. Definition is unchanged */ } if((pi->pass == PASS_2) && pi->list_line && pi->list_on) { fprintf(pi->list_file, " %s\n", pi->list_line); pi->list_line = NULL; } break; case DIRECTIVE_NOOVERLAP: if (pi->pass == PASS_1) { fix_orglist(pi->segment); pi->segment_overlap = SEG_DONT_OVERLAP; def_orglist(pi->segment); } break; case DIRECTIVE_OVERLAP: if (pi->pass == PASS_1) { fix_orglist(pi->segment); pi->segment_overlap = SEG_ALLOW_OVERLAP; def_orglist(pi->segment); } break; case DIRECTIVE_PRAGMA: if (!next) { print_msg(pi, MSGTYPE_ERROR, "PRAGMA needs an operand, %s should be specified", snprint_list(buf, sizeof(buf), pragma_list)); return(True); } my_strupr(next); data = get_next_token(next, TERM_SPACE); pragma = lookup_keyword(pragma_list, next, False); switch (pragma) { case PRAGMA_OVERLAP: if (pi->pass == PASS_1) { int overlap_setting = OVERLAP_UNDEFINED; if (data) { my_strupr(data); overlap_setting = lookup_keyword(overlap_value, data, False); }; switch (overlap_setting) { case OVERLAP_DEFAULT: pi->effective_overlap = GET_ARG_I(pi->args, ARG_OVERLAP); break; case OVERLAP_IGNORE: case OVERLAP_WARNING: case OVERLAP_ERROR: pi->effective_overlap = overlap_setting; break; default: print_msg(pi, MSGTYPE_ERROR, "For PRAGMA %s directive" " %s should be specified as the parameter", next, snprint_list(buf, sizeof(buf), overlap_value)); return(False); } } return(True); break; default: if(pi->pass == PASS_2) print_msg(pi, MSGTYPE_MESSAGE, "PRAGMA %s directive currently ignored", next); return(True); } break; case DIRECTIVE_UNDEF: // TODO break; case DIRECTIVE_IFDEF: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".IFDEF needs an operand"); return(True); } get_next_token(next, TERM_END); /* B.A. : Forward referenc is not allowed for ifdef and ifndef */ /* Store undefined symbols in blacklist in pass1 and check, if they are still undefined in pass2 */ if(get_symbol(pi, next, NULL)) { #if 0 // If it's not defined in the first pass, but was defined later // then it should be considered OK with regards to ifdef..endif and // ifndef..endif code sections. Removed this code. if(pi->pass==PASS_2) { /* B.A. : 'Still undefined'-test in pass 2 */ if(test_blacklist(pi,next,"Forward reference (%s) not allowed in .ifdef directive")!=NULL) return(False); } #else pi->conditional_depth++; #endif } else { if(pi->pass==PASS_1) { /* B.A. : Store undefined symbols in pass 1 */ if(def_blacklist(pi, next)==False) return(False); } if(!spool_conditional(pi, False)) return(False); } break; case DIRECTIVE_IFNDEF: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".IFNDEF needs an operand"); return(True); } get_next_token(next, TERM_END); /* B.A. : Forward referenc is not allowed for ifdef and ifndef */ /* Store undefined symbols in blacklist in pass1 and check, if they are still undefined in pass2 */ if(!get_symbol(pi, next, NULL)) { #if 0 if(pi->pass==PASS_2) { /* B.A. : 'Still undefined'-test in pass 2 */ // If it's not defined in the first pass, but was defined later // then it should be considered OK with regards to ifdef..endif and // ifndef..endif code sections. Removed this code. if(test_blacklist(pi,next,"Forward reference (%s) not allowed in .ifndef directive")!=NULL) return(False); } if(!spool_conditional(pi, False)) return(False); #else pi->conditional_depth++; #endif } else { if(pi->pass==PASS_1) { /* B.A. : Store undefined symbols in pass 1 */ if(def_blacklist(pi, next)==False) return(False); } if(!spool_conditional(pi, False)) return(False); } break; case DIRECTIVE_IF: if(!next) { print_msg(pi, MSGTYPE_ERROR, ".IF needs an expression"); return(True); } get_next_token(next, TERM_END); if(!get_expr(pi, next, &i)) return(False); if(i) pi->conditional_depth++; else { if(!spool_conditional(pi, False)) return(False); } break; case DIRECTIVE_ELSE: case DIRECTIVE_ELIF: case DIRECTIVE_ELSEIF: if(!spool_conditional(pi, True)) return(False); break; case DIRECTIVE_ENDIF: if(pi->conditional_depth == 0) print_msg(pi, MSGTYPE_ERROR, "Too many .ENDIF"); else pi->conditional_depth--; break; case DIRECTIVE_MESSAGE: if(pi->pass == PASS_1) return(True); if(!next) { print_msg(pi, MSGTYPE_ERROR, "No message parameter supplied"); return(True); } /* B.A : Extended .MESSAGE. Now a comma separated list like in .db is possible and not only a string */ print_msg(pi, MSGTYPE_MESSAGE_NO_LF, NULL); /* Prints Line Header (filename, linenumber) without trailing /n */ while(next) { /* Modified code from parse_db(). Thank you :-) */ data = get_next_token(next, TERM_COMMA); if(next[0] == '\"') { /* string parsing */ next = term_string(pi, next); print_msg(pi, MSGTYPE_APPEND,"%s",next); while(*next != '\0') { next++; } } else { if(!get_expr(pi, next, &i)) { print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */ return(False); } print_msg(pi, MSGTYPE_APPEND,"0x%02X",i); } next = data; } print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */ break; case DIRECTIVE_WARNING: if(pi->pass == PASS_1) return(True); if(!next) { print_msg(pi, MSGTYPE_ERROR, "No warning string supplied"); return(True); } next = term_string(pi, next); print_msg(pi, MSGTYPE_WARNING, next); break; case DIRECTIVE_ERROR: if(!next) { /* B.A : Fix segfault bug if .error without parameter was used */ print_msg(pi, MSGTYPE_ERROR, "No error string supplied"); return(True); } next = term_string(pi, next); print_msg(pi, MSGTYPE_ERROR, "%s", next); pi->error_count = pi->max_errors; if(pi->pass == PASS_1) return(True); break; }