1 /*
2 $Id: error.c 2620 2021-04-25 12:05:16Z soci $
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 */
19 #include "error.h"
20 #include <string.h>
21 #include <errno.h>
22 #include "wchar.h"
23 #include "file.h"
24 #include "64tass.h"
25 #include "unicode.h"
26 #include "eval.h"
27 #include "arguments.h"
28 #include "opcodes.h"
29 #include "section.h"
30 #include "macro.h"
31
32 #include "strobj.h"
33 #include "addressobj.h"
34 #include "registerobj.h"
35 #include "namespaceobj.h"
36 #include "operobj.h"
37 #include "typeobj.h"
38 #include "labelobj.h"
39 #include "errorobj.h"
40 #include "noneobj.h"
41 #include "symbolobj.h"
42 #include "anonsymbolobj.h"
43 #include "console.h"
44
45 struct file_list_s *current_file_list;
46 const struct file_list_s *dummy_file_list;
47
48 #define ALIGN(v) (((v) + (sizeof(int *) - 1)) & ~(sizeof(int *) - 1))
49
50 static unsigned int errors = 0, warnings = 0;
51
52 struct file_listnode_s {
53 struct file_list_s flist;
54 struct file_listnode_s *parent;
55 struct avltree_node node;
56 struct avltree members;
57 uint8_t pass;
58 };
59
60 static struct file_listnode_s file_list;
61 static const struct file_listnode_s *included_from = &file_list;
62 static const char *prgname;
63
64 struct errorbuffer_s {
65 size_t max;
66 size_t len;
67 size_t header_pos;
68 size_t header_stop;
69 uint8_t *data;
70 struct avltree members;
71 };
72
73 static struct errorbuffer_s error_list;
74 static struct avltree notdefines;
75
76 typedef enum Severity_types {
77 SV_NOTE, SV_WARNING, SV_NONEERROR, SV_ERROR, SV_FATAL
78 } Severity_types;
79
80 struct errorentry_s {
81 Severity_types severity;
82 size_t error_len;
83 size_t line_len;
84 const struct file_list_s *file_list;
85 struct linepos_s epoint;
86 linecpos_t caret;
87 struct avltree_node node;
88 };
89
90 struct notdefines_s {
91 str_t cfname;
92 const struct file_list_s *file_list;
93 struct linepos_s epoint;
94 uint8_t pass;
95 struct avltree_node node;
96 };
97
duplicate_compare(const struct avltree_node * aa,const struct avltree_node * bb)98 static FAST_CALL int duplicate_compare(const struct avltree_node *aa, const struct avltree_node *bb)
99 {
100 const struct errorentry_s *a = cavltree_container_of(aa, struct errorentry_s, node);
101 const struct errorentry_s *b = cavltree_container_of(bb, struct errorentry_s, node);
102 const uint8_t *aerr, *berr;
103
104 if (a->severity != b->severity) return (int)a->severity - (int)b->severity;
105 if (a->file_list != b->file_list) return a->file_list > b->file_list ? 1 : -1;
106 if (a->error_len != b->error_len) return a->error_len > b->error_len ? 1 : -1;
107 if (a->epoint.line != b->epoint.line) return a->epoint.line > b->epoint.line ? 1 : -1;
108 if (a->epoint.pos != b->epoint.pos) return a->epoint.pos > b->epoint.pos ? 1 : -1;
109
110 aerr = (const uint8_t *)(a + 1);
111 berr = (const uint8_t *)(b + 1);
112
113 if ((a->line_len | b->line_len) != 0) {
114 int i;
115 const uint8_t *aline, *bline;
116
117 if (a->line_len != 0) {
118 aline = aerr;
119 aerr += a->line_len;
120 } else if (a->epoint.line == 0) {
121 aline = (const uint8_t *)"";
122 } else {
123 aline = &a->file_list->file->data[a->file_list->file->line[a->epoint.line - 1]];
124 }
125
126 if (b->line_len != 0) {
127 bline = berr;
128 berr += b->line_len;
129 } else if (a->epoint.line == 0) {
130 bline = (const uint8_t *)"";
131 } else {
132 bline = &a->file_list->file->data[a->file_list->file->line[a->epoint.line - 1]];
133 }
134
135 i = strcmp((const char *)aline, (const char *)bline);
136 if (i != 0) return i;
137 }
138 return memcmp(aerr, berr, a->error_len);
139 }
140
close_error(void)141 static void close_error(void) {
142 static bool duplicate;
143 if (error_list.header_pos < error_list.len) {
144 struct errorentry_s *err = (struct errorentry_s *)&error_list.data[error_list.header_pos];
145 err->error_len = error_list.len - error_list.header_pos - (sizeof *err) - err->line_len;
146 switch (err->severity) {
147 case SV_NOTE:
148 if (!duplicate) memset(&err->node, 0, sizeof err->node);
149 break;
150 default:
151 duplicate = avltree_insert(&err->node, &error_list.members, duplicate_compare) != NULL;
152 }
153 if (duplicate) {
154 error_list.len = error_list.header_pos;
155 }
156 error_list.header_pos = ALIGN(error_list.len);
157 }
158 }
159
error_extend(void)160 static void error_extend(void) {
161 struct errorentry_s *err;
162 uint8_t *data = (uint8_t *)realloc(error_list.data, error_list.max);
163 size_t diff, pos;
164 bool dir;
165 if (data == NULL) err_msg_out_of_memory2();
166 dir = data >= error_list.data;
167 diff = dir ? (size_t)(data - error_list.data) : (size_t)(error_list.data - data);
168 error_list.data = data;
169 if (diff == 0) return;
170 for (pos = 0; pos < error_list.header_pos; pos = ALIGN(pos + (sizeof *err) + err->line_len + err->error_len)) {
171 err = (struct errorentry_s *)&data[pos];
172 if (err->node.left != NULL) err->node.left = (struct avltree_node *)((dir ? ((uint8_t *)err->node.left + diff) : ((uint8_t *)err->node.left - diff)));
173 if (err->node.right != NULL) err->node.right = (struct avltree_node *)((dir ? ((uint8_t *)err->node.right + diff) : ((uint8_t *)err->node.right - diff)));
174 if (err->node.parent != NULL) err->node.parent = (struct avltree_node *)((dir ? ((uint8_t *)err->node.parent + diff) : ((uint8_t *)err->node.parent - diff)));
175 }
176 if (error_list.members.root != NULL) error_list.members.root = (struct avltree_node *)((dir ? ((uint8_t *)error_list.members.root + diff) : ((uint8_t *)error_list.members.root - diff)));
177 }
178
new_error_msg_common(Severity_types severity,const struct file_list_s * flist,linepos_t epoint,size_t line_len,linecpos_t pos)179 static void new_error_msg_common(Severity_types severity, const struct file_list_s *flist, linepos_t epoint, size_t line_len, linecpos_t pos) {
180 struct errorentry_s *err;
181 close_error();
182 error_list.len = error_list.header_pos + sizeof *err;
183 if (error_list.len < sizeof *err) err_msg_out_of_memory2(); /* overflow */
184 error_list.len += line_len;
185 if (error_list.len < line_len) err_msg_out_of_memory2(); /* overflow */
186 if (error_list.len > error_list.max) {
187 error_list.max = error_list.len + 0x200;
188 if (error_list.max < 0x200) err_msg_out_of_memory2(); /* overflow */
189 error_extend();
190 }
191 err = (struct errorentry_s *)&error_list.data[error_list.header_pos];
192 err->severity = severity;
193 err->error_len = 0;
194 err->line_len = line_len;
195 err->file_list = flist;
196 err->epoint.line = epoint->line;
197 err->epoint.pos = pos;
198 err->caret = epoint->pos;
199 }
200
201 static struct {
202 Severity_types severity;
203 const struct file_list_s *flist;
204 linepos_t epoint;
205 } new_error_msg_more_param;
206
207 static void new_error_msg_more(void);
new_error_msg(Severity_types severity,const struct file_list_s * flist,linepos_t epoint)208 static bool new_error_msg(Severity_types severity, const struct file_list_s *flist, linepos_t epoint) {
209 size_t line_len;
210 if (in_macro && flist == current_file_list && epoint->line == lpoint.line) {
211 struct linepos_s opoint;
212 const struct file_list_s *eflist = macro_error_translate(&opoint, epoint->pos);
213 if (eflist != NULL) {
214 new_error_msg_common(severity, eflist, &opoint, 0, opoint.pos);
215 new_error_msg_more_param.severity = severity;
216 new_error_msg_more_param.flist = flist;
217 new_error_msg_more_param.epoint = epoint;
218 return true;
219 }
220 }
221 switch (severity) {
222 case SV_NOTE: line_len = 0; break;
223 default: line_len = ((epoint->line == lpoint.line) && not_in_file(pline, flist->file)) ? (strlen((const char *)pline) + 1) : 0; break;
224 }
225 new_error_msg_common(severity, flist, epoint, line_len, macro_error_translate2(epoint->pos));
226 if (line_len != 0) memcpy(&error_list.data[error_list.header_pos + sizeof(struct errorentry_s)], pline, line_len);
227 return false;
228 }
229
new_error_msg_err(const Error * err)230 static bool new_error_msg_err(const Error *err) {
231 struct linepos_s opoint;
232 size_t line_len;
233 if (in_macro && err->file_list == current_file_list && err->epoint.line == lpoint.line) {
234 const struct file_list_s *eflist = macro_error_translate(&opoint, err->caret);
235 if (eflist != NULL) {
236 new_error_msg_common(SV_ERROR, eflist, &opoint, 0, opoint.pos);
237 return true;
238 }
239 }
240 if (err->line == NULL) {
241 opoint = err->epoint;
242 line_len = 0;
243 } else {
244 opoint.line = err->epoint.line;
245 opoint.pos = err->caret;
246 line_len = strlen((const char *)err->line) + 1;
247 }
248 new_error_msg_common(SV_ERROR, err->file_list, &opoint, line_len, err->epoint.pos);
249 if (line_len != 0) memcpy(&error_list.data[error_list.header_pos + sizeof(struct errorentry_s)], err->line, line_len);
250 return false;
251 }
252
new_error_msg2(bool type,linepos_t epoint)253 static void new_error_msg2(bool type, linepos_t epoint) {
254 Severity_types severity = type ? SV_ERROR : SV_WARNING;
255 bool more = new_error_msg(severity, current_file_list, epoint);
256 if (more) new_error_msg_more();
257 }
258
file_list_compare(const struct avltree_node * aa,const struct avltree_node * bb)259 static FAST_CALL int file_list_compare(const struct avltree_node *aa, const struct avltree_node *bb)
260 {
261 const struct file_list_s *a = &cavltree_container_of(aa, struct file_listnode_s, node)->flist;
262 const struct file_list_s *b = &cavltree_container_of(bb, struct file_listnode_s, node)->flist;
263 if (a->epoint.line != b->epoint.line) return a->epoint.line > b->epoint.line ? 1 : -1;
264 if (a->epoint.pos != b->epoint.pos) return a->epoint.pos > b->epoint.pos ? 1 : -1;
265 return a->file->uid - b->file->uid;
266 }
267
268 static struct file_lists_s {
269 struct file_listnode_s file_lists[90];
270 struct file_lists_s *next;
271 } *file_lists = NULL;
272
parent_file_list(const struct file_list_s * cflist)273 const struct file_list_s *parent_file_list(const struct file_list_s *cflist) {
274 return &((const struct file_listnode_s *)cflist)->parent->flist;
275 }
276
277 static struct file_listnode_s *lastfl;
278 static int file_listsp;
enterfile(struct file_s * file,linepos_t epoint)279 void enterfile(struct file_s *file, linepos_t epoint) {
280 struct avltree_node *b;
281 struct file_listnode_s *cflist = (struct file_listnode_s *)current_file_list;
282 lastfl->flist.file = file;
283 lastfl->flist.epoint = *epoint;
284 b = avltree_insert(&lastfl->node, &cflist->members, file_list_compare);
285 if (b == NULL) {
286 lastfl->parent = cflist;
287 avltree_init(&lastfl->members);
288 cflist = lastfl;
289 if (file_listsp == 89) {
290 struct file_lists_s *old = file_lists;
291 file_lists = (struct file_lists_s *)mallocx(sizeof *file_lists);
292 file_lists->next = old;
293 file_listsp = 0;
294 } else file_listsp++;
295 lastfl = &file_lists->file_lists[file_listsp];
296 } else {
297 cflist = avltree_container_of(b, struct file_listnode_s, node);
298 }
299 cflist->pass = pass;
300 current_file_list = &cflist->flist;
301 }
302
exitfile(void)303 void exitfile(void) {
304 struct file_listnode_s *cflist = (struct file_listnode_s *)current_file_list;
305 if (cflist->parent != NULL) current_file_list = &cflist->parent->flist;
306 }
307
adderror2(const uint8_t * s,size_t len)308 static void adderror2(const uint8_t *s, size_t len) {
309 if (len + error_list.len > error_list.max) {
310 error_list.max += (len > 0x200) ? len : 0x200;
311 error_extend();
312 }
313 memcpy(error_list.data + error_list.len, s, len);
314 error_list.len += len;
315 }
316
adderror(const char * s)317 static void adderror(const char *s) {
318 adderror2((const uint8_t *)s, strlen(s));
319 }
320
321 static const char * const terr_warning[] = {
322 "deprecated modulo operator, use '%' instead",
323 "deprecated not equal operator, use '!=' instead",
324 "deprecated directive, only for TASM compatible mode",
325 "please use format(\"%d\", ...) as '^' will change it's meaning",
326 "please use quotes now to allow expressions in future",
327 "constant result, possibly changeable to 'lda'",
328 "independent result, possibly changeable to 'lda'",
329 #ifdef _WIN32
330 "the file's real name is not '",
331 #endif
332 #if defined _WIN32 || defined __WIN32__ || defined __MSDOS__ || defined __DOS__
333 "use '/' as path separation '",
334 #else
335 "this name uses reserved characters '",
336 #endif
337 "use relative path for '"
338 };
339
340 static const char * const terr_error[] = {
341 "double defined range",
342 "double defined escape",
343 "extra characters on line",
344 "more than two characters",
345 "floating point overflow",
346 "general syntax",
347 "expression syntax",
348 "label required",
349 "division by zero ",
350 "zero value not allowed",
351 "most significiant bit must be clear in byte",
352 "at least one byte is needed",
353 "last byte must not be gap",
354 "address in different program bank ",
355 "address out of section",
356 "negative number raised on fractional power",
357 "zero raised to negative power ",
358 "square root of negative number ",
359 "logarithm of non-positive number ",
360 "not in range -1.0 to 1.0 ",
361 "empty range not allowed",
362 "empty string not allowed",
363 "empty list not allowed",
364 "more than a single character",
365 "requirements not met",
366 "conflict",
367 "index out of range ",
368 "key not in dictionary ",
369 "offset out of range",
370 "not hashable ",
371 "not a key and value pair ",
372 "too large for a %u bit signed integer ",
373 "too large for a %u bit unsigned integer ",
374 "value needs to be non-negative ",
375 "operands could not be broadcast together with shapes %" PRIuSIZE " and %" PRIuSIZE,
376 "can't get sign of ",
377 "can't get absolute value of ",
378 "can't get integer value of ",
379 "can't get length of ",
380 "can't get size of ",
381 "can't get boolean value of ",
382 "not iterable ",
383 "no byte sized",
384 "no word sized",
385 "no long sized",
386 "not a direct page address ",
387 "not a data bank address ",
388 "not a bank 0 address ",
389 "out of memory",
390 "addressing mode too complex",
391 "empty encoding, add something or correct name",
392 "closing directive '",
393 "opening directive '",
394 "must be used within a loop",
395 "not measurable as start offset beyond size of original"
396 };
397
398 static const char * const terr_fatal[] = {
399 "can't open file",
400 "error reading file",
401 "can't write object file",
402 "can't write listing file",
403 "can't write label file",
404 "can't write make file",
405 "can't write error file",
406 "file recursion",
407 "macro recursion too deep",
408 "function recursion too deep",
409 "weak recursion too deep",
410 "too many passes"
411 };
412
err_msg_variable(Obj * val)413 static void err_msg_variable(Obj *val) {
414 Obj *err;
415 adderror(val->obj->name);
416 err = val->obj->str(val, NULL, 40);
417 if (err != NULL) {
418 if (err->obj == STR_OBJ) {
419 Str *str = Str(err);
420 adderror(" '");
421 adderror2(str->data, str->len);
422 adderror("'");
423 }
424 val_destroy(err);
425 }
426 }
427
str_name(const uint8_t * data,size_t len)428 static void str_name(const uint8_t *data, size_t len) {
429 adderror(" '");
430 if (len != 0) {
431 if (data[0] == '-') {
432 adderror("-");
433 } else if (data[0] == '+') {
434 adderror("+");
435 } else if (data[0] == '.' || data[0] == '#') {
436 adderror("<anonymous>");
437 } else adderror2(data, len);
438 }
439 adderror("'");
440 }
441
442 static void err_opcode(uint32_t);
443
err_msg2(Error_types no,const void * prm,linepos_t epoint)444 void err_msg2(Error_types no, const void *prm, linepos_t epoint) {
445 bool more;
446 if (no < 0x40) {
447 switch (no) {
448 case ERROR___OPTIMIZABLE:
449 new_error_msg2(diagnostic_errors.optimize, epoint);
450 adderror("could be shorter by using '");
451 adderror((const char *)prm);
452 adderror("' instead");
453 adderror(" [-Woptimize]");
454 break;
455 case ERROR______SIMPLIFY:
456 new_error_msg2(diagnostic_errors.optimize, epoint);
457 adderror("could be simpler by using '");
458 adderror((const char *)prm);
459 adderror("' instead");
460 adderror(" [-Woptimize]");
461 break;
462 case ERROR_____REDUNDANT:
463 new_error_msg2(diagnostic_errors.optimize, epoint);
464 adderror("possibly redundant ");
465 adderror((const char *)prm);
466 adderror(" [-Woptimize]");
467 break;
468 case ERROR__CONST_RESULT:
469 new_error_msg2(diagnostic_errors.optimize, epoint);
470 adderror(terr_warning[no]);
471 adderror(" [-Woptimize]");
472 break;
473 case ERROR_______OLD_NEQ:
474 case ERROR____OLD_MODULO:
475 case ERROR____OLD_STRING:
476 case ERROR_______OLD_ENC:
477 new_error_msg2(diagnostic_errors.deprecated, epoint);
478 adderror(terr_warning[no]);
479 adderror(" [-Wdeprecated]");
480 break;
481 case ERROR_____OLD_EQUAL:
482 new_error_msg2(diagnostic_errors.old_equal, epoint);
483 adderror("deprecated equal operator, use '==' instead [-Wold-equal]");
484 break;
485 case ERROR_NONIMMEDCONST:
486 new_error_msg2(diagnostic_errors.immediate, epoint);
487 adderror("immediate addressing mode suggested [-Wimmediate]");
488 break;
489 case ERROR_LEADING_ZEROS:
490 new_error_msg2(diagnostic_errors.leading_zeros, epoint);
491 adderror("leading zeros ignored [-Wleading-zeros]");
492 break;
493 case ERROR_DIRECTIVE_IGN:
494 new_error_msg2(diagnostic_errors.ignored, epoint);
495 adderror("directive ignored [-Wignored]");
496 break;
497 case ERROR_FLOAT_COMPARE:
498 new_error_msg2(diagnostic_errors.float_compare, epoint);
499 adderror("approximate floating point ");
500 adderror((const char *)prm);
501 adderror("' [-Wfloat-compare]");
502 break;
503 case ERROR___FLOAT_ROUND:
504 new_error_msg2(diagnostic_errors.float_round, epoint);
505 adderror("implicit floating point rounding [-Wfloat-round]");
506 break;
507 case ERROR___LONG_BRANCH:
508 new_error_msg2(diagnostic_errors.long_branch, epoint);
509 adderror("long branch used [-Wlong-branch]");
510 break;
511 case ERROR_WUSER_DEFINED:
512 more = new_error_msg(SV_WARNING, current_file_list, epoint);
513 adderror2(((const Str *)prm)->data, ((const Str *)prm)->len);
514 if (more) new_error_msg_more();
515 break;
516 #ifdef _WIN32
517 case ERROR___INSENSITIVE:
518 #endif
519 #if defined _WIN32 || defined __WIN32__ || defined __MSDOS__ || defined __DOS__
520 case ERROR_____BACKSLASH:
521 #else
522 case ERROR__RESERVED_CHR:
523 #endif
524 case ERROR_ABSOLUTE_PATH:
525 new_error_msg2(diagnostic_errors.portable, epoint);
526 adderror(terr_warning[no]);
527 adderror2(((const str_t *)prm)->data, ((const str_t *)prm)->len);
528 adderror("' [-Wportable]");
529 break;
530 default:
531 more = new_error_msg(SV_WARNING, current_file_list, epoint);
532 adderror(terr_warning[no]);
533 if (more) new_error_msg_more();
534 break;
535 }
536 return;
537 }
538
539 if (no < 0xc0) {
540 char line[1024];
541 more = new_error_msg(SV_ERROR, current_file_list, epoint);
542 switch (no) {
543 case ERROR_BRANCH_TOOFAR:
544 sprintf(line,"branch too far by %+d bytes", *(const int *)prm); adderror(line);
545 break;
546 case ERROR____PTEXT_LONG:
547 sprintf(line,"ptext too long by %" PRIuSIZE " bytes", *(const size_t *)prm - 0x100); adderror(line);
548 break;
549 case ERROR__BRANCH_CROSS:
550 sprintf(line,"branch crosses page by %+d bytes", *(const int *)prm); adderror(line);
551 break;
552 case ERROR__USER_DEFINED:
553 adderror2(((const Str *)prm)->data, ((const Str *)prm)->len);
554 break;
555 case ERROR______EXPECTED:
556 adderror((const char *)prm);
557 adderror(" expected");
558 break;
559 case ERROR__MISSING_OPEN:
560 case ERROR_MISSING_CLOSE:
561 adderror(terr_error[no - 0x40]);
562 adderror((const char *)prm);
563 adderror("' not found");
564 break;
565 case ERROR_RESERVED_LABL:
566 adderror("reserved symbol name '");
567 adderror2(((const str_t *)prm)->data, ((const str_t *)prm)->len);
568 adderror("'");
569 break;
570 case ERROR_____NOT_BANK0:
571 case ERROR____NOT_DIRECT:
572 case ERROR__NOT_DATABANK:
573 case ERROR_CANT_CROSS_BA:
574 adderror(terr_error[no - 0x40]);
575 if (prm != NULL) err_msg_variable((Obj *)prm);
576 break;
577 case ERROR___UNKNOWN_CPU:
578 adderror("unknown processor '");
579 adderror2(((const str_t *)prm)->data, ((const str_t *)prm)->len);
580 adderror("'");
581 break;
582 case ERROR__NO_BYTE_ADDR:
583 case ERROR__NO_WORD_ADDR:
584 case ERROR__NO_LONG_ADDR:
585 adderror(terr_error[no - 0x40]);
586 err_opcode(*(const uint32_t *)prm);
587 break;
588 default:
589 adderror(terr_error[no - 0x40]);
590 }
591 if (more) new_error_msg_more();
592 return;
593 }
594
595 more = new_error_msg(SV_FATAL, current_file_list, epoint);
596 switch (no) {
597 case ERROR_UNKNOWN_OPTIO:
598 adderror("unknown option '");
599 adderror2(((const str_t *)prm)->data, ((const str_t *)prm)->len);
600 adderror("'");
601 break;
602 case ERROR____LABEL_ROOT:
603 adderror("scope '");
604 adderror2(((const str_t *)prm)->data, ((const str_t *)prm)->len);
605 adderror("' for label listing not found");
606 break;
607 case ERROR__SECTION_ROOT:
608 adderror("section '");
609 adderror2(((const str_t *)prm)->data, ((const str_t *)prm)->len);
610 adderror("' for output not found");
611 break;
612 default:
613 adderror(terr_fatal[no - 0xc0]);
614 }
615 if (more) new_error_msg_more();
616 }
617
err_msg(Error_types no,const void * prm)618 void err_msg(Error_types no, const void* prm) {
619 err_msg2(no, prm, &lpoint);
620 }
621
err_msg_str_name(const char * msg,const str_t * name,linepos_t epoint)622 static void err_msg_str_name(const char *msg, const str_t *name, linepos_t epoint) {
623 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
624 adderror(msg);
625 if (name != NULL) str_name(name->data, name->len);
626 if (more) new_error_msg_more();
627 }
628
err_msg_big_address(linepos_t epoint)629 void err_msg_big_address(linepos_t epoint) {
630 Obj *val = get_star_value(current_address->l_address, current_address->l_address_val);
631 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
632 adderror("address not in processor address space ");
633 err_msg_variable(val);
634 val_destroy(val);
635 if (more) new_error_msg_more();
636 }
637
err_msg_big_integer(const Error * err)638 static bool err_msg_big_integer(const Error *err) {
639 char msg2[256];
640 bool more = new_error_msg_err(err);
641 sprintf(msg2, terr_error[err->num - 0x40], err->u.intconv.bits);
642 adderror(msg2);
643 err_msg_variable(err->u.intconv.val);
644 return more;
645 }
646
new_error_msg_err_more(const Error * err)647 static void new_error_msg_err_more(const Error *err) {
648 size_t line_len;
649 struct linepos_s opoint;
650 if (err->line == NULL) {
651 opoint = err->epoint;
652 line_len = 0;
653 } else {
654 opoint.line = err->epoint.line;
655 opoint.pos = err->caret;
656 line_len = strlen((const char *)err->line) + 1;
657 }
658 new_error_msg_common(SV_NOTE, err->file_list, &opoint, line_len, err->epoint.pos);
659 if (line_len != 0) memcpy(&error_list.data[error_list.header_pos + sizeof(struct errorentry_s)], err->line, line_len);
660 adderror("original location in an expanded macro was here");
661 }
662
new_error_msg_more(void)663 static void new_error_msg_more(void) {
664 const struct file_list_s *flist = new_error_msg_more_param.flist;
665 linepos_t epoint = new_error_msg_more_param.epoint;
666 size_t line_len;
667 switch (new_error_msg_more_param.severity) {
668 case SV_NOTE: line_len = 0; break;
669 default: line_len = ((epoint->line == lpoint.line) && not_in_file(pline, flist->file)) ? (strlen((const char *)pline) + 1) : 0; break;
670 }
671 new_error_msg_common(SV_NOTE, flist, epoint, line_len, macro_error_translate2(epoint->pos));
672 if (line_len != 0) memcpy(&error_list.data[error_list.header_pos + sizeof(struct errorentry_s)], pline, line_len);
673 adderror("original location in an expanded macro was here");
674 }
675
err_msg_invalid_conv(const Error * err)676 static bool err_msg_invalid_conv(const Error *err) {
677 bool more;
678 Obj *v1 = err->u.conv.val;
679 if (v1->obj == ERROR_OBJ) {
680 err_msg_output((const Error *)v1);
681 return false;
682 }
683 more = new_error_msg_err(err);
684 adderror("conversion of ");
685 err_msg_variable(v1);
686 adderror(" to ");
687 adderror(err->u.conv.t->name);
688 adderror(" is not possible");
689 return more;
690 }
691
notdefines_compare(const struct avltree_node * aa,const struct avltree_node * bb)692 static FAST_CALL int notdefines_compare(const struct avltree_node *aa, const struct avltree_node *bb)
693 {
694 const struct notdefines_s *a = cavltree_container_of(aa, struct notdefines_s, node);
695 const struct notdefines_s *b = cavltree_container_of(bb, struct notdefines_s, node);
696 if (a->file_list != b->file_list) return a->file_list > b->file_list ? 1 : -1;
697 if (a->epoint.line != b->epoint.line) return a->epoint.line > b->epoint.line ? 1 : -1;
698 if (a->epoint.pos != b->epoint.pos) return a->epoint.pos > b->epoint.pos ? 1 : -1;
699 return str_cmp(&a->cfname, &b->cfname);
700 }
701
notdefines_free(struct avltree_node * aa)702 static void notdefines_free(struct avltree_node *aa) {
703 struct notdefines_s *a = avltree_container_of(aa, struct notdefines_s, node);
704 free((uint8_t *)a->cfname.data);
705 free(a);
706 }
707
708 static struct notdefines_s *lastnd = NULL;
err_msg_not_defined3(const Error * err)709 static void err_msg_not_defined3(const Error *err) {
710 Namespace *l = err->u.notdef.names;
711 struct notdefines_s *tmp2;
712 struct avltree_node *b;
713 bool more;
714
715 if (constcreated && pass < max_pass) return;
716
717 if (lastnd == NULL) {
718 lastnd = (struct notdefines_s *)mallocx(sizeof *lastnd);
719 }
720
721 if (err->u.notdef.symbol->obj == SYMBOL_OBJ) {
722 const str_t *name = &Symbol(err->u.notdef.symbol)->name;
723 str_cfcpy(&lastnd->cfname, name);
724 lastnd->file_list = l->file_list;
725 lastnd->epoint = l->epoint;
726 lastnd->pass = pass;
727 b = avltree_insert(&lastnd->node, ¬defines, notdefines_compare);
728 if (b != NULL) {
729 tmp2 = avltree_container_of(b, struct notdefines_s, node);
730 if (tmp2->pass == pass) {
731 return;
732 }
733 tmp2->pass = pass;
734 } else {
735 if (lastnd->cfname.data == name->data) str_cpy(&lastnd->cfname, name);
736 else str_cfcpy(&lastnd->cfname, NULL);
737 lastnd = NULL;
738 }
739 }
740
741 more = new_error_msg_err(err);
742 adderror("not defined ");
743 err_msg_variable(err->u.notdef.symbol);
744 if (more) new_error_msg_err_more(err);
745
746 if (l->file_list == NULL) {
747 struct linepos_s nopoint = {0, 0};
748 new_error_msg(SV_NOTE, err->file_list, &nopoint);
749 adderror("searched in the global scope");
750 } else {
751 new_error_msg(SV_NOTE, l->file_list, &l->epoint);
752 if (err->u.notdef.down) adderror("searched in this scope and in all it's parents");
753 else adderror("searched in this object only");
754 }
755 }
756
err_msg_not_defined2(const str_t * name,Namespace * l,bool down,linepos_t epoint)757 void err_msg_not_defined2(const str_t *name, Namespace *l, bool down, linepos_t epoint) {
758 Error *err = new_error(ERROR___NOT_DEFINED, epoint);
759 err->u.notdef.down = down;
760 err->u.notdef.names = ref_namespace(l);
761 err->u.notdef.symbol = new_symbol(name, epoint);
762 err_msg_not_defined3(err);
763 val_destroy(Obj(err));
764 }
765
err_msg_not_defined2a(ssize_t count,Namespace * l,bool down,linepos_t epoint)766 void err_msg_not_defined2a(ssize_t count, Namespace *l, bool down, linepos_t epoint) {
767 Error *err = new_error(ERROR___NOT_DEFINED, epoint);
768 err->u.notdef.down = down;
769 err->u.notdef.names = ref_namespace(l);
770 err->u.notdef.symbol = new_anonsymbol(count);
771 err_msg_not_defined3(err);
772 val_destroy(Obj(err));
773 }
774
err_opcode(uint32_t cod)775 static void err_opcode(uint32_t cod) {
776 adderror(" addressing mode ");
777 if (cod != 0) {
778 char tmp[17];
779 memcpy(tmp, "for opcode 'xxx'", sizeof tmp);
780 tmp[12] = (char)(cod >> 16);
781 tmp[13] = (char)(cod >> 8);
782 tmp[14] = (char)cod;
783 adderror(tmp);
784 } else adderror("accepted");
785 }
786
err_msg_no_addressing(atype_t addrtype,uint32_t cod)787 static void err_msg_no_addressing(atype_t addrtype, uint32_t cod) {
788 adderror("no");
789 if (addrtype == A_NONE) adderror(" implied");
790 for (; (addrtype & MAX_ADDRESS_MASK) != 0; addrtype <<= 4) {
791 const char *txt = "?";
792 switch ((Address_types)((addrtype & 0xf000) >> 12)) {
793 case A_NONE: continue;
794 case A_IMMEDIATE: txt = " immediate"; break;
795 case A_IMMEDIATE_SIGNED: txt = " signed immediate"; break;
796 case A_XR: txt = " x indexed"; break;
797 case A_YR: txt = " y indexed"; break;
798 case A_ZR: txt = " z indexed"; break;
799 case A_SR: txt = " stack"; break;
800 case A_RR: txt = " data stack"; break;
801 case A_DR: txt = " direct page"; break;
802 case A_BR: txt = " data bank"; break;
803 case A_KR: txt = " program bank"; break;
804 case A_I: txt = " indirect"; break;
805 case A_LI: txt = " long indirect"; break;
806 }
807 adderror(txt);
808 }
809 err_opcode(cod);
810 }
811
err_msg_no_register(const Error * err)812 static bool err_msg_no_register(const Error *err) {
813 bool more = new_error_msg_err(err);
814 Register *val = err->u.reg.reg;
815 adderror("no register '");
816 adderror2(val->data, val->len);
817 adderror("'");
818 err_opcode(err->u.reg.cod);
819 return more;
820 }
821
err_msg_no_lot_operand(const Error * err)822 static bool err_msg_no_lot_operand(const Error *err) {
823 char msg2[256];
824 bool more = new_error_msg_err(err);
825 sprintf(msg2, "no %" PRIuSIZE " operand", err->u.opers.num);
826 adderror(msg2);
827 err_opcode(err->u.opers.cod);
828 return more;
829 }
830
err_msg_cant_broadcast(const Error * err)831 static bool err_msg_cant_broadcast(const Error *err) {
832 char msg2[256];
833 bool more = new_error_msg_err(err);
834 sprintf(msg2, terr_error[err->num - 0x40], err->u.broadcast.v1, err->u.broadcast.v2);
835 adderror(msg2);
836 return more;
837 }
838
err_msg_invalid_oper2(Oper_types op,Obj * v1,Obj * v2)839 static void err_msg_invalid_oper2(Oper_types op, Obj *v1, Obj *v2) {
840 adderror(operators[op].name);
841 adderror("' of ");
842 err_msg_variable(v1);
843 if (v2 != NULL) {
844 adderror(" and ");
845 err_msg_variable(v2);
846 }
847 adderror(" not possible");
848 }
849
err_msg_invalid_oper3(const Error * err)850 static void err_msg_invalid_oper3(const Error *err) {
851 Obj *v1 = err->u.invoper.v1, *v2;
852 bool more;
853 if (v1->obj == ERROR_OBJ) {
854 err_msg_output((const Error *)v1);
855 return;
856 }
857 v2 = err->u.invoper.v2;
858 if (v2 != NULL && v2->obj == ERROR_OBJ) {
859 err_msg_output((const Error *)v2);
860 return;
861 }
862
863 more = new_error_msg_err(err);
864 err_msg_invalid_oper2(err->u.invoper.op, v1, v2);
865 if (more) new_error_msg_err_more(err);
866 }
867
err_msg_still_none2(const Error * err)868 static bool err_msg_still_none2(const Error *err) {
869 struct errorentry_s *e;
870 bool more;
871 if ((constcreated || !fixeddig) && pass < max_pass) return false;
872 more = new_error_msg_err(err);
873 e = (struct errorentry_s *)&error_list.data[error_list.header_pos];
874 e->severity = SV_NONEERROR;
875 adderror("can't calculate this");
876 return more;
877 }
878
err_msg_argnum2(argcount_t num,argcount_t min,argcount_t max)879 static void err_msg_argnum2(argcount_t num, argcount_t min, argcount_t max) {
880 argcount_t n;
881 char line[1024];
882 adderror("expected ");
883 n = min;
884 if (min == max) { if (min != 0) adderror("exactly "); }
885 else if (num < min) adderror("at least ");
886 else {n = max; adderror("at most "); }
887 switch (n) {
888 case 0: adderror("no arguments"); break;
889 case 1: adderror("one argument"); break;
890 default: sprintf(line, "%" PRIuargcount " arguments", n); adderror(line); break;
891 }
892 if (num != 0) {
893 sprintf(line, ", got %" PRIuargcount, num);
894 adderror(line);
895 }
896 }
897
err_msg_output(const Error * val)898 void err_msg_output(const Error *val) {
899 bool more = false;
900 switch (val->num) {
901 case ERROR___NOT_DEFINED: err_msg_not_defined3(val);break;
902 case ERROR__INVALID_CONV: more = err_msg_invalid_conv(val);break;
903 case ERROR__INVALID_OPER: err_msg_invalid_oper3(val);break;
904 case ERROR____STILL_NONE: more = err_msg_still_none2(val); break;
905 case ERROR_____CANT_IVAL:
906 case ERROR_____CANT_UVAL:
907 case ERROR______NOT_UVAL: more = err_msg_big_integer(val); break;
908 case ERROR_REQUIREMENTS_:
909 case ERROR______CONFLICT:
910 case ERROR_NOT_TWO_CHARS:
911 case ERROR_NUMERIC_OVERF:
912 case ERROR_NEGFRAC_POWER:
913 case ERROR___EMPTY_RANGE:
914 case ERROR__EMPTY_STRING:
915 case ERROR____EMPTY_LIST:
916 case ERROR__BYTES_NEEDED:
917 case ERROR___NO_LAST_GAP:
918 case ERROR__NOT_ONE_CHAR:
919 case ERROR_NO_ZERO_VALUE:
920 case ERROR_OUT_OF_MEMORY:
921 case ERROR__ADDR_COMPLEX:
922 case ERROR_NEGATIVE_SIZE: more = new_error_msg_err(val); adderror(terr_error[val->num - 0x40]); break;
923 case ERROR_NO_ADDRESSING: more = new_error_msg_err(val); err_msg_no_addressing(val->u.addressing.am, val->u.addressing.cod);break;
924 case ERROR___NO_REGISTER: more = err_msg_no_register(val);break;
925 case ERROR___NO_LOT_OPER: more = err_msg_no_lot_operand(val);break;
926 case ERROR_CANT_BROADCAS: more = err_msg_cant_broadcast(val);break;
927 case ERROR__NO_BYTE_ADDR:
928 case ERROR__NO_WORD_ADDR:
929 case ERROR__NO_LONG_ADDR: more = new_error_msg_err(val); adderror(terr_error[val->num - 0x40]); err_opcode(val->u.addresssize.cod); break;
930 case ERROR_DIVISION_BY_Z:
931 case ERROR_ZERO_NEGPOWER:
932 case ERROR__NOT_KEYVALUE:
933 case ERROR__NOT_HASHABLE:
934 case ERROR_____CANT_SIGN:
935 case ERROR______CANT_ABS:
936 case ERROR______CANT_INT:
937 case ERROR______CANT_LEN:
938 case ERROR_____CANT_SIZE:
939 case ERROR_____CANT_BOOL:
940 case ERROR______NOT_ITER:
941 case ERROR___MATH_DOMAIN:
942 case ERROR_LOG_NON_POSIT:
943 case ERROR_SQUARE_ROOT_N:
944 case ERROR___INDEX_RANGE:
945 case ERROR_____KEY_ERROR: more = new_error_msg_err(val); adderror(terr_error[val->num - 0x40]); err_msg_variable(val->u.obj);break;
946 case ERROR__WRONG_ARGNUM: more = new_error_msg_err(val); err_msg_argnum2(val->u.argnum.num, val->u.argnum.min, val->u.argnum.max); break;
947 default: break;
948 }
949 if (more) new_error_msg_err_more(val);
950 }
951
err_msg_output_and_destroy(Error * val)952 void err_msg_output_and_destroy(Error *val) {
953 err_msg_output(val);
954 val_destroy(Obj(val));
955 }
956
err_msg_wrong_type(const Obj * val,Type * expected,linepos_t epoint)957 void err_msg_wrong_type(const Obj *val, Type *expected, linepos_t epoint) {
958 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
959 adderror("wrong type '");
960 adderror(val->obj->name);
961 if (expected != NULL) {
962 adderror("', expected '");
963 adderror(expected->name);
964 }
965 adderror("'");
966 if (more) new_error_msg_more();
967 }
968
err_msg_wrong_type2(const Obj * val,Type * expected,linepos_t epoint)969 void err_msg_wrong_type2(const Obj *val, Type *expected, linepos_t epoint) {
970 if (val->obj == ADDRESS_OBJ) {
971 const Obj *val2 = Address(val)->val;
972 if (val2 == none_value || val2->obj == ERROR_OBJ) val = val2;
973 }
974 if (val->obj == ERROR_OBJ) err_msg_output(Error(val));
975 else if (val == none_value) err_msg_still_none(NULL, epoint);
976 else err_msg_wrong_type(val, expected, epoint);
977 }
978
err_msg_cant_unpack(size_t expect,size_t got,linepos_t epoint)979 void err_msg_cant_unpack(size_t expect, size_t got, linepos_t epoint) {
980 char line[1024];
981 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
982 sprintf(line, "expected %" PRIuSIZE " values but got %" PRIuSIZE " to unpack", expect, got);
983 adderror(line);
984 if (more) new_error_msg_more();
985 }
986
err_msg_cant_calculate(const str_t * name,linepos_t epoint)987 void err_msg_cant_calculate(const str_t *name, linepos_t epoint) {
988 err_msg_str_name("can't calculate stable value", name, epoint);
989 }
990
err_msg_cant_calculate2(const str_t * name,const struct file_list_s * flist,linepos_t epoint)991 void err_msg_cant_calculate2(const str_t *name, const struct file_list_s *flist, linepos_t epoint) {
992 bool more = new_error_msg(SV_ERROR, flist, epoint);
993 adderror("can't calculate stable value");
994 str_name(name->data, name->len);
995 if (more) new_error_msg_more();
996 }
997
err_msg_still_none(const str_t * name,linepos_t epoint)998 void err_msg_still_none(const str_t *name, linepos_t epoint) {
999 if ((constcreated || !fixeddig) && pass < max_pass) return;
1000 new_error_msg(SV_NONEERROR, current_file_list, epoint);
1001 adderror("can't calculate this");
1002 if (name != NULL) str_name(name->data, name->len);
1003 }
1004
err_msg_not_defined(const str_t * name,linepos_t epoint)1005 void err_msg_not_defined(const str_t *name, linepos_t epoint) {
1006 err_msg_str_name("not defined", name, epoint);
1007 }
1008
err_msg_unknown_formatchar(const Str * s,size_t offs,linepos_t epoint)1009 unsigned int err_msg_unknown_formatchar(const Str *s, size_t offs, linepos_t epoint) {
1010 struct linepos_s epoint2 = *epoint;
1011 unsigned int len;
1012 bool more;
1013 epoint2.pos = interstring_position(&epoint2, s->data, offs);
1014 len = offs < s->len ? utf8len(s->data[offs]) : 0;
1015 more = new_error_msg(SV_ERROR, current_file_list, &epoint2);
1016 if (len == 0) {
1017 adderror("format character expected");
1018 } else {
1019 adderror("unknown format character '");
1020 adderror2(s->data + offs, len);
1021 adderror("'");
1022 }
1023 if (more) new_error_msg_more();
1024 return len;
1025 }
1026
err_msg_double_note(const struct file_list_s * cflist,linepos_t epoint,const str_t * labelname2)1027 static void err_msg_double_note(const struct file_list_s *cflist, linepos_t epoint, const str_t *labelname2) {
1028 new_error_msg(SV_NOTE, cflist, epoint);
1029 adderror("original definition of");
1030 str_name(labelname2->data, labelname2->len);
1031 adderror(" was here");
1032 }
1033
err_msg_star_assign(linepos_t epoint)1034 void err_msg_star_assign(linepos_t epoint) {
1035 new_error_msg2(diagnostic_errors.star_assign, epoint);
1036 adderror("label defined instead of variable multiplication for compatibility [-Wstar-assign]");
1037 }
1038
err_msg_compound_note(linepos_t epoint)1039 void err_msg_compound_note(linepos_t epoint) {
1040 static unsigned once;
1041 if (once != pass) {
1042 new_error_msg(SV_NOTE, current_file_list, epoint);
1043 adderror("for reserving space use '.fill x' or '.byte ?' [-Wpitfalls]");
1044 once = pass;
1045 }
1046 }
1047
err_msg_byte_note(linepos_t epoint)1048 void err_msg_byte_note(linepos_t epoint) {
1049 static unsigned int once;
1050 if (once != pass) {
1051 new_error_msg(SV_NOTE, current_file_list, epoint);
1052 adderror("for long strings mixed with bytes please use the '.text' directive [-Wpitfalls]");
1053 once = pass;
1054 }
1055 }
1056
err_msg_char_note(const char * directive,linepos_t epoint)1057 void err_msg_char_note(const char *directive, linepos_t epoint) {
1058 new_error_msg(SV_NOTE, current_file_list, epoint);
1059 adderror("for signed values '");
1060 adderror(directive);
1061 adderror("' is a better fit [-Wpitfalls]");
1062 }
1063
err_msg_immediate_note(linepos_t epoint)1064 void err_msg_immediate_note(linepos_t epoint) {
1065 new_error_msg(SV_NOTE, current_file_list, epoint);
1066 adderror("to accept signed values use the '#+' operator [-Wpitfalls]");
1067 }
1068
err_msg_symbol_case(const str_t * labelname1,const Label * l,linepos_t epoint)1069 void err_msg_symbol_case(const str_t *labelname1, const Label *l, linepos_t epoint) {
1070 new_error_msg2(diagnostic_errors.case_symbol, epoint);
1071 adderror("symbol case mismatch");
1072 str_name(labelname1->data, labelname1->len);
1073 adderror(" [-Wcase-symbol]");
1074 if (l != NULL) err_msg_double_note(l->file_list, &l->epoint, &l->name);
1075 }
1076
err_msg_symbol_case2(const Symbol * l1,const Symbol * l2)1077 void err_msg_symbol_case2(const Symbol *l1, const Symbol *l2) {
1078 Severity_types severity = diagnostic_errors.case_symbol ? SV_ERROR : SV_WARNING;
1079 bool more = new_error_msg(severity, l1->file_list, &l1->epoint);
1080 adderror("symbol case mismatch");
1081 str_name(l1->name.data, l1->name.len);
1082 adderror(" [-Wcase-symbol]");
1083 if (more) new_error_msg_more();
1084 err_msg_double_note(l2->file_list, &l2->epoint, &l2->name);
1085 }
1086
err_msg_macro_prefix(linepos_t epoint)1087 void err_msg_macro_prefix(linepos_t epoint) {
1088 new_error_msg2(diagnostic_errors.macro_prefix, epoint);
1089 adderror("macro call without prefix [-Wmacro-prefix]");
1090 }
1091
1092 static const char * const opr_names[ADR_LEN] = {
1093 "", /* ADR_REG */
1094 "", /* ADR_IMPLIED */
1095 "", /* ADR_IMMEDIATE */
1096 "long", /* ADR_LONG */
1097 "data bank", /* ADR_ADDR */
1098 "direct page", /* ADR_ZP */
1099 "long x indexed", /* ADR_LONG_X */
1100 "data bank x indexed", /* ADR_ADDR_X */
1101 "direct page x indexed", /* ADR_ZP_X */
1102 "", /* ADR_ADDR_X_I */
1103 "", /* ADR_ZP_X_I */
1104 "", /* ADR_ZP_S */
1105 "long y indexed", /* ADR_ZP_S_I_Y */
1106 "data bank y indexed", /* ADR_ADDR_Y */
1107 "direct page y indexed", /* ADR_ZP_Y */
1108 "", /* ADR_ZP_LI_Y */
1109 "", /* ADR_ZP_I_Y */
1110 "", /* ADR_ADDR_LI */
1111 "", /* ADR_ZP_LI */
1112 "", /* ADR_ADDR_I */
1113 "", /* ADR_ZP_I */
1114 "", /* ADR_REL_L */
1115 "", /* ADR_REL */
1116 "", /* ADR_MOVE */
1117 "", /* ADR_ZP_R */
1118 "", /* ADR_ZP_R_I_Y */
1119 "", /* ADR_BIT_ZP */
1120 "", /* ADR_BIT_ZP_REL */
1121 };
1122
err_msg_address_mismatch(unsigned int a,unsigned int b,linepos_t epoint)1123 void err_msg_address_mismatch(unsigned int a, unsigned int b, linepos_t epoint) {
1124 new_error_msg2(diagnostic_errors.altmode, epoint);
1125 adderror("using ");
1126 adderror(opr_names[a]);
1127 adderror(" addressing instead of ");
1128 adderror(opr_names[b]);
1129 adderror(" [-Waltmode]");
1130 }
1131
err_msg_double_defined2(const char * msg,Severity_types severity,const struct file_list_s * cflist,const str_t * labelname2,linepos_t epoint2)1132 static void err_msg_double_defined2(const char *msg, Severity_types severity, const struct file_list_s *cflist, const str_t *labelname2, linepos_t epoint2) {
1133 bool more = new_error_msg(severity, cflist, epoint2);
1134 adderror(msg);
1135 str_name(labelname2->data, labelname2->len);
1136 if (more) new_error_msg_more();
1137 }
1138
err_msg_not_variable(Label * l,const str_t * labelname2,linepos_t epoint2)1139 void err_msg_not_variable(Label *l, const str_t *labelname2, linepos_t epoint2) {
1140 err_msg_double_defined2("not a variable", SV_ERROR, current_file_list, labelname2, epoint2);
1141 err_msg_double_note(l->file_list, &l->epoint, labelname2);
1142 }
1143
err_msg_double_defined(Label * l,const str_t * labelname2,linepos_t epoint2)1144 void err_msg_double_defined(Label *l, const str_t *labelname2, linepos_t epoint2) {
1145 err_msg_double_defined2("duplicate definition", SV_ERROR, current_file_list, labelname2, epoint2);
1146 err_msg_double_note(l->file_list, &l->epoint, labelname2);
1147 }
1148
err_msg_double_definedo(const struct file_list_s * cflist,linepos_t epoint,const str_t * labelname2,linepos_t epoint2)1149 void err_msg_double_definedo(const struct file_list_s *cflist, linepos_t epoint, const str_t *labelname2, linepos_t epoint2) {
1150 err_msg_double_defined2("duplicate definition", SV_ERROR, current_file_list, labelname2, epoint2);
1151 err_msg_double_note(cflist, epoint, labelname2);
1152 }
1153
err_msg_shadow_defined(Label * l,Label * l2)1154 void err_msg_shadow_defined(Label *l, Label *l2) {
1155 err_msg_double_defined2("shadow definition", diagnostic_errors.shadow ? SV_ERROR : SV_WARNING, l2->file_list, &l2->name, &l2->epoint);
1156 adderror(" [-Wshadow]");
1157 err_msg_double_note(l->file_list, &l->epoint, &l2->name);
1158 }
1159
err_msg_shadow_defined2(Label * l)1160 void err_msg_shadow_defined2(Label *l) {
1161 err_msg_double_defined2("shadow definition of built-in", diagnostic_errors.shadow ? SV_ERROR : SV_WARNING, l->file_list, &l->name, &l->epoint);
1162 adderror(" [-Wshadow]");
1163 }
1164
1165 static const char * const order_suffix[4] = {
1166 "st", "nd", "rd", "th"
1167 };
1168
err_msg_missing_argument(linepos_t epoint,argcount_t n)1169 void err_msg_missing_argument(linepos_t epoint, argcount_t n) {
1170 char msg2[4];
1171 bool more = new_error_msg(SV_ERROR, &((const struct file_listnode_s *)current_file_list)->parent->flist, ¤t_file_list->epoint);
1172 msg2[0] = (char)(n + '1');
1173 memcpy(msg2 + 1, order_suffix[n < 4 ? n : 3], 3);
1174 adderror(msg2);
1175 adderror(" argument is missing");
1176 if (more) new_error_msg_more();
1177 new_error_msg(SV_NOTE, current_file_list, epoint);
1178 adderror("argument reference was here");
1179 }
1180
err_msg_unknown_argument(const str_t * labelname,linepos_t epoint)1181 void err_msg_unknown_argument(const str_t *labelname, linepos_t epoint) {
1182 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
1183 adderror("unknown argument name");
1184 str_name(labelname->data, labelname->len);
1185 if (more) new_error_msg_more();
1186 }
1187
err_msg_unused(const char * msg,bool error,Label * l)1188 static void err_msg_unused(const char *msg, bool error, Label *l) {
1189 Severity_types severity = error ? SV_ERROR : SV_WARNING;
1190 bool more = new_error_msg(severity, l->file_list, &l->epoint);
1191 adderror(msg);
1192 str_name(l->name.data, l->name.len);
1193 if (more) new_error_msg_more();
1194 }
1195
err_msg_unused_macro(Label * l)1196 void err_msg_unused_macro(Label *l) {
1197 err_msg_unused("unused macro", diagnostic_errors.unused.macro, l);
1198 adderror(" [-Wunused-macro]");
1199 }
1200
err_msg_unused_label(Label * l)1201 void err_msg_unused_label(Label *l) {
1202 err_msg_unused("unused label", diagnostic_errors.unused.label, l);
1203 adderror(" [-Wunused-label]");
1204 }
1205
err_msg_unused_const(Label * l)1206 void err_msg_unused_const(Label *l) {
1207 err_msg_unused("unused const", diagnostic_errors.unused.consts, l);
1208 adderror(" [-Wunused-const]");
1209 }
1210
err_msg_unused_variable(Label * l)1211 void err_msg_unused_variable(Label *l) {
1212 err_msg_unused("unused variable", diagnostic_errors.unused.variable, l);
1213 adderror(" [-Wunused-variable]");
1214 }
1215
err_msg_argnum(argcount_t num,argcount_t min,argcount_t max,linepos_t epoint)1216 void err_msg_argnum(argcount_t num, argcount_t min, argcount_t max, linepos_t epoint) {
1217 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
1218 err_msg_argnum2(num, min, max);
1219 if (more) new_error_msg_more();
1220 }
1221
err_msg_bool(Error_types no,Obj * o,linepos_t epoint)1222 void err_msg_bool(Error_types no, Obj *o, linepos_t epoint) {
1223 new_error_msg2(diagnostic_errors.strict_bool, epoint);
1224 adderror(terr_error[no - 0x40]);
1225 err_msg_variable(o);
1226 adderror(" [-Wstrict-bool]");
1227 }
1228
err_msg_bool_oper(oper_t op)1229 void err_msg_bool_oper(oper_t op) {
1230 Obj *v2;
1231 new_error_msg2(diagnostic_errors.strict_bool, op->epoint3);
1232 switch (op->op) {
1233 case O_WORD:
1234 case O_HWORD:
1235 case O_BSWORD:
1236 case O_LOWER:
1237 case O_HIGHER:
1238 case O_BANK:
1239 case O_STRING:
1240 case O_INV:
1241 case O_NEG:
1242 case O_POS:
1243 case O_LNOT:
1244 case O_X:
1245 case O_FUNC:
1246 case O_INDEX: v2 = NULL; break;
1247 default: v2 = op->v2; break;
1248 }
1249 err_msg_invalid_oper2(op->op, op->v1, v2);
1250 adderror(" [-Wstrict-bool]");
1251 }
1252
err_msg_implied_reg(linepos_t epoint,uint32_t cod)1253 void err_msg_implied_reg(linepos_t epoint, uint32_t cod) {
1254 Severity_types severity = diagnostic_errors.implied_reg ? SV_ERROR : SV_WARNING;
1255 bool more = new_error_msg(severity, current_file_list, epoint);
1256 err_msg_no_addressing(A_NONE, cod);
1257 adderror(" [-Wimplied-reg]");
1258 if (more) new_error_msg_more();
1259 }
1260
err_msg_size_larger(linepos_t epoint)1261 void err_msg_size_larger(linepos_t epoint) {
1262 new_error_msg2(diagnostic_errors.size_larger, epoint);
1263 adderror("larger than original due to negative offset [-Wsize-larger]");
1264 }
1265
err_msg_jmp_bug(linepos_t epoint)1266 void err_msg_jmp_bug(linepos_t epoint) {
1267 new_error_msg2(diagnostic_errors.jmp_bug, epoint);
1268 adderror("possible jmp ($xxff) bug [-Wjmp-bug]");
1269 }
1270
err_msg_pc_bank(linepos_t epoint)1271 void err_msg_pc_bank(linepos_t epoint) {
1272 if (!diagnostics.wrap.pc) return;
1273 new_error_msg2(diagnostic_errors.wrap.pc, epoint);
1274 adderror("processor program counter crossed bank [-Wwrap-pc]");
1275 }
1276
err_msg_mem_wrap(linepos_t epoint)1277 void err_msg_mem_wrap(linepos_t epoint) {
1278 if (!diagnostics.wrap.mem) return;
1279 new_error_msg2(diagnostic_errors.wrap.mem, epoint);
1280 adderror("compile offset overflow [-Wwrap-mem]");
1281 }
1282
err_msg_addr_wrap(linepos_t epoint)1283 void err_msg_addr_wrap(linepos_t epoint) {
1284 if (!diagnostics.wrap.addr) return;
1285 new_error_msg2(diagnostic_errors.wrap.addr, epoint);
1286 adderror("memory location address overflow [-Wwrap-addr]");
1287 }
1288
err_msg_dpage_wrap(linepos_t epoint)1289 void err_msg_dpage_wrap(linepos_t epoint) {
1290 if (!diagnostics.wrap.dpage) return;
1291 new_error_msg2(diagnostic_errors.wrap.dpage, epoint);
1292 adderror("direct page address overflow [-Wwrap-dpage]");
1293 }
1294
err_msg_bank0_wrap(linepos_t epoint)1295 void err_msg_bank0_wrap(linepos_t epoint) {
1296 if (!diagnostics.wrap.bank0) return;
1297 new_error_msg2(diagnostic_errors.wrap.bank0, epoint);
1298 adderror("bank 0 address overflow [-Wwrap-bank0]");
1299 }
1300
err_msg_pbank_wrap(linepos_t epoint)1301 void err_msg_pbank_wrap(linepos_t epoint) {
1302 if (!diagnostics.wrap.pbank) return;
1303 new_error_msg2(diagnostic_errors.wrap.pbank, epoint);
1304 adderror("program bank address overflow [-Wwrap-pbank]");
1305 }
1306
err_msg_label_left(linepos_t epoint)1307 void err_msg_label_left(linepos_t epoint) {
1308 new_error_msg2(diagnostic_errors.label_left, epoint);
1309 adderror("label not on left side [-Wlabel-left]");
1310 }
1311
err_msg_branch_page(int by,linepos_t epoint)1312 void err_msg_branch_page(int by, linepos_t epoint) {
1313 char msg2[256];
1314 new_error_msg2(diagnostic_errors.branch_page, epoint);
1315 sprintf(msg2, "branch crosses page by %+d bytes [-Wbranch-page]", by);
1316 adderror(msg2);
1317 }
1318
err_msg_page(address_t adr,address_t adr2,linepos_t epoint)1319 void err_msg_page(address_t adr, address_t adr2, linepos_t epoint) {
1320 char line[256];
1321 new_error_msg2(diagnostic_errors.page, epoint);
1322 sprintf(line,"different start and end page $%04" PRIaddress " and $%04" PRIaddress " [-Wpage]", adr, adr2);
1323 adderror(line);
1324 }
1325
err_msg_alias(uint32_t a,uint32_t b,linepos_t epoint)1326 void err_msg_alias(uint32_t a, uint32_t b, linepos_t epoint) {
1327 char name[4];
1328 new_error_msg2(diagnostic_errors.alias, epoint);
1329 adderror("instruction '");
1330 name[0] = (char)(a >> 16);
1331 name[1] = (char)(a >> 8);
1332 name[2] = (char)a;
1333 name[3] = '\0';
1334 adderror(name);
1335 adderror("' is alias of '");
1336 name[0] = (char)(b >> 16);
1337 name[1] = (char)(b >> 8);
1338 name[2] = (char)b;
1339 adderror(name);
1340 adderror("' [-Walias]");
1341 }
1342
err_msg_unknown_char(uchar_t ch,const str_t * name,linepos_t epoint)1343 void err_msg_unknown_char(uchar_t ch, const str_t *name, linepos_t epoint) {
1344 uint8_t line[256], *s = line;
1345 bool more = new_error_msg(SV_ERROR, current_file_list, epoint);
1346 adderror("can't encode character '");
1347 if (ch != 0 && ch < 0x80) *s++ = (uint8_t)ch; else s += utf8out(ch, s);
1348 sprintf((char *)s, "' ($%02" PRIx32 ") in encoding '", ch); adderror((char *)line);
1349 adderror2(name->data, name->len);
1350 adderror("'");
1351 if (more) new_error_msg_more();
1352 }
1353
printline(const struct file_list_s * cfile,linepos_t epoint,const uint8_t * line,FILE * f)1354 static const uint8_t *printline(const struct file_list_s *cfile, linepos_t epoint, const uint8_t *line, FILE *f) {
1355 const struct file_s *file;
1356 if (epoint->line == 0) return NULL;
1357 file = cfile->file;
1358 if (line == NULL) line = &file->data[file->line[epoint->line - 1]];
1359 fprintf(f, ":%" PRIuline ":%" PRIlinepos, epoint->line, ((file->encoding == E_UTF8) ? (linecpos_t)calcpos(line, epoint->pos) : epoint->pos) + 1);
1360 return line;
1361 }
1362
print_error(FILE * f,const struct errorentry_s * err,bool caret)1363 static void print_error(FILE *f, const struct errorentry_s *err, bool caret) {
1364 const struct file_list_s *cflist = err->file_list;
1365 linepos_t epoint = &err->epoint;
1366 const uint8_t *line = NULL;
1367 bool bold;
1368
1369 if (cflist != &file_list.flist) {
1370 if (cflist != &included_from->flist) {
1371 included_from = (const struct file_listnode_s *)cflist;
1372 while (included_from->parent != &file_list) {
1373 if (included_from->flist.file->entercount != 1) break;
1374 included_from = included_from->parent;
1375 }
1376 if (included_from->parent != &file_list) included_from = (const struct file_listnode_s *)cflist;
1377 while (included_from->parent != &file_list) {
1378 fputs((&included_from->flist == cflist) ? "In file included from " : " ", f);
1379 if (console_use_color) console_bold(f);
1380 printable_print((const uint8_t *)included_from->parent->flist.file->realname, f);
1381 printline(&included_from->parent->flist, &included_from->flist.epoint, NULL, f);
1382 included_from = included_from->parent;
1383 if (console_use_color) console_default(f);
1384 fputs((included_from->parent != &file_list) ? ",\n" : ":\n", f);
1385 }
1386 included_from = (const struct file_listnode_s *)cflist;
1387 }
1388 if (console_use_color) console_bold(f);
1389 printable_print((const uint8_t *)cflist->file->realname, f);
1390 line = printline(cflist, epoint, (err->line_len != 0) ? (const uint8_t *)(err + 1) : NULL, f);
1391 } else {
1392 if (console_use_color) console_bold(f);
1393 printable_print((const uint8_t *)prgname, f);
1394 }
1395 fputs(": ", f);
1396 switch (err->severity) {
1397 case SV_NOTE: if (console_use_color) console_cyan(f); fputs("note: ", f); bold = false; break;
1398 case SV_WARNING: if (console_use_color) console_purple(f); fputs("warning: ", f); bold = true; break;
1399 case SV_NONEERROR:
1400 case SV_ERROR: if (console_use_color) console_red(f); fputs("error: ", f); bold = true; break;
1401 case SV_FATAL: if (console_use_color) console_red(f); fputs("fatal error: ", f); bold = true; break;
1402 default: bold = false;
1403 }
1404 if (console_use_color) {
1405 if (bold) {
1406 console_defaultbold(f);
1407 #ifdef COLOR_OUTPUT
1408 console_use_bold = true;
1409 #endif
1410 } else console_default(f);
1411 }
1412 printable_print2(((const uint8_t *)(err + 1)) + err->line_len, f, err->error_len);
1413 #ifdef COLOR_OUTPUT
1414 if (console_use_bold) {
1415 console_default(f);
1416 console_use_bold = false;
1417 }
1418 #endif
1419 putc('\n', f);
1420 if (caret && line != NULL) {
1421 putc(' ', f);
1422 printable_print(line, f);
1423 fputs("\n ", f);
1424 caret_print(line, f, err->caret);
1425 if (console_use_color) console_boldgreen(f);
1426 putc('^', f);
1427 if (console_use_color) console_default(f);
1428 putc('\n', f);
1429 }
1430 }
1431
caret_needed(const struct errorentry_s * err)1432 static inline bool caret_needed(const struct errorentry_s *err) {
1433 return (arguments.error.caret == CARET_ALWAYS || (arguments.error.caret != CARET_NEVER && (err->line_len != 0 || err->file_list->file->name[0] == 0)));
1434 }
1435
different_line(const struct errorentry_s * err,const struct errorentry_s * err2)1436 static bool different_line(const struct errorentry_s *err, const struct errorentry_s *err2) {
1437 if (!caret_needed(err2)) return false;
1438 if (err->file_list->file != err2->file_list->file || err->line_len != err2->line_len ||
1439 err->epoint.line != err2->epoint.line || err->epoint.pos != err2->epoint.pos) return true;
1440 if (err->line_len == 0) return false;
1441 return memcmp(err + 1, err2 + 1, err->line_len) != 0;
1442 }
1443
walkfilelist(struct avltree_node * aa)1444 static void walkfilelist(struct avltree_node *aa) {
1445 struct file_listnode_s *l = avltree_container_of(aa, struct file_listnode_s, node);
1446 if (l->flist.file->entercount > 1 || l->pass != pass) return;
1447 l->flist.file->entercount++;
1448 avltree_destroy(&l->members, walkfilelist);
1449 }
1450
error_print(const struct error_output_s * output)1451 void error_print(const struct error_output_s *output) {
1452 const struct errorentry_s *err, *err2, *err3;
1453 size_t pos, end;
1454 bool noneerr = false, anyerr = false, usenote;
1455 FILE *ferr;
1456 struct linepos_s nopoint = {0, 0};
1457
1458 if (error_list.header_pos != 0) {
1459 avltree_destroy(&file_list.members, walkfilelist);
1460 }
1461
1462 if (output->name != NULL) {
1463 ferr = dash_name(output->name) ? stdout : file_open(output->name, output->append ? "at" : "wt");
1464 if (ferr == NULL) {
1465 err_msg_file(ERROR_CANT_WRTE_ERR, output->name, &nopoint);
1466 ferr = stderr;
1467 }
1468 } else ferr = output->no_output ? NULL : stderr;
1469
1470 if (ferr != NULL) {
1471 if (ferr != stderr) console_use(ferr); else if (arguments.quiet) fflush(stdout);
1472 }
1473
1474 warnings = errors = 0;
1475 close_error();
1476
1477 end = (error_list.header_stop != SIZE_MAX) ? error_list.header_stop : error_list.header_pos;
1478 for (pos = 0; pos < end; pos = ALIGN(pos + (sizeof *err) + err->line_len + err->error_len)) {
1479 err = (const struct errorentry_s *)&error_list.data[pos];
1480 switch (err->severity) {
1481 case SV_NONEERROR: anyerr = true; break;
1482 case SV_NOTE:
1483 case SV_WARNING:
1484 break;
1485 default: noneerr = true; anyerr = true; break;
1486 }
1487 }
1488
1489 err2 = err3 = NULL;
1490 usenote = false;
1491 for (pos = 0; pos < end; pos = ALIGN(pos + (sizeof *err) + err->line_len + err->error_len)) {
1492 err = (const struct errorentry_s *)&error_list.data[pos];
1493 switch (err->severity) {
1494 case SV_NOTE:
1495 if (!usenote) continue;
1496 if (err3 != NULL && ferr != NULL) {
1497 if (err->severity != err3->severity || err->file_list != err3->file_list ||
1498 err->line_len != err3->line_len || err->error_len != err3->error_len ||
1499 err->epoint.line != err3->epoint.line || err->epoint.pos != err3->epoint.pos ||
1500 memcmp(err + 1, err3 + 1, err->line_len + err->error_len) != 0) {
1501 print_error(ferr, err3, different_line(err, err3));
1502 }
1503 }
1504 err3 = err2;
1505 err2 = err;
1506 continue;
1507 case SV_WARNING:
1508 if (!output->warning) {
1509 usenote = false;
1510 continue;
1511 }
1512 warnings++;
1513 if (anyerr) {
1514 usenote = false;
1515 continue;
1516 }
1517 break;
1518 case SV_NONEERROR:
1519 if (noneerr) {
1520 usenote = false;
1521 continue;
1522 }
1523 /* fall through */
1524 default:
1525 errors++;
1526 break;
1527 }
1528 if (err3 != NULL && ferr != NULL) print_error(ferr, err3, different_line(err2, err3));
1529 err3 = err2;
1530 err2 = err;
1531 usenote = true;
1532 }
1533 if (ferr == NULL) return;
1534 if (err3 != NULL) print_error(ferr, err3, different_line(err2, err3));
1535 if (err2 != NULL) print_error(ferr, err2, caret_needed(err2));
1536 if (ferr != stderr) console_use(stderr);
1537 if (ferr != stderr && ferr != stdout) fclose(ferr); else fflush(ferr);
1538 }
1539
error_reset(void)1540 void error_reset(void) {
1541 error_list.len = error_list.header_pos = 0;
1542 error_list.header_stop = SIZE_MAX;
1543 avltree_init(&error_list.members);
1544 current_file_list = &file_list.flist;
1545 included_from = &file_list;
1546 }
1547
err_init(const char * name)1548 void err_init(const char *name) {
1549 static struct file_s file_list_file;
1550 prgname = name;
1551 setvbuf(stderr, NULL, _IOLBF, 1024);
1552 console_use(stderr);
1553 file_lists = (struct file_lists_s *)mallocx(sizeof *file_lists);
1554 file_lists->next = NULL;
1555 file_listsp = 0;
1556 lastfl = &file_lists->file_lists[file_listsp];
1557 file_list_file.name = "";
1558 file_list_file.realname = file_list_file.name;
1559 file_list_file.data = (uint8_t *)0;
1560 file_list_file.len = ~(filesize_t)0;
1561 file_list.flist.file = &file_list_file;
1562 avltree_init(&file_list.members);
1563 error_list.len = error_list.max = error_list.header_pos = 0;
1564 error_list.data = NULL;
1565 avltree_init(&error_list.members);
1566 current_file_list = &file_list.flist;
1567 dummy_file_list = &file_list.flist;
1568 included_from = &file_list;
1569 avltree_init(¬defines);
1570 }
1571
err_destroy(void)1572 void err_destroy(void) {
1573 while (file_lists != NULL) {
1574 struct file_lists_s *old = file_lists;
1575 file_lists = file_lists->next;
1576 free(old);
1577 }
1578 free(error_list.data);
1579 avltree_destroy(¬defines, notdefines_free);
1580 free(lastnd);
1581 }
1582
fatal_error(const char * txt)1583 void fatal_error(const char *txt) {
1584 if (txt != NULL) {
1585 if (console_use_color) console_bold(stderr);
1586 printable_print((const uint8_t *)((prgname != NULL) ? prgname : "64tass"), stderr);
1587 fputs(": ", stderr);
1588 if (console_use_color) console_red(stderr);
1589 fputs("fatal error: ", stderr);
1590 if (console_use_color) {
1591 console_default(stderr);
1592 console_bold(stderr);
1593 }
1594 fputs(txt, stderr);
1595 return;
1596 }
1597 if (console_use_color) console_default(stderr);
1598 putc('\n', stderr);
1599 }
1600
err_msg_out_of_memory2(void)1601 NO_RETURN void err_msg_out_of_memory2(void)
1602 {
1603 fatal_error("out of memory");
1604 fatal_error(NULL);
1605 exit(EXIT_FAILURE);
1606 }
1607
err_msg_out_of_memory(void)1608 NO_RETURN void err_msg_out_of_memory(void)
1609 {
1610 error_print(&arguments.error);
1611 err_msg_out_of_memory2();
1612 }
1613
err_msg_signal(void)1614 void err_msg_signal(void)
1615 {
1616 if (error_list.header_stop == SIZE_MAX) {
1617 bool more = new_error_msg(SV_FATAL, current_file_list, &lpoint);
1618 adderror("compilation was interrupted");
1619 if (more) new_error_msg_more();
1620 error_list.header_stop = error_list.header_pos + 1;
1621 }
1622 }
1623
err_msg_file(Error_types no,const char * prm,linepos_t epoint)1624 void err_msg_file(Error_types no, const char *prm, linepos_t epoint) {
1625 mbstate_t ps;
1626 const char *s;
1627 wchar_t w;
1628 uint8_t s2[10];
1629 size_t n, i = 0;
1630 ssize_t l;
1631 bool more;
1632
1633 s = strerror(errno);
1634 n = strlen(s);
1635
1636 more = new_error_msg(SV_FATAL, current_file_list, epoint);
1637 adderror(terr_fatal[no - 0xc0]);
1638 adderror(" '");
1639 adderror(prm);
1640 adderror("': ");
1641 memset(&ps, 0, sizeof ps);
1642 while (i < n) {
1643 if (s[i] != 0 && (s[i] & 0x80) == 0) {
1644 adderror2((const uint8_t *)s + i, 1);
1645 i++;
1646 continue;
1647 }
1648 l = (ssize_t)mbrtowc(&w, s + i, n - i, &ps);
1649 if (l < 1) {
1650 w = (uint8_t)s[i];
1651 if (w == 0 || l == 0) break;
1652 l = 1;
1653 }
1654 s2[utf8out((uchar_t)w, s2)] = 0;
1655 adderror((char *)s2);
1656 i += (size_t)l;
1657 }
1658 if (more) new_error_msg_more();
1659 }
1660
error_status_val(const char * head,unsigned int val)1661 static void error_status_val(const char *head, unsigned int val) {
1662 fputs(head, stdout);
1663 if (val != 0) printf("%u\n", val); else puts("None");
1664 }
1665
error_status(void)1666 void error_status(void) {
1667 error_status_val("Error messages: ", errors);
1668 error_status_val("Warning messages: ", warnings);
1669 }
1670
interstring_position(linepos_t epoint,const uint8_t * data,size_t i)1671 linecpos_t interstring_position(linepos_t epoint, const uint8_t *data, size_t i) {
1672 if (epoint->line == lpoint.line && strlen((const char *)pline) > epoint->pos) {
1673 uint8_t q = pline[epoint->pos];
1674 if (q == '"' || q == '\'') {
1675 linecpos_t pos = epoint->pos + 1;
1676 size_t pp = 0;
1677 while (pp < i && pline[pos] != 0) {
1678 unsigned int ln2;
1679 if (pline[pos] == q) {
1680 if (pline[pos + 1] != q) break;
1681 pos++;
1682 }
1683 ln2 = utf8len(pline[pos]);
1684 if (memcmp(pline + pos, data + pp, ln2) != 0) break;
1685 pos += ln2; pp += ln2;
1686 }
1687 if (pp == i) {
1688 return pos;
1689 }
1690 }
1691 }
1692 return epoint->pos;
1693 }
1694
error_serious(void)1695 bool error_serious(void) {
1696 const struct errorentry_s *err;
1697 size_t pos;
1698 close_error();
1699 for (pos = 0; pos < error_list.header_pos; pos = ALIGN(pos + (sizeof *err) + err->line_len + err->error_len)) {
1700 err = (const struct errorentry_s *)&error_list.data[pos];
1701 switch (err->severity) {
1702 case SV_NOTE:
1703 case SV_WARNING: break;
1704 default: return true;
1705 }
1706 }
1707 return false;
1708 }
1709