# HG changeset patch # User lost # Date 1231134016 0 # Node ID aa9d9fedfdf49033d7ce69419475ac7addde7ff5 # Parent 31d8e85706e7bac3b2f2ea18599613fa53fa728c Redid lwasm_parse_line() to correct overly complex logic flaws diff -r 31d8e85706e7 -r aa9d9fedfdf4 src/parse.c --- a/src/parse.c Mon Jan 05 01:40:01 2009 +0000 +++ b/src/parse.c Mon Jan 05 05:40:16 2009 +0000 @@ -38,25 +38,35 @@ char *opc; int opnum; char *sym = NULL; + + // if this was a bad op first pass (or otherwise a no-process line) + // ignore it + if (l -> badop) + return; p = l -> text; - + + // blank lines are a no brainer if (!*p) { - if (as -> inmacro == 0) - as -> context = lwasm_next_context(as); + as -> context = lwasm_next_context(as); return 0; } // for output generation later but only on pass 1 + // also used by some pseudo ops on pass 2 if (as -> passnum == 1) l -> codeaddr = as -> addr; - if (!isspace(*p) && *p != '*' && *p != ';') + // if it's a comment, return (this doesn't cause a context change) + if (*p == '*' || *p == ';') + return; + + // if we start with a non-space character, it's a symbol + if (!isspace(*p)) { // we have a symbol specified here - // parse it and define - // need to handle local symbols here... + // parse it out and record it for later use for (p2 = p; *p2 && !isspace(*p2); p2++) /* do nothing */ ; @@ -65,30 +75,19 @@ memcpy(sym, p, p2 - p); p = p2; - } - else - { - while (*p && isspace(*p)) - p++; - if (!*p) - { - if (as -> inmacro == 0) - as -> context = lwasm_next_context(as); - return 0; - } - } + l -> sym = sym; - // skip white space + // now skip any whitespace to find the opcode while (*p && isspace(*p)) p++; - // if comment or end of line, return - if (!*p || *p == '*' || *p == ';') + // is the line blank? + if (!*p && !sym) { - if (sym) - lwasm_free(l -> sym); - return 0; + // nothing but white space *is* a context break + as -> context = lwasm_next_context(as); + return; } // parse the opcode @@ -112,44 +111,73 @@ break; } + // if we found no operation, check if we had a comment + // the reason this check is here is to allow for "private" + // operation codes like "*pragma" which will be ignored by + // other assemblers + if (!(instab[opnum].opcode)) + { + if (*opc == '*' || *opc == ';') + goto done_line; + } + + // now we have the opcode and the symbol, we can decide if we're + // actually going to do anything with this line + + // we will NOT call the function if any of the following are true: + + // - we are skipping a condition and the operation code is not a conditional + // - we are defining a macro and the operation code is not ENDM + + // we will call the function in any other circumstance + + // first condition above if (as -> inmacro && instab[opnum].endm == 0) { add_macro_line(as, l -> text); + goto done_line; } - if (as -> inmacro == 0 && as -> skipcond == 0) + // second condition above + if (as -> skipcond && instab[opnum].iscond == 0) + goto done_line; + + // register symbol if the operation won't + if (sym && instab[opnum].setsym == 0) { - if (expand_macro(as, l, &p2, opc) == 0) - goto done_line; - } - - // register symbol if needed - if (as -> skipcond == 0 && as -> inmacro == 0 && sym) - { - l -> sym = sym; - if (as -> passnum == 1 && !(instab[opnum].opcode && instab[opnum].setsym)) + if (as -> passnum == 1) { - // have a symbol; now determine if it is valid and register it - // at the current address of the line debug_message(1, "Registering symbol '%s' at %04X", sym, as -> addr); if (lwasm_register_symbol(as, l, sym, as -> addr, SYMBOL_NORM) < 0) l -> sym = NULL; } } - if (!(instab[opnum].opcode) || !(instab[opnum].fn) && !(as -> skipcond || as -> inmacro)) + // we've registered the symbol as needed + // now we need to check for a macro call IFF we don't collide with + // an operation code; otherwise, call the operation function + if (instab[opnum].opcode) { - // invalid operation code, throw error - register_error(as, l, 1, "Invalid operation code '%s'", opc); - if (sym) - lwasm_free(l -> sym); - lwasm_free(opc); - return -1; + if (instab[opnum].fn) + { + (instab[opnum].fn)(as, l, &p2, opnum); + } + else + { + // carp about unimplemented operation + register_error(as, l, 1, "Unimplemented operation code: %s", opc); + } } + else + { + if (expand_macro(as, l, &p2, opc) == 0) + goto done_line; - // dispatch handler if we're not ignoring items - if (as -> skipcond == 0 && as -> inmacro == 0 && !(instab[opnum].iscond)) - (instab[opnum].fn)(as, l, &p2, opnum); + // carp about an unknown operation code and note that fact for + // pass 2 in case a macro appears later with the same name! + register_error(as, l, 1, "Uknown operation code: %s", opc); + l -> badop = 1; + } done_line: lwasm_free(opc);