Mercurial > hg-old > index.cgi
comparison src/parse.c @ 66:aa9d9fedfdf4
Redid lwasm_parse_line() to correct overly complex logic flaws
author | lost |
---|---|
date | Mon, 05 Jan 2009 05:40:16 +0000 |
parents | aaddd47219b4 |
children | cef25b0088e6 |
comparison
equal
deleted
inserted
replaced
65:31d8e85706e7 | 66:aa9d9fedfdf4 |
---|---|
36 { | 36 { |
37 char *p, *p2; | 37 char *p, *p2; |
38 char *opc; | 38 char *opc; |
39 int opnum; | 39 int opnum; |
40 char *sym = NULL; | 40 char *sym = NULL; |
41 | |
42 // if this was a bad op first pass (or otherwise a no-process line) | |
43 // ignore it | |
44 if (l -> badop) | |
45 return; | |
41 | 46 |
42 p = l -> text; | 47 p = l -> text; |
43 | 48 |
49 // blank lines are a no brainer | |
44 if (!*p) | 50 if (!*p) |
45 { | 51 { |
46 if (as -> inmacro == 0) | 52 as -> context = lwasm_next_context(as); |
47 as -> context = lwasm_next_context(as); | |
48 return 0; | 53 return 0; |
49 } | 54 } |
50 | 55 |
51 // for output generation later but only on pass 1 | 56 // for output generation later but only on pass 1 |
57 // also used by some pseudo ops on pass 2 | |
52 if (as -> passnum == 1) | 58 if (as -> passnum == 1) |
53 l -> codeaddr = as -> addr; | 59 l -> codeaddr = as -> addr; |
54 | 60 |
55 if (!isspace(*p) && *p != '*' && *p != ';') | 61 // if it's a comment, return (this doesn't cause a context change) |
62 if (*p == '*' || *p == ';') | |
63 return; | |
64 | |
65 // if we start with a non-space character, it's a symbol | |
66 if (!isspace(*p)) | |
56 { | 67 { |
57 // we have a symbol specified here | 68 // we have a symbol specified here |
58 // parse it and define | 69 // parse it out and record it for later use |
59 // need to handle local symbols here... | |
60 for (p2 = p; *p2 && !isspace(*p2); p2++) | 70 for (p2 = p; *p2 && !isspace(*p2); p2++) |
61 /* do nothing */ ; | 71 /* do nothing */ ; |
62 | 72 |
63 sym = lwasm_alloc((p2 - p) + 1); | 73 sym = lwasm_alloc((p2 - p) + 1); |
64 sym[p2 - p] = '\0'; | 74 sym[p2 - p] = '\0'; |
65 memcpy(sym, p, p2 - p); | 75 memcpy(sym, p, p2 - p); |
66 | 76 |
67 p = p2; | 77 p = p2; |
68 | |
69 } | 78 } |
70 else | 79 l -> sym = sym; |
71 { | |
72 while (*p && isspace(*p)) | |
73 p++; | |
74 if (!*p) | |
75 { | |
76 if (as -> inmacro == 0) | |
77 as -> context = lwasm_next_context(as); | |
78 return 0; | |
79 } | |
80 } | |
81 | 80 |
82 // skip white space | 81 // now skip any whitespace to find the opcode |
83 while (*p && isspace(*p)) | 82 while (*p && isspace(*p)) |
84 p++; | 83 p++; |
85 | 84 |
86 // if comment or end of line, return | 85 // is the line blank? |
87 if (!*p || *p == '*' || *p == ';') | 86 if (!*p && !sym) |
88 { | 87 { |
89 if (sym) | 88 // nothing but white space *is* a context break |
90 lwasm_free(l -> sym); | 89 as -> context = lwasm_next_context(as); |
91 return 0; | 90 return; |
92 } | 91 } |
93 | 92 |
94 // parse the opcode | 93 // parse the opcode |
95 for (p2 = p; *p2 && !isspace(*p2); p2++) | 94 for (p2 = p; *p2 && !isspace(*p2); p2++) |
96 /* do nothing */ ; | 95 /* do nothing */ ; |
110 { | 109 { |
111 if (!strcasecmp(instab[opnum].opcode, opc)) | 110 if (!strcasecmp(instab[opnum].opcode, opc)) |
112 break; | 111 break; |
113 } | 112 } |
114 | 113 |
114 // if we found no operation, check if we had a comment | |
115 // the reason this check is here is to allow for "private" | |
116 // operation codes like "*pragma" which will be ignored by | |
117 // other assemblers | |
118 if (!(instab[opnum].opcode)) | |
119 { | |
120 if (*opc == '*' || *opc == ';') | |
121 goto done_line; | |
122 } | |
123 | |
124 // now we have the opcode and the symbol, we can decide if we're | |
125 // actually going to do anything with this line | |
126 | |
127 // we will NOT call the function if any of the following are true: | |
128 | |
129 // - we are skipping a condition and the operation code is not a conditional | |
130 // - we are defining a macro and the operation code is not ENDM | |
131 | |
132 // we will call the function in any other circumstance | |
133 | |
134 // first condition above | |
115 if (as -> inmacro && instab[opnum].endm == 0) | 135 if (as -> inmacro && instab[opnum].endm == 0) |
116 { | 136 { |
117 add_macro_line(as, l -> text); | 137 add_macro_line(as, l -> text); |
138 goto done_line; | |
118 } | 139 } |
119 | 140 |
120 if (as -> inmacro == 0 && as -> skipcond == 0) | 141 // second condition above |
142 if (as -> skipcond && instab[opnum].iscond == 0) | |
143 goto done_line; | |
144 | |
145 // register symbol if the operation won't | |
146 if (sym && instab[opnum].setsym == 0) | |
121 { | 147 { |
122 if (expand_macro(as, l, &p2, opc) == 0) | 148 if (as -> passnum == 1) |
123 goto done_line; | |
124 } | |
125 | |
126 // register symbol if needed | |
127 if (as -> skipcond == 0 && as -> inmacro == 0 && sym) | |
128 { | |
129 l -> sym = sym; | |
130 if (as -> passnum == 1 && !(instab[opnum].opcode && instab[opnum].setsym)) | |
131 { | 149 { |
132 // have a symbol; now determine if it is valid and register it | |
133 // at the current address of the line | |
134 debug_message(1, "Registering symbol '%s' at %04X", sym, as -> addr); | 150 debug_message(1, "Registering symbol '%s' at %04X", sym, as -> addr); |
135 if (lwasm_register_symbol(as, l, sym, as -> addr, SYMBOL_NORM) < 0) | 151 if (lwasm_register_symbol(as, l, sym, as -> addr, SYMBOL_NORM) < 0) |
136 l -> sym = NULL; | 152 l -> sym = NULL; |
137 } | 153 } |
138 } | 154 } |
139 | 155 |
140 if (!(instab[opnum].opcode) || !(instab[opnum].fn) && !(as -> skipcond || as -> inmacro)) | 156 // we've registered the symbol as needed |
157 // now we need to check for a macro call IFF we don't collide with | |
158 // an operation code; otherwise, call the operation function | |
159 if (instab[opnum].opcode) | |
141 { | 160 { |
142 // invalid operation code, throw error | 161 if (instab[opnum].fn) |
143 register_error(as, l, 1, "Invalid operation code '%s'", opc); | 162 { |
144 if (sym) | 163 (instab[opnum].fn)(as, l, &p2, opnum); |
145 lwasm_free(l -> sym); | 164 } |
146 lwasm_free(opc); | 165 else |
147 return -1; | 166 { |
167 // carp about unimplemented operation | |
168 register_error(as, l, 1, "Unimplemented operation code: %s", opc); | |
169 } | |
148 } | 170 } |
171 else | |
172 { | |
173 if (expand_macro(as, l, &p2, opc) == 0) | |
174 goto done_line; | |
149 | 175 |
150 // dispatch handler if we're not ignoring items | 176 // carp about an unknown operation code and note that fact for |
151 if (as -> skipcond == 0 && as -> inmacro == 0 && !(instab[opnum].iscond)) | 177 // pass 2 in case a macro appears later with the same name! |
152 (instab[opnum].fn)(as, l, &p2, opnum); | 178 register_error(as, l, 1, "Uknown operation code: %s", opc); |
179 l -> badop = 1; | |
180 } | |
153 | 181 |
154 done_line: | 182 done_line: |
155 lwasm_free(opc); | 183 lwasm_free(opc); |
156 if (sym) | 184 if (sym) |
157 lwasm_free(sym); | 185 lwasm_free(sym); |