1 /***********************************************************************
2 *
3 * AVRA - Assembler for the Atmel AVR microcontroller series
4 *
5 * Copyright (C) 1998-2020 The AVRA Authors
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 *
22 *
23 * Authors of AVRA can be reached at:
24 * email: jonah@omegav.ntnu.no, tobiw@suprafluid.com
25 * www: https://github.com/Ro5bert/avra
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "misc.h"
34 #include "args.h"
35 #include "avra.h"
36 #include "device.h"
37
38 enum {
39 DIRECTIVE_BYTE = 0,
40 DIRECTIVE_CSEG,
41 DIRECTIVE_CSEGSIZE,
42 DIRECTIVE_DB,
43 DIRECTIVE_DEF,
44 DIRECTIVE_DEVICE,
45 DIRECTIVE_DSEG,
46 DIRECTIVE_DW,
47 DIRECTIVE_ENDM,
48 DIRECTIVE_ENDMACRO,
49 DIRECTIVE_EQU,
50 DIRECTIVE_ESEG,
51 DIRECTIVE_EXIT,
52 DIRECTIVE_INCLUDE,
53 DIRECTIVE_INCLUDEPATH,
54 DIRECTIVE_LIST,
55 DIRECTIVE_LISTMAC,
56 DIRECTIVE_MACRO,
57 DIRECTIVE_NOLIST,
58 DIRECTIVE_ORG,
59 DIRECTIVE_SET,
60 DIRECTIVE_DEFINE,
61 DIRECTIVE_UNDEF,
62 DIRECTIVE_IFDEF,
63 DIRECTIVE_IFNDEF,
64 DIRECTIVE_IF,
65 DIRECTIVE_ELSE,
66 DIRECTIVE_ELSEIF, /* The Atmel AVR Assembler version 1.71 and later use ELSEIF and not ELIF */
67 DIRECTIVE_ELIF,
68 DIRECTIVE_ENDIF,
69 DIRECTIVE_MESSAGE,
70 DIRECTIVE_WARNING,
71 DIRECTIVE_ERROR,
72 DIRECTIVE_PRAGMA,
73 DIRECTIVE_OVERLAP,
74 DIRECTIVE_NOOVERLAP,
75 DIRECTIVE_COUNT
76 };
77
78 static const char *const directive_list[] = {
79 "BYTE",
80 "CSEG",
81 "CSEGSIZE",
82 "DB",
83 "DEF",
84 "DEVICE",
85 "DSEG",
86 "DW",
87 "ENDM",
88 "ENDMACRO",
89 "EQU",
90 "ESEG",
91 "EXIT",
92 "INCLUDE",
93 "INCLUDEPATH",
94 "LIST",
95 "LISTMAC",
96 "MACRO",
97 "NOLIST",
98 "ORG",
99 "SET",
100 "DEFINE",
101 "UNDEF",
102 "IFDEF",
103 "IFNDEF",
104 "IF",
105 "ELSE",
106 "ELSEIF", /* The Atmel AVR Assembler version 1.71 and later use ELSEIF and not ELIF */
107 "ELIF",
108 "ENDIF",
109 "MESSAGE",
110 "WARNING",
111 "ERROR",
112 "PRAGMA",
113 "OVERLAP",
114 "NOOVERLAP",
115 NULL
116 };
117
118 enum {
119 PRAGMA_OVERLAP,
120 PRAGMA_COUNT
121 };
122
123 static const char *const pragma_list[] = {
124 "OVERLAP",
125 NULL
126 };
127
128 static const char *const overlap_value[] = {
129 "DEFAULT",
130 "IGNORE",
131 "WARNING",
132 "ERROR",
133 NULL
134 };
135
136 /* caller has to free result */
137 static char *
joinpaths(const char * dirname,const char * fname)138 joinpaths(const char *dirname, const char *fname)
139 {
140 char *res;
141 int len;
142
143 len = strlen(dirname);
144 res = malloc(len + strlen(fname) + 2);
145 if (!res) {
146 return NULL;
147 }
148 strcpy(res, dirname);
149 if ((res[len - 1] != '\\') && (res[len - 1] != '/'))
150 res[len++] = '/';
151 strcpy(&res[len], fname);
152 return res;
153 }
154
155 int
parse_directive(struct prog_info * pi)156 parse_directive(struct prog_info *pi)
157 {
158 int directive, pragma;
159 int ok = True;
160 int i;
161 char *next, *data, buf[140];
162 struct file_info *fi_bak;
163
164 struct def *def;
165 struct data_list *incpath, *dl;
166
167 next = get_next_token(pi->fi->scratch, TERM_SPACE);
168
169 my_strupr(pi->fi->scratch);
170 directive = lookup_keyword(directive_list, pi->fi->scratch + 1, True);
171 if (directive == -1) {
172 print_msg(pi, MSGTYPE_ERROR, "Unknown directive: %s", pi->fi->scratch);
173 return (True);
174 }
175 switch (directive) {
176 case DIRECTIVE_BYTE:
177 if (!next) {
178 print_msg(pi, MSGTYPE_ERROR, ".BYTE needs a size operand");
179 return (True);
180 }
181 if (pi->segment == pi->cseg) {
182 print_msg(pi, MSGTYPE_ERROR, ".BYTE directive cannot be used within the code segment (.CSEG)");
183 return False;
184 }
185 get_next_token(next, TERM_END);
186 if (!get_expr(pi, next, &i))
187 return (False);
188 if (i < 0) {
189 print_msg(pi, MSGTYPE_ERROR, ".BYTE directive must have nonnegative operand");
190 return False;
191 }
192 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
193 fprintf(pi->list_file, "%c:%06lx %s\n",
194 pi->segment->ident, pi->segment->addr, pi->list_line);
195 pi->list_line = NULL;
196 }
197 advance_ip(pi->segment, i);
198 break;
199 case DIRECTIVE_CSEG:
200 fix_orglist(pi->segment);
201 def_orglist(pi->cseg);
202 break;
203 case DIRECTIVE_CSEGSIZE:
204 break;
205 case DIRECTIVE_DB:
206 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
207 fprintf(pi->list_file, " %s\n", pi->list_line);
208 pi->list_line = NULL;
209 }
210 return (parse_db(pi, next));
211 /* Directive .def */
212 case DIRECTIVE_DEF:
213 if (!next) {
214 print_msg(pi, MSGTYPE_ERROR, ".DEF needs an operand");
215 return (True);
216 }
217 data = get_next_token(next, TERM_EQUAL);
218 if (!(data && (tolower(data[0]) == 'r') && isdigit(data[1]))) {
219 print_msg(pi, MSGTYPE_ERROR, "%s needs a register (e.g. .def BZZZT = r16)", next);
220 return (True);
221 }
222 i = atoi(&data[1]);
223 /* check range of given register */
224 if (i > 31)
225 print_msg(pi, MSGTYPE_ERROR, "R%d is not a valid register", i);
226 /* check if this reg is already assigned */
227 for (def = pi->first_def; def; def = def->next) {
228 if (def->reg == i && pi->pass == PASS_1 && !pi->NoRegDef) {
229 print_msg(pi, MSGTYPE_WARNING, "r%d is already assigned to '%s'!", i, def->name);
230 return (True);
231 }
232 }
233 /* check if this regname is already defined */
234 for (def = pi->first_def; def; def = def->next) {
235 if (!nocase_strcmp(def->name, next)) {
236 if (pi->pass == PASS_1 && !pi->NoRegDef) {
237 print_msg(pi, MSGTYPE_WARNING, "'%s' is already assigned as r%d but will now be set to r%i!", next, def->reg, i);
238 }
239 def->reg = i;
240 return (True);
241 }
242 }
243 /* Check, if symbol is already defined as a label or constant */
244 if (pi->pass == PASS_2) {
245 if (get_label(pi,next,NULL))
246 print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a label", next);
247 if (get_constant(pi,next,NULL))
248 print_msg(pi, MSGTYPE_WARNING, "Name '%s' is used for a register and a constant", next);
249 }
250
251 def = malloc(sizeof(struct def));
252 if (!def) {
253 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
254 return (False);
255 }
256 def->next = NULL;
257 if (pi->last_def)
258 pi->last_def->next = def;
259 else
260 pi->first_def = def;
261 pi->last_def = def;
262 def->name = malloc(strlen(next) + 1);
263 if (!def->name) {
264 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
265 return (False);
266 }
267 strcpy(def->name, next);
268 def->reg = i;
269 break;
270 case DIRECTIVE_DEVICE:
271 if (pi->pass == PASS_2)
272 return (True);
273 if (!next) {
274 print_msg(pi, MSGTYPE_ERROR, ".DEVICE needs an operand");
275 return (True);
276 }
277 if (pi->device->name != NULL) { /* Check for multiple device definitions */
278 print_msg(pi, MSGTYPE_ERROR, "More than one .DEVICE definition");
279 }
280 if (pi->cseg->count || pi->dseg->count || pi->eseg->count) {
281 /* Check if something was already assembled */
282 print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any code lines");
283 } else {
284 if ((pi->cseg->addr != pi->cseg->lo_addr)
285 || (pi->dseg->addr != pi->dseg->lo_addr)
286 || (pi->eseg->addr != pi->eseg->lo_addr)) {
287 /* Check if something was already assembled */
288 print_msg(pi, MSGTYPE_ERROR, ".DEVICE definition must be before any .ORG directive");
289 }
290 }
291
292 get_next_token(next, TERM_END);
293 pi->device = get_device(pi,next);
294 if (!pi->device) {
295 print_msg(pi, MSGTYPE_ERROR, "Unknown device: %s", next);
296 pi->device = get_device(pi,NULL); /* Fix segmentation fault if device is unknown */
297 }
298
299 /* Now that we know the device type, we can
300 * start memory allocation from the correct offsets.
301 */
302 fix_orglist(pi->segment);
303
304 init_segment_size(pi, pi->device); /* Resync. ...->lo_addr variables */
305 def_orglist(pi->segment);
306 break;
307 case DIRECTIVE_DSEG:
308 fix_orglist(pi->segment);
309 def_orglist(pi->dseg);
310 if (pi->dseg->hi_addr == 0) {
311 /* XXX move to emit */
312 print_msg(pi, MSGTYPE_ERROR, "Can't use .DSEG directive because device has no RAM");
313 }
314 break;
315 case DIRECTIVE_DW:
316 if (pi->segment->flags & SEG_BSS_DATA) {
317 print_msg(pi, MSGTYPE_ERROR, "Can't use .DW directive in data segment (.DSEG)");
318 return (True);
319 }
320 while (next) {
321 data = get_next_token(next, TERM_COMMA);
322 if (pi->pass == PASS_2) {
323 if (!get_expr(pi, next, &i))
324 return (False);
325 if ((i < -32768) || (i > 65535))
326 print_msg(pi, MSGTYPE_WARNING, "Value %d is out of range (-32768 <= k <= 65535). Will be masked", i);
327 }
328 if (pi->pass == PASS_2) {
329 if (pi->list_line && pi->list_on) {
330 fprintf(pi->list_file, " %s\n", pi->list_line);
331 pi->list_line = NULL;
332 fprintf(pi->list_file, "%c:%06lx %04x\n",
333 pi->segment->ident, pi->segment->addr, i);
334 }
335 if (pi->segment == pi->eseg) {
336 write_ee_byte(pi, pi->eseg->addr, (unsigned char)i);
337 write_ee_byte(pi, pi->eseg->addr + 1, (unsigned char)(i >> 8));
338 }
339 if (pi->segment == pi->cseg) {
340 write_prog_word(pi, pi->cseg->addr, i);
341 }
342 }
343 if (pi->segment == pi->eseg)
344 advance_ip(pi->eseg, 2);
345 if (pi->segment == pi->cseg)
346 advance_ip(pi->cseg, 1);
347 next = data;
348 }
349 break;
350 case DIRECTIVE_ENDM:
351 case DIRECTIVE_ENDMACRO:
352 print_msg(pi, MSGTYPE_ERROR, "No .MACRO found before .ENDMACRO");
353 break;
354 case DIRECTIVE_EQU:
355 if (!next) {
356 print_msg(pi, MSGTYPE_ERROR, ".EQU needs an operand");
357 return (True);
358 }
359 data = get_next_token(next, TERM_EQUAL);
360 if (!data) {
361 print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .EQU BZZZT = 0x2a)", next);
362 return (True);
363 }
364 get_next_token(data, TERM_END);
365 if (!get_expr(pi, data, &i))
366 return (False);
367 if (test_label(pi,next,"%s have already been defined as a label")!=NULL)
368 return (True);
369 if (test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL)
370 return (True);
371 /* Forward references allowed. But check, if everything is ok ... */
372 if (pi->pass==PASS_1) { /* Pass 1 */
373 if (test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL)
374 return (True);
375 if (def_const(pi, next, i)==False)
376 return (False);
377 } else { /* Pass 2 */
378 int j;
379 if (get_constant(pi, next, &j)==False) { /* Defined in Pass 1 and now missing ? */
380 print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next);
381 return (False);
382 }
383 if (i != j) {
384 print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i);
385 return (False);
386 }
387 /* OK. Definition is unchanged */
388 }
389 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
390 fprintf(pi->list_file, " %s\n", pi->list_line);
391 pi->list_line = NULL;
392 }
393 break;
394 case DIRECTIVE_ESEG:
395 fix_orglist(pi->segment);
396 def_orglist(pi->eseg);
397 if (pi->device->eeprom_size == 0) { /* XXX */
398 print_msg(pi, MSGTYPE_ERROR, "Can't use .ESEG directive because device has no EEPROM");
399 }
400 break;
401 case DIRECTIVE_EXIT:
402 pi->fi->exit_file = True;
403 break;
404 case DIRECTIVE_INCLUDE:
405 if (!next) {
406 print_msg(pi, MSGTYPE_ERROR, "Nothing to include");
407 return (True);
408 }
409 next = term_string(pi, next);
410 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
411 fprintf(pi->list_file, " %s\n", pi->list_line);
412 pi->list_line = NULL;
413 }
414 /* Test if include is in local directory */
415 ok = test_include(next);
416 data = NULL;
417 if (!ok) {
418 #ifdef DEFAULT_INCLUDE_PATH
419 data = joinpaths(DEFAULT_INCLUDE_PATH, next);
420 ok = test_include(data);
421 #endif
422 for (incpath = GET_ARG_LIST(pi->args, ARG_INCLUDEPATH); incpath && !ok; incpath = incpath->next) {
423 if (data != NULL) {
424 free(data);
425 }
426 data = joinpaths(incpath->data, next);
427 if (data == NULL) {
428 print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
429 return (False);
430 }
431 ok = test_include(data);
432 }
433 }
434 if (ok) {
435 fi_bak = pi->fi;
436 ok = parse_file(pi, data ? data : next);
437 pi->fi = fi_bak;
438 } else
439 print_msg(pi, MSGTYPE_ERROR, "Cannot find include file: %s", next);
440 if (data)
441 free(data);
442 break;
443 case DIRECTIVE_INCLUDEPATH:
444 if (!next) {
445 print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand");
446 return (True);
447 }
448 data = get_next_token(next, TERM_SPACE);
449 if (data) {
450 print_msg(pi, MSGTYPE_ERROR, ".INCLUDEPATH needs an operand!!!");
451 get_next_token(data, TERM_END);
452 if (!get_expr(pi, data, &i))
453 return (False);
454 }
455 next = term_string(pi, next);
456 /* get arg list start pointer */
457 incpath = GET_ARG_LIST(pi->args, ARG_INCLUDEPATH);
458 /* search for last element */
459 if (incpath == NULL) {
460 dl = malloc(sizeof(struct data_list));
461 data = malloc(strlen(next)+1);
462 if (dl && data) {
463 dl->next = NULL;
464 strcpy(data, next);
465 dl->data = data;
466 SET_ARG_LIST(pi->args, ARG_INCLUDEPATH, dl);
467 } else {
468 printf("Error: Unable to allocate memory\n");
469 return (False);
470 }
471 } else
472 add_arg(&incpath, next);
473 break;
474 case DIRECTIVE_LIST:
475 if (pi->pass == PASS_2)
476 if (pi->list_file)
477 pi->list_on = True;
478 break;
479 case DIRECTIVE_LISTMAC:
480 if (pi->pass == PASS_2)
481 SET_ARG_I(pi->args, ARG_LISTMAC, True);
482 break;
483 case DIRECTIVE_MACRO:
484 return (read_macro(pi, next));
485 case DIRECTIVE_NOLIST:
486 if (pi->pass == PASS_2)
487 pi->list_on = False;
488 break;
489 case DIRECTIVE_ORG:
490 if (!next) {
491 print_msg(pi, MSGTYPE_ERROR, ".ORG needs an operand");
492 return (True);
493 }
494 get_next_token(next, TERM_END);
495 if (!get_expr(pi, next, &i))
496 return (False);
497 fix_orglist(pi->segment);
498 pi->segment->addr = i; /* XXX advance */
499 def_orglist(pi->segment);
500 if (pi->fi->label)
501 pi->fi->label->value = i;
502 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
503 fprintf(pi->list_file, " %s\n", pi->list_line);
504 pi->list_line = NULL;
505 }
506 break;
507 case DIRECTIVE_SET:
508 if (!next) {
509 print_msg(pi, MSGTYPE_ERROR, ".SET needs an operand");
510 return (True);
511 }
512 data = get_next_token(next, TERM_EQUAL);
513 if (!data) {
514 print_msg(pi, MSGTYPE_ERROR, "%s needs an expression (e.g. .SET BZZZT = 0x2a)", next);
515 return (True);
516 }
517 get_next_token(data, TERM_END);
518 if (!get_expr(pi, data, &i))
519 return (False);
520
521 if (test_label(pi,next,"%s have already been defined as a label")!=NULL)
522 return (True);
523 if (test_constant(pi,next,"%s have already been defined as a .EQU constant")!=NULL)
524 return (True);
525 return (def_var(pi, next, i));
526 case DIRECTIVE_DEFINE:
527 if (!next) {
528 print_msg(pi, MSGTYPE_ERROR, ".DEFINE needs an operand");
529 return (True);
530 }
531 data = get_next_token(next, TERM_SPACE);
532 if (data) {
533 get_next_token(data, TERM_END);
534 if (!get_expr(pi, data, &i))
535 return (False);
536 } else
537 i = 1;
538 if (test_label(pi,next,"%s have already been defined as a label")!=NULL)
539 return (True);
540 if (test_variable(pi,next,"%s have already been defined as a .SET variable")!=NULL)
541 return (True);
542 /* Forward references allowed. But check, if everything is ok ... */
543 if (pi->pass==PASS_1) { /* Pass 1 */
544 if (test_constant(pi,next,"Can't redefine constant %s, use .SET instead")!=NULL)
545 return (True);
546 if (def_const(pi, next, i)==False)
547 return (False);
548 } else { /* Pass 2 */
549 int j;
550 if (get_constant(pi, next, &j)==False) { /* Defined in Pass 1 and now missing ? */
551 print_msg(pi, MSGTYPE_ERROR, "Constant %s is missing in pass 2", next);
552 return (False);
553 }
554 if (i != j) {
555 print_msg(pi, MSGTYPE_ERROR, "Constant %s changed value from %d in pass1 to %d in pass 2", next,j,i);
556 return (False);
557 }
558 /* OK. Definition is unchanged */
559 }
560 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on) {
561 fprintf(pi->list_file, " %s\n", pi->list_line);
562 pi->list_line = NULL;
563 }
564 break;
565 case DIRECTIVE_NOOVERLAP:
566 if (pi->pass == PASS_1) {
567 fix_orglist(pi->segment);
568 pi->segment_overlap = SEG_DONT_OVERLAP;
569 def_orglist(pi->segment);
570 }
571 break;
572 case DIRECTIVE_OVERLAP:
573 if (pi->pass == PASS_1) {
574 fix_orglist(pi->segment);
575 pi->segment_overlap = SEG_ALLOW_OVERLAP;
576 def_orglist(pi->segment);
577 }
578 break;
579 case DIRECTIVE_PRAGMA:
580 if (!next) {
581 print_msg(pi, MSGTYPE_ERROR, "PRAGMA needs an operand, %s should be specified",
582 snprint_list(buf, sizeof(buf), pragma_list));
583 return (True);
584 }
585 my_strupr(next);
586 data = get_next_token(next, TERM_SPACE);
587 pragma = lookup_keyword(pragma_list, next, False);
588 switch (pragma) {
589
590 case PRAGMA_OVERLAP:
591 if (pi->pass == PASS_1) {
592 int overlap_setting = OVERLAP_UNDEFINED;
593 if (data) {
594 my_strupr(data);
595 overlap_setting = lookup_keyword(overlap_value, data, False);
596 };
597 switch (overlap_setting) {
598 case OVERLAP_DEFAULT:
599 pi->effective_overlap = GET_ARG_I(pi->args, ARG_OVERLAP);
600 break;
601
602 case OVERLAP_IGNORE:
603 case OVERLAP_WARNING:
604 case OVERLAP_ERROR:
605 pi->effective_overlap = overlap_setting;
606 break;
607
608 default:
609 print_msg(pi, MSGTYPE_ERROR, "For PRAGMA %s directive"
610 " %s should be specified as the parameter", next,
611 snprint_list(buf, sizeof(buf), overlap_value));
612 return (False);
613 }
614 }
615 return (True);
616 break;
617 default:
618 if (pi->pass == PASS_2)
619 print_msg(pi, MSGTYPE_MESSAGE, "PRAGMA %s directive currently ignored", next);
620 return (True);
621 }
622 break;
623 case DIRECTIVE_UNDEF: /* TODO */
624 break;
625 case DIRECTIVE_IFDEF:
626 if (!next) {
627 print_msg(pi, MSGTYPE_ERROR, ".IFDEF needs an operand");
628 return True;
629 }
630 get_next_token(next, TERM_END);
631 /* Store location of ifdef (line number and file number) if the condition
632 * fails on pass 1 so that we do not reinterpret it as succeeding on pass 2. */
633 if ((pi->pass==PASS_1 && get_symbol(pi, next, NULL)) || (pi->pass==PASS_2 && !ifdef_is_blacklisted(pi))) {
634 pi->conditional_depth++;
635 } else {
636 if (pi->pass==PASS_1) {
637 /* Blacklist this ifdef. */
638 if (!ifdef_blacklist(pi)) {
639 return False;
640 }
641 }
642 if (!spool_conditional(pi, False)) {
643 return False;
644 }
645 }
646 break;
647 case DIRECTIVE_IFNDEF:
648 if (!next) {
649 print_msg(pi, MSGTYPE_ERROR, ".IFNDEF needs an operand");
650 return True;
651 }
652 get_next_token(next, TERM_END);
653 /* Store location of ifndef (line number and file number) if the condition
654 * fails on pass 1 so that we do not reinterpret it as succeeding on pass 2. */
655 if ((pi->pass==PASS_1 && !get_symbol(pi, next, NULL)) || (pi->pass==PASS_2 && !ifndef_is_blacklisted(pi))) {
656 pi->conditional_depth++;
657 } else {
658 if (pi->pass==PASS_1) {
659 /* Blacklist this ifndef. */
660 if (!ifndef_blacklist(pi)) {
661 return False;
662 }
663 }
664 if (!spool_conditional(pi, False)) {
665 return False;
666 }
667 }
668 break;
669 case DIRECTIVE_IF:
670 if (!next) {
671 print_msg(pi, MSGTYPE_ERROR, ".IF needs an expression");
672 return (True);
673 }
674 get_next_token(next, TERM_END);
675 if (!get_expr(pi, next, &i))
676 return (False);
677 if (i)
678 pi->conditional_depth++;
679 else {
680 if (!spool_conditional(pi, False))
681 return (False);
682 }
683 break;
684 case DIRECTIVE_ELSE:
685 case DIRECTIVE_ELIF:
686 case DIRECTIVE_ELSEIF:
687 if (!spool_conditional(pi, True))
688 return (False);
689 break;
690 case DIRECTIVE_ENDIF:
691 if (pi->conditional_depth == 0)
692 print_msg(pi, MSGTYPE_ERROR, "Too many .ENDIF");
693 else
694 pi->conditional_depth--;
695 break;
696 case DIRECTIVE_MESSAGE:
697 if (pi->pass == PASS_1)
698 return (True);
699 if (!next) {
700 print_msg(pi, MSGTYPE_ERROR, "No message parameter supplied");
701 return (True);
702 }
703 print_msg(pi, MSGTYPE_MESSAGE_NO_LF, NULL); /* Prints Line Header (filename, linenumber) without trailing \n */
704 while (next) {
705 data = get_next_token(next, TERM_COMMA);
706 if (next[0] == '\"') { /* string parsing */
707 next = term_string(pi, next);
708 print_msg(pi, MSGTYPE_APPEND,"%s",next);
709 while (*next != '\0') {
710 next++;
711 }
712 } else {
713 if (!get_expr(pi, next, &i)) {
714 print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */
715 return (False);
716 }
717 print_msg(pi, MSGTYPE_APPEND,"0x%02X",i);
718 }
719 next = data;
720 }
721 print_msg(pi, MSGTYPE_APPEND,"\n"); /* Add newline */
722 break;
723 case DIRECTIVE_WARNING:
724 if (pi->pass == PASS_1)
725 return (True);
726 if (!next) {
727 print_msg(pi, MSGTYPE_ERROR, "No warning string supplied");
728 return (True);
729 }
730 next = term_string(pi, next);
731 print_msg(pi, MSGTYPE_WARNING, next);
732 break;
733 case DIRECTIVE_ERROR:
734 if (!next) {
735 print_msg(pi, MSGTYPE_ERROR, "No error string supplied");
736 return (True);
737 }
738 next = term_string(pi, next);
739 print_msg(pi, MSGTYPE_ERROR, "%s", next);
740 pi->error_count = pi->max_errors;
741 if (pi->pass == PASS_1)
742 return (True);
743 break;
744 }
745 return (ok);
746 }
747
748
749 int
lookup_keyword(const char * const keyword_list[],const char * const keyword,int strict)750 lookup_keyword(const char *const keyword_list[], const char *const keyword, int strict)
751 {
752 int i;
753
754 for (i = 0; keyword_list[i] != NULL; i++) {
755 if (strict) {
756 if (!strcmp(keyword, keyword_list[i]))
757 return (i);
758 } else {
759 if (!strncmp(keyword, keyword_list[i], strlen(keyword_list[i])))
760 return (i);
761 }
762 }
763 return (-1);
764 }
765
766 char *
term_string(struct prog_info * pi,char * string)767 term_string(struct prog_info *pi, char *string)
768 {
769 int i;
770
771 if (string[0] != '\"') {
772 print_msg(pi, MSGTYPE_ERROR, "String must be enclosed in \"-signs");
773 } else {
774 string++;
775 }
776 /* skip to the end of the string*/
777 for (i = 0; (string[i] != '\"') && !((string[i] == 10) || (string[i] == 13) || (string[i] == '\0')); i++);
778 if ((string[i] == 10) || (string[i] == 13) || (string[i] == '\0')) {
779 print_msg(pi, MSGTYPE_ERROR, "String is missing a closing \"-sign");
780 }
781 string[i] = '\0'; /* and terminate it where the " was */
782 return (string);
783 }
784
785 /* Parse data byte directive */
786 int
parse_db(struct prog_info * pi,char * next)787 parse_db(struct prog_info *pi, char *next)
788 {
789 int i;
790 int count;
791 char *data;
792 char prev = 0;
793
794 /* check if .db is allowed in this segment type */
795 if (pi->segment->flags & SEG_BSS_DATA) {
796 print_msg(pi, MSGTYPE_ERROR, "Can't use .DB directive in data segment (.DSEG) !");
797 return True ;
798 }
799
800 count = 0;
801 if (pi->pass == PASS_2 && pi->list_on) {
802 fprintf(pi->list_file, "%c:%06lX ", pi->segment->ident, pi->segment->addr);
803 }
804 /* get each db token */
805 while (next) {
806 data = get_next_token(next, TERM_COMMA);
807 /* string parsing */
808 if (next[0] == '\"') {
809 next = term_string(pi, next);
810 while (*next != '\0') {
811 count++;
812 write_db(pi, *next, &prev, count);
813 if (pi->pass == PASS_2 && pi->list_on)
814 fprintf(pi->list_file, "%02X", (unsigned char)*next);
815 if ((unsigned char)*next > 127 && pi->pass == PASS_2)
816 print_msg(pi, MSGTYPE_WARNING, "Found .DB string with characters > code 127. Be careful !"); /* Print warning for codes > 127 */
817 next++;
818 }
819 } else {
820 if (pi->pass == PASS_2) {
821 if (!get_expr(pi, next, &i))
822 return (False);
823 if ((i < -128) || (i > 255))
824 print_msg(pi, MSGTYPE_WARNING, "Value %d is out of range (-128 <= k <= 255). Will be masked", i);
825 if (pi->list_on) fprintf(pi->list_file, "%02X", i);
826 }
827 count++;
828 write_db(pi, (char)i, &prev, count);
829 }
830 next = data;
831 }
832 if (pi->segment == pi->cseg) { /* XXX PAD */
833 if ((count % 2) == 1) {
834 if (pi->pass == PASS_2) {
835 if (pi->list_on) fprintf(pi->list_file, "00 ; zero byte added");
836 write_prog_word(pi, pi->segment->addr, prev & 0xFF);
837 print_msg(pi, MSGTYPE_WARNING, "A .DB segment with an odd number of bytes is detected. A zero byte is added.");
838 }
839 advance_ip(pi->cseg, 1);
840 }
841 }
842 if (pi->pass == PASS_2 && pi->list_on) {
843 fprintf(pi->list_file, "\n");
844 pi->list_line = NULL;
845 }
846 return True;
847 }
848
849
850 void
write_db(struct prog_info * pi,char byte,char * prev,int count)851 write_db(struct prog_info *pi, char byte, char *prev, int count)
852 {
853 if (pi->segment == pi->eseg) {
854 if (pi->pass == PASS_2) {
855 write_ee_byte(pi, pi->eseg->addr, byte);
856 }
857 advance_ip(pi->eseg, 1);
858 }
859 if (pi->segment == pi->cseg) {
860 if ((count % 2) == 0) {
861 if (pi->pass == PASS_2) {
862 write_prog_word(pi, pi->cseg->addr, (byte << 8) | (*prev & 0xff));
863 }
864 advance_ip(pi->cseg, 1);
865 } else {
866 *prev = byte;
867 }
868 }
869 }
870
871
872 int
spool_conditional(struct prog_info * pi,int only_endif)873 spool_conditional(struct prog_info *pi, int only_endif)
874 {
875 int current_depth = 0, do_next;
876
877 if (pi->macro_line) {
878 while ((pi->macro_line = pi->macro_line->next)) {
879 pi->macro_call->line_index++;
880 if (check_conditional(pi, pi->macro_line->line, ¤t_depth, &do_next, only_endif)) {
881 if (!do_next)
882 return (True);
883 } else
884 return (False);
885 }
886 print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDIF in macro");
887 } else {
888 if ((pi->pass == PASS_2) && pi->list_line && pi->list_on)
889 fprintf(pi->list_file, " %s\n", pi->list_line);
890 while (fgets_new(pi,pi->fi->buff, LINEBUFFER_LENGTH, pi->fi->fp)) {
891 pi->fi->line_number++;
892 if (check_conditional(pi, pi->fi->buff, ¤t_depth, &do_next, only_endif)) {
893 if (!do_next)
894 return (True);
895 } else
896 return (False);
897 }
898 if (feof(pi->fi->fp)) {
899 print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDIF");
900 return (True);
901 } else {
902 perror(pi->fi->include_file->name);
903 return (False);
904 }
905 }
906 return (True);
907 }
908
909
910 int
check_conditional(struct prog_info * pi,char * pbuff,int * current_depth,int * do_next,int only_endif)911 check_conditional(struct prog_info *pi, char *pbuff, int *current_depth, int *do_next, int only_endif)
912 {
913 int i = 0;
914 char *next;
915 char linebuff[LINEBUFFER_LENGTH];
916
917 strcpy(linebuff, pbuff); /* avoid cutting of the end of .elif line */
918
919 *do_next = False;
920 while (IS_HOR_SPACE(linebuff[i]) && !IS_END_OR_COMMENT(linebuff[i])) i++;
921 if ((linebuff[i] == '.') || (linebuff[i] == '#')) {
922 i++;
923 if (!nocase_strncmp(&linebuff[i], "if", 2))
924 (*current_depth)++;
925 else if (!nocase_strncmp(&linebuff[i], "endif", 5)) {
926 if (*current_depth == 0)
927 return (True);
928 (*current_depth)--;
929 } else if (!only_endif && (*current_depth == 0)) {
930 if ((!nocase_strncmp(&linebuff[i], "else", 4)) && (nocase_strncmp(&linebuff[i], "elseif", 6))) {
931 pi->conditional_depth++;
932 return (True);
933 } else if ((!nocase_strncmp(&linebuff[i], "elif", 4)) || (!nocase_strncmp(&linebuff[i], "elseif", 6))) {
934 next = get_next_token(&linebuff[i], TERM_SPACE);
935 if (!next) {
936 print_msg(pi, MSGTYPE_ERROR, ".ELSEIF / .ELIF needs an operand");
937 return (True);
938 }
939 get_next_token(next, TERM_END);
940 if (!get_expr(pi, next, &i))
941 return (False);
942 if (i)
943 pi->conditional_depth++;
944 else {
945 if (!spool_conditional(pi, False))
946 return (False);
947 }
948 return (True);
949 }
950 }
951 }
952 *do_next = True;
953 return (True);
954 }
955
956 int
test_include(const char * filename)957 test_include(const char *filename)
958 {
959 FILE *fp;
960 fp = fopen(filename, "r");
961 if (fp) {
962 fclose(fp);
963 return (True);
964 } else
965 return (False);
966 }
967
968 /* end of directiv.c */
969
970
971