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);