0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #include <sys/types.h>
0045 #include <sys/mman.h>
0046
0047 #include <ctype.h>
0048 #include <inttypes.h>
0049 #include <regex.h>
0050 #include <stdio.h>
0051 #include <stdlib.h>
0052 #include <string.h>
0053 #include <sysexits.h>
0054 #include <unistd.h>
0055
0056 #if linux
0057 #include <endian.h>
0058 #else
0059 #include <machine/endian.h>
0060 #endif
0061
0062 #include "aicasm.h"
0063 #include "aicasm_symbol.h"
0064 #include "aicasm_insformat.h"
0065
0066 typedef struct patch {
0067 STAILQ_ENTRY(patch) links;
0068 int patch_func;
0069 u_int begin;
0070 u_int skip_instr;
0071 u_int skip_patch;
0072 } patch_t;
0073
0074 STAILQ_HEAD(patch_list, patch) patches;
0075
0076 static void usage(void);
0077 static void back_patch(void);
0078 static void output_code(void);
0079 static void output_listing(char *ifilename);
0080 static void dump_scope(scope_t *scope);
0081 static void emit_patch(scope_t *scope, int patch);
0082 static int check_patch(patch_t **start_patch, int start_instr,
0083 int *skip_addr, int *func_vals);
0084
0085 struct path_list search_path;
0086 int includes_search_curdir;
0087 char *appname;
0088 char *stock_include_file;
0089 FILE *ofile;
0090 char *ofilename;
0091 char *regfilename;
0092 FILE *regfile;
0093 char *listfilename;
0094 FILE *listfile;
0095 char *regdiagfilename;
0096 FILE *regdiagfile;
0097 int src_mode;
0098 int dst_mode;
0099
0100 static STAILQ_HEAD(,instruction) seq_program;
0101 struct cs_tailq cs_tailq;
0102 struct scope_list scope_stack;
0103 symlist_t patch_functions;
0104
0105 #if DEBUG
0106 extern int yy_flex_debug;
0107 extern int mm_flex_debug;
0108 extern int yydebug;
0109 extern int mmdebug;
0110 #endif
0111 extern FILE *yyin;
0112 extern int yyparse(void);
0113
0114 int main(int argc, char *argv[]);
0115
0116 int
0117 main(int argc, char *argv[])
0118 {
0119 extern char *optarg;
0120 extern int optind;
0121 int ch;
0122 int retval;
0123 char *inputfilename;
0124 scope_t *sentinal;
0125
0126 STAILQ_INIT(&patches);
0127 SLIST_INIT(&search_path);
0128 STAILQ_INIT(&seq_program);
0129 TAILQ_INIT(&cs_tailq);
0130 SLIST_INIT(&scope_stack);
0131
0132
0133 sentinal = scope_alloc();
0134 sentinal->type = SCOPE_ROOT;
0135
0136 includes_search_curdir = 1;
0137 appname = *argv;
0138 regfile = NULL;
0139 listfile = NULL;
0140 #if DEBUG
0141 yy_flex_debug = 0;
0142 mm_flex_debug = 0;
0143 yydebug = 0;
0144 mmdebug = 0;
0145 #endif
0146 while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:")) != -1) {
0147 switch(ch) {
0148 case 'd':
0149 #if DEBUG
0150 if (strcmp(optarg, "s") == 0) {
0151 yy_flex_debug = 1;
0152 mm_flex_debug = 1;
0153 } else if (strcmp(optarg, "p") == 0) {
0154 yydebug = 1;
0155 mmdebug = 1;
0156 } else {
0157 fprintf(stderr, "%s: -d Requires either an "
0158 "'s' or 'p' argument\n", appname);
0159 usage();
0160 }
0161 #else
0162 stop("-d: Assembler not built with debugging "
0163 "information", EX_SOFTWARE);
0164 #endif
0165 break;
0166 case 'i':
0167 stock_include_file = optarg;
0168 break;
0169 case 'l':
0170
0171 if ((listfile = fopen(optarg, "w")) == NULL) {
0172 perror(optarg);
0173 stop(NULL, EX_CANTCREAT);
0174 }
0175 listfilename = optarg;
0176 break;
0177 case 'n':
0178
0179 if (strcmp(optarg, "ostdinc")) {
0180 fprintf(stderr, "%s: Unknown option -%c%s\n",
0181 appname, ch, optarg);
0182 usage();
0183
0184 }
0185 break;
0186 case 'o':
0187 if ((ofile = fopen(optarg, "w")) == NULL) {
0188 perror(optarg);
0189 stop(NULL, EX_CANTCREAT);
0190 }
0191 ofilename = optarg;
0192 break;
0193 case 'p':
0194
0195 if ((regdiagfile = fopen(optarg, "w")) == NULL) {
0196 perror(optarg);
0197 stop(NULL, EX_CANTCREAT);
0198 }
0199 regdiagfilename = optarg;
0200 break;
0201 case 'r':
0202 if ((regfile = fopen(optarg, "w")) == NULL) {
0203 perror(optarg);
0204 stop(NULL, EX_CANTCREAT);
0205 }
0206 regfilename = optarg;
0207 break;
0208 case 'I':
0209 {
0210 path_entry_t include_dir;
0211
0212 if (strcmp(optarg, "-") == 0) {
0213 if (includes_search_curdir == 0) {
0214 fprintf(stderr, "%s: Warning - '-I-' "
0215 "specified multiple "
0216 "times\n", appname);
0217 }
0218 includes_search_curdir = 0;
0219 for (include_dir = SLIST_FIRST(&search_path);
0220 include_dir != NULL;
0221 include_dir = SLIST_NEXT(include_dir,
0222 links))
0223
0224
0225
0226
0227
0228 include_dir->quoted_includes_only = 1;
0229 } else {
0230 include_dir =
0231 (path_entry_t)malloc(sizeof(*include_dir));
0232 if (include_dir == NULL) {
0233 perror(optarg);
0234 stop(NULL, EX_OSERR);
0235 }
0236 include_dir->directory = strdup(optarg);
0237 if (include_dir->directory == NULL) {
0238 perror(optarg);
0239 stop(NULL, EX_OSERR);
0240 }
0241 include_dir->quoted_includes_only = 0;
0242 SLIST_INSERT_HEAD(&search_path, include_dir,
0243 links);
0244 }
0245 break;
0246 }
0247 case '?':
0248 default:
0249 usage();
0250
0251 }
0252 }
0253 argc -= optind;
0254 argv += optind;
0255
0256 if (argc != 1) {
0257 fprintf(stderr, "%s: No input file specified\n", appname);
0258 usage();
0259
0260 }
0261
0262 if (regdiagfile != NULL
0263 && (regfile == NULL || stock_include_file == NULL)) {
0264 fprintf(stderr,
0265 "%s: The -p option requires the -r and -i options.\n",
0266 appname);
0267 usage();
0268
0269 }
0270 symtable_open();
0271 inputfilename = *argv;
0272 include_file(*argv, SOURCE_FILE);
0273 retval = yyparse();
0274 if (retval == 0) {
0275 if (SLIST_FIRST(&scope_stack) == NULL
0276 || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
0277 stop("Unterminated conditional expression", EX_DATAERR);
0278
0279 }
0280
0281
0282 process_scope(SLIST_FIRST(&scope_stack));
0283
0284
0285
0286
0287
0288
0289 dump_scope(SLIST_FIRST(&scope_stack));
0290
0291
0292 back_patch();
0293
0294 if (ofile != NULL)
0295 output_code();
0296 if (regfile != NULL)
0297 symtable_dump(regfile, regdiagfile);
0298 if (listfile != NULL)
0299 output_listing(inputfilename);
0300 }
0301
0302 stop(NULL, 0);
0303
0304 return (0);
0305 }
0306
0307 static void
0308 usage()
0309 {
0310
0311 (void)fprintf(stderr,
0312 "usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]\n"
0313 " [-r register_output_file [-p register_diag_file -i includefile]]\n"
0314 " [-l program_list_file]\n"
0315 " input_file\n", appname);
0316 exit(EX_USAGE);
0317 }
0318
0319 static void
0320 back_patch()
0321 {
0322 struct instruction *cur_instr;
0323
0324 for (cur_instr = STAILQ_FIRST(&seq_program);
0325 cur_instr != NULL;
0326 cur_instr = STAILQ_NEXT(cur_instr, links)) {
0327 if (cur_instr->patch_label != NULL) {
0328 struct ins_format3 *f3_instr;
0329 u_int address;
0330
0331 if (cur_instr->patch_label->type != LABEL) {
0332 char buf[255];
0333
0334 snprintf(buf, sizeof(buf),
0335 "Undefined label %s",
0336 cur_instr->patch_label->name);
0337 stop(buf, EX_DATAERR);
0338
0339 }
0340 f3_instr = &cur_instr->format.format3;
0341 address = f3_instr->address;
0342 address += cur_instr->patch_label->info.linfo->address;
0343 f3_instr->address = address;
0344 }
0345 }
0346 }
0347
0348 static void
0349 output_code()
0350 {
0351 struct instruction *cur_instr;
0352 patch_t *cur_patch;
0353 critical_section_t *cs;
0354 symbol_node_t *cur_node;
0355 int instrcount;
0356
0357 instrcount = 0;
0358 fprintf(ofile,
0359 "/*\n"
0360 " * DO NOT EDIT - This file is automatically generated\n"
0361 " * from the following source files:\n"
0362 " *\n"
0363 "%s */\n", versions);
0364
0365 fprintf(ofile, "static const uint8_t seqprog[] = {\n");
0366 for (cur_instr = STAILQ_FIRST(&seq_program);
0367 cur_instr != NULL;
0368 cur_instr = STAILQ_NEXT(cur_instr, links)) {
0369
0370 fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
0371 cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
0372 #ifdef __LITTLE_ENDIAN
0373 cur_instr->format.bytes[0],
0374 cur_instr->format.bytes[1],
0375 cur_instr->format.bytes[2],
0376 cur_instr->format.bytes[3]);
0377 #else
0378 cur_instr->format.bytes[3],
0379 cur_instr->format.bytes[2],
0380 cur_instr->format.bytes[1],
0381 cur_instr->format.bytes[0]);
0382 #endif
0383 instrcount++;
0384 }
0385 fprintf(ofile, "\n};\n\n");
0386
0387 if (patch_arg_list == NULL)
0388 stop("Patch argument list not defined",
0389 EX_DATAERR);
0390
0391
0392
0393
0394 fprintf(ofile,
0395 "typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list);
0396
0397 for (cur_node = SLIST_FIRST(&patch_functions);
0398 cur_node != NULL;
0399 cur_node = SLIST_NEXT(cur_node,links)) {
0400 fprintf(ofile,
0401 "static %spatch_func_t %spatch%d_func;\n"
0402 "\n"
0403 "static int\n"
0404 "%spatch%d_func(%s)\n"
0405 "{\n"
0406 " return (%s);\n"
0407 "}\n\n",
0408 prefix,
0409 prefix,
0410 cur_node->symbol->info.condinfo->func_num,
0411 prefix,
0412 cur_node->symbol->info.condinfo->func_num,
0413 patch_arg_list,
0414 cur_node->symbol->name);
0415 }
0416
0417 fprintf(ofile,
0418 "static const struct patch {\n"
0419 " %spatch_func_t *patch_func;\n"
0420 " uint32_t begin :10,\n"
0421 " skip_instr :10,\n"
0422 " skip_patch :12;\n"
0423 "} patches[] = {\n", prefix);
0424
0425 for (cur_patch = STAILQ_FIRST(&patches);
0426 cur_patch != NULL;
0427 cur_patch = STAILQ_NEXT(cur_patch,links)) {
0428 fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }",
0429 cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
0430 prefix,
0431 cur_patch->patch_func, cur_patch->begin,
0432 cur_patch->skip_instr, cur_patch->skip_patch);
0433 }
0434
0435 fprintf(ofile, "\n};\n\n");
0436
0437 fprintf(ofile,
0438 "static const struct cs {\n"
0439 " uint16_t begin;\n"
0440 " uint16_t end;\n"
0441 "} critical_sections[] = {\n");
0442
0443 for (cs = TAILQ_FIRST(&cs_tailq);
0444 cs != NULL;
0445 cs = TAILQ_NEXT(cs, links)) {
0446 fprintf(ofile, "%s\t{ %d, %d }",
0447 cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
0448 cs->begin_addr, cs->end_addr);
0449 }
0450
0451 fprintf(ofile, "\n};\n\n");
0452
0453 fprintf(ofile,
0454 "#define NUM_CRITICAL_SECTIONS ARRAY_SIZE(critical_sections)\n");
0455
0456 fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
0457 }
0458
0459 static void
0460 dump_scope(scope_t *scope)
0461 {
0462 scope_t *cur_scope;
0463
0464
0465
0466
0467 emit_patch(scope, 0);
0468
0469
0470
0471
0472 cur_scope = TAILQ_FIRST(&scope->inner_scope);
0473
0474 while (cur_scope != NULL) {
0475
0476 dump_scope(cur_scope);
0477
0478 cur_scope = TAILQ_NEXT(cur_scope, scope_links);
0479 }
0480
0481
0482
0483
0484 emit_patch(scope, 1);
0485 }
0486
0487 void
0488 emit_patch(scope_t *scope, int patch)
0489 {
0490 patch_info_t *pinfo;
0491 patch_t *new_patch;
0492
0493 pinfo = &scope->patches[patch];
0494
0495 if (pinfo->skip_instr == 0)
0496
0497 return;
0498
0499 new_patch = (patch_t *)malloc(sizeof(*new_patch));
0500
0501 if (new_patch == NULL)
0502 stop("Could not malloc patch structure", EX_OSERR);
0503
0504 memset(new_patch, 0, sizeof(*new_patch));
0505
0506 if (patch == 0) {
0507 new_patch->patch_func = scope->func_num;
0508 new_patch->begin = scope->begin_addr;
0509 } else {
0510 new_patch->patch_func = 0;
0511 new_patch->begin = scope->end_addr;
0512 }
0513 new_patch->skip_instr = pinfo->skip_instr;
0514 new_patch->skip_patch = pinfo->skip_patch;
0515 STAILQ_INSERT_TAIL(&patches, new_patch, links);
0516 }
0517
0518 void
0519 output_listing(char *ifilename)
0520 {
0521 char buf[1024];
0522 FILE *ifile;
0523 struct instruction *cur_instr;
0524 patch_t *cur_patch;
0525 symbol_node_t *cur_func;
0526 int *func_values;
0527 int instrcount;
0528 int instrptr;
0529 int line;
0530 int func_count;
0531 int skip_addr;
0532
0533 instrcount = 0;
0534 instrptr = 0;
0535 line = 1;
0536 skip_addr = 0;
0537 if ((ifile = fopen(ifilename, "r")) == NULL) {
0538 perror(ifilename);
0539 stop(NULL, EX_DATAERR);
0540 }
0541
0542
0543
0544
0545 for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
0546 cur_func != NULL;
0547 cur_func = SLIST_NEXT(cur_func, links))
0548 func_count++;
0549
0550 func_values = NULL;
0551 if (func_count != 0) {
0552 func_values = (int *)malloc(func_count * sizeof(int));
0553
0554 if (func_values == NULL)
0555 stop("Could not malloc", EX_OSERR);
0556
0557 func_values[0] = 0;
0558 func_count--;
0559
0560
0561
0562
0563
0564
0565
0566 for (cur_func = SLIST_FIRST(&patch_functions);
0567 cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
0568 cur_func = SLIST_NEXT(cur_func, links), func_count--) {
0569 int input;
0570
0571 fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
0572 fprintf(stdout,
0573 "Enter the return value for "
0574 "this expression[T/F]:");
0575
0576 while (1) {
0577
0578 input = getchar();
0579 input = toupper(input);
0580
0581 if (input == 'T') {
0582 func_values[func_count] = 1;
0583 break;
0584 } else if (input == 'F') {
0585 func_values[func_count] = 0;
0586 break;
0587 }
0588 }
0589 if (isatty(fileno(stdin)) == 0)
0590 putchar(input);
0591 }
0592 fprintf(stdout, "\nThanks!\n");
0593 }
0594
0595
0596 cur_patch = STAILQ_FIRST(&patches);
0597 for (cur_instr = STAILQ_FIRST(&seq_program);
0598 cur_instr != NULL;
0599 cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
0600
0601 if (check_patch(&cur_patch, instrcount,
0602 &skip_addr, func_values) == 0) {
0603
0604
0605
0606 continue;
0607 }
0608
0609 while (line < cur_instr->srcline) {
0610 fgets(buf, sizeof(buf), ifile);
0611 fprintf(listfile, " \t%s", buf);
0612 line++;
0613 }
0614 fprintf(listfile, "%04x %02x%02x%02x%02x", instrptr,
0615 #ifdef __LITTLE_ENDIAN
0616 cur_instr->format.bytes[0],
0617 cur_instr->format.bytes[1],
0618 cur_instr->format.bytes[2],
0619 cur_instr->format.bytes[3]);
0620 #else
0621 cur_instr->format.bytes[3],
0622 cur_instr->format.bytes[2],
0623 cur_instr->format.bytes[1],
0624 cur_instr->format.bytes[0]);
0625 #endif
0626
0627
0628
0629
0630
0631 if (line == cur_instr->srcline) {
0632 fgets(buf, sizeof(buf), ifile);
0633 fprintf(listfile, "\t%s", buf);
0634 line++;
0635 } else {
0636 fprintf(listfile, "\n");
0637 }
0638 instrptr++;
0639 }
0640
0641 while(fgets(buf, sizeof(buf), ifile) != NULL)
0642 fprintf(listfile, " %s", buf);
0643
0644 fclose(ifile);
0645 }
0646
0647 static int
0648 check_patch(patch_t **start_patch, int start_instr,
0649 int *skip_addr, int *func_vals)
0650 {
0651 patch_t *cur_patch;
0652
0653 cur_patch = *start_patch;
0654
0655 while (cur_patch != NULL && start_instr == cur_patch->begin) {
0656 if (func_vals[cur_patch->patch_func] == 0) {
0657 int skip;
0658
0659
0660 *skip_addr = start_instr + cur_patch->skip_instr;
0661 for (skip = cur_patch->skip_patch;
0662 skip > 0 && cur_patch != NULL;
0663 skip--)
0664 cur_patch = STAILQ_NEXT(cur_patch, links);
0665 } else {
0666
0667
0668
0669
0670 cur_patch = STAILQ_NEXT(cur_patch, links);
0671 }
0672 }
0673
0674 *start_patch = cur_patch;
0675 if (start_instr < *skip_addr)
0676
0677 return (0);
0678
0679 return (1);
0680 }
0681
0682
0683
0684
0685
0686 void
0687 stop(const char *string, int err_code)
0688 {
0689 if (string != NULL) {
0690 fprintf(stderr, "%s: ", appname);
0691 if (yyfilename != NULL) {
0692 fprintf(stderr, "Stopped at file %s, line %d - ",
0693 yyfilename, yylineno);
0694 }
0695 fprintf(stderr, "%s\n", string);
0696 }
0697
0698 if (ofile != NULL) {
0699 fclose(ofile);
0700 if (err_code != 0) {
0701 fprintf(stderr, "%s: Removing %s due to error\n",
0702 appname, ofilename);
0703 unlink(ofilename);
0704 }
0705 }
0706
0707 if (regfile != NULL) {
0708 fclose(regfile);
0709 if (err_code != 0) {
0710 fprintf(stderr, "%s: Removing %s due to error\n",
0711 appname, regfilename);
0712 unlink(regfilename);
0713 }
0714 }
0715
0716 if (listfile != NULL) {
0717 fclose(listfile);
0718 if (err_code != 0) {
0719 fprintf(stderr, "%s: Removing %s due to error\n",
0720 appname, listfilename);
0721 unlink(listfilename);
0722 }
0723 }
0724
0725 symlist_free(&patch_functions);
0726 symtable_close();
0727
0728 exit(err_code);
0729 }
0730
0731 struct instruction *
0732 seq_alloc()
0733 {
0734 struct instruction *new_instr;
0735
0736 new_instr = (struct instruction *)malloc(sizeof(struct instruction));
0737 if (new_instr == NULL)
0738 stop("Unable to malloc instruction object", EX_SOFTWARE);
0739 memset(new_instr, 0, sizeof(*new_instr));
0740 STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
0741 new_instr->srcline = yylineno;
0742 return new_instr;
0743 }
0744
0745 critical_section_t *
0746 cs_alloc()
0747 {
0748 critical_section_t *new_cs;
0749
0750 new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
0751 if (new_cs == NULL)
0752 stop("Unable to malloc critical_section object", EX_SOFTWARE);
0753 memset(new_cs, 0, sizeof(*new_cs));
0754
0755 TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
0756 return new_cs;
0757 }
0758
0759 scope_t *
0760 scope_alloc()
0761 {
0762 scope_t *new_scope;
0763
0764 new_scope = (scope_t *)malloc(sizeof(scope_t));
0765 if (new_scope == NULL)
0766 stop("Unable to malloc scope object", EX_SOFTWARE);
0767 memset(new_scope, 0, sizeof(*new_scope));
0768 TAILQ_INIT(&new_scope->inner_scope);
0769
0770 if (SLIST_FIRST(&scope_stack) != NULL) {
0771 TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
0772 new_scope, scope_links);
0773 }
0774
0775 SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
0776 return new_scope;
0777 }
0778
0779 void
0780 process_scope(scope_t *scope)
0781 {
0782
0783
0784
0785
0786
0787 scope_t *cur_scope;
0788 u_int skip_patch_count;
0789 u_int skip_instr_count;
0790
0791 cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
0792 skip_patch_count = 0;
0793 skip_instr_count = 0;
0794 while (cur_scope != NULL) {
0795 u_int patch0_patch_skip;
0796
0797 patch0_patch_skip = 0;
0798 switch (cur_scope->type) {
0799 case SCOPE_IF:
0800 case SCOPE_ELSE_IF:
0801 if (skip_instr_count != 0) {
0802
0803 patch0_patch_skip++;
0804 cur_scope->patches[1].skip_patch =
0805 skip_patch_count + 1;
0806 cur_scope->patches[1].skip_instr =
0807 skip_instr_count;
0808 }
0809
0810
0811 patch0_patch_skip++;
0812
0813
0814 patch0_patch_skip += cur_scope->inner_scope_patches;
0815
0816 cur_scope->patches[0].skip_patch = patch0_patch_skip;
0817 cur_scope->patches[0].skip_instr =
0818 cur_scope->end_addr - cur_scope->begin_addr;
0819
0820 skip_instr_count += cur_scope->patches[0].skip_instr;
0821
0822 skip_patch_count += patch0_patch_skip;
0823 if (cur_scope->type == SCOPE_IF) {
0824 scope->inner_scope_patches += skip_patch_count;
0825 skip_patch_count = 0;
0826 skip_instr_count = 0;
0827 }
0828 break;
0829 case SCOPE_ELSE:
0830
0831 skip_patch_count += cur_scope->inner_scope_patches;
0832
0833 skip_instr_count += cur_scope->end_addr
0834 - cur_scope->begin_addr;
0835 break;
0836 case SCOPE_ROOT:
0837 stop("Unexpected scope type encountered", EX_SOFTWARE);
0838
0839 }
0840
0841 cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
0842 }
0843 }