~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/drivers/scsi/aic7xxx/aicasm/aicasm.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Aic7xxx SCSI host adapter firmware asssembler
3
 
 *
4
 
 * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs.
5
 
 * Copyright (c) 2001 Adaptec Inc.
6
 
 * All rights reserved.
7
 
 *
8
 
 * Redistribution and use in source and binary forms, with or without
9
 
 * modification, are permitted provided that the following conditions
10
 
 * are met:
11
 
 * 1. Redistributions of source code must retain the above copyright
12
 
 *    notice, this list of conditions, and the following disclaimer,
13
 
 *    without modification.
14
 
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
15
 
 *    substantially similar to the "NO WARRANTY" disclaimer below
16
 
 *    ("Disclaimer") and any redistribution must be conditioned upon
17
 
 *    including a substantially similar Disclaimer requirement for further
18
 
 *    binary redistribution.
19
 
 * 3. Neither the names of the above-listed copyright holders nor the names
20
 
 *    of any contributors may be used to endorse or promote products derived
21
 
 *    from this software without specific prior written permission.
22
 
 *
23
 
 * Alternatively, this software may be distributed under the terms of the
24
 
 * GNU General Public License ("GPL") version 2 as published by the Free
25
 
 * Software Foundation.
26
 
 *
27
 
 * NO WARRANTY
28
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29
 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
31
 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32
 
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34
 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35
 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36
 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
37
 
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
 
 * POSSIBILITY OF SUCH DAMAGES.
39
 
 *
40
 
 * $Id: //depot/aic7xxx/aic7xxx/aicasm/aicasm.c#16 $
41
 
 *
42
 
 * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm.c,v 1.28.2.5 2002/04/29 19:36:36 gibbs Exp $
43
 
 */
44
 
#include <sys/types.h>
45
 
#include <sys/mman.h>
46
 
 
47
 
#include <ctype.h>
48
 
#include <inttypes.h>
49
 
#include <regex.h>
50
 
#include <stdio.h>
51
 
#include <stdlib.h>
52
 
#include <string.h>
53
 
#include <sysexits.h>
54
 
#include <unistd.h>
55
 
 
56
 
#if linux
57
 
#include <endian.h>
58
 
#else
59
 
#include <machine/endian.h>
60
 
#endif
61
 
 
62
 
#include "aicasm.h"
63
 
#include "aicasm_symbol.h"
64
 
#include "aicasm_insformat.h"
65
 
 
66
 
typedef struct patch {
67
 
        STAILQ_ENTRY(patch) links;
68
 
        int             patch_func;
69
 
        u_int           begin;
70
 
        u_int           skip_instr;
71
 
        u_int           skip_patch;
72
 
} patch_t;
73
 
 
74
 
STAILQ_HEAD(patch_list, patch) patches;
75
 
 
76
 
static void usage(void);
77
 
static void back_patch(void);
78
 
static void output_code(void);
79
 
static void output_listing(char *ifilename);
80
 
static void dump_scope(scope_t *scope);
81
 
static void emit_patch(scope_t *scope, int patch);
82
 
static int check_patch(patch_t **start_patch, int start_instr,
83
 
                       int *skip_addr, int *func_vals);
84
 
 
85
 
struct path_list search_path;
86
 
int includes_search_curdir;
87
 
char *appname;
88
 
FILE *ofile;
89
 
char *ofilename;
90
 
char *regfilename;
91
 
FILE *regfile;
92
 
char *listfilename;
93
 
FILE *listfile;
94
 
int   src_mode;
95
 
int   dst_mode;
96
 
 
97
 
static STAILQ_HEAD(,instruction) seq_program;
98
 
struct cs_tailq cs_tailq;
99
 
struct scope_list scope_stack;
100
 
symlist_t patch_functions;
101
 
 
102
 
#if DEBUG
103
 
extern int yy_flex_debug;
104
 
extern int mm_flex_debug;
105
 
extern int yydebug;
106
 
extern int mmdebug;
107
 
#endif
108
 
extern FILE *yyin;
109
 
extern int yyparse(void);
110
 
 
111
 
int main(int argc, char *argv[]);
112
 
 
113
 
int
114
 
main(int argc, char *argv[])
115
 
{
116
 
        extern char *optarg;
117
 
        extern int optind;
118
 
        int  ch;
119
 
        int  retval;
120
 
        char *inputfilename;
121
 
        scope_t *sentinal;
122
 
 
123
 
        STAILQ_INIT(&patches);
124
 
        SLIST_INIT(&search_path);
125
 
        STAILQ_INIT(&seq_program);
126
 
        TAILQ_INIT(&cs_tailq);
127
 
        SLIST_INIT(&scope_stack);
128
 
 
129
 
        /* Set Sentinal scope node */
130
 
        sentinal = scope_alloc();
131
 
        sentinal->type = SCOPE_ROOT;
132
 
        
133
 
        includes_search_curdir = 1;
134
 
        appname = *argv;
135
 
        regfile = NULL;
136
 
        listfile = NULL;
137
 
#if DEBUG
138
 
        yy_flex_debug = 0;
139
 
        mm_flex_debug = 0;
140
 
        yydebug = 0;
141
 
        mmdebug = 0;
142
 
#endif
143
 
        while ((ch = getopt(argc, argv, "d:l:n:o:r:I:O:")) != -1) {
144
 
                switch(ch) {
145
 
                case 'd':
146
 
#if DEBUG
147
 
                        if (strcmp(optarg, "s") == 0) {
148
 
                                yy_flex_debug = 1;
149
 
                                mm_flex_debug = 1;
150
 
                        } else if (strcmp(optarg, "p") == 0) {
151
 
                                yydebug = 1;
152
 
                                mmdebug = 1;
153
 
                        } else {
154
 
                                fprintf(stderr, "%s: -d Requires either an "
155
 
                                        "'s' or 'p' argument\n", appname);
156
 
                                usage();
157
 
                        }
158
 
#else
159
 
                        stop("-d: Assembler not built with debugging "
160
 
                             "information", EX_SOFTWARE);
161
 
#endif
162
 
                        break;
163
 
                case 'l':
164
 
                        /* Create a program listing */
165
 
                        if ((listfile = fopen(optarg, "w")) == NULL) {
166
 
                                perror(optarg);
167
 
                                stop(NULL, EX_CANTCREAT);
168
 
                        }
169
 
                        listfilename = optarg;
170
 
                        break;
171
 
                case 'n':
172
 
                        /* Don't complain about the -nostdinc directrive */
173
 
                        if (strcmp(optarg, "ostdinc")) {
174
 
                                fprintf(stderr, "%s: Unknown option -%c%s\n",
175
 
                                        appname, ch, optarg);
176
 
                                usage();
177
 
                                /* NOTREACHED */
178
 
                        }
179
 
                        break;
180
 
                case 'o':
181
 
                        if ((ofile = fopen(optarg, "w")) == NULL) {
182
 
                                perror(optarg);
183
 
                                stop(NULL, EX_CANTCREAT);
184
 
                        }
185
 
                        ofilename = optarg;
186
 
                        break;
187
 
                case 'r':
188
 
                        if ((regfile = fopen(optarg, "w")) == NULL) {
189
 
                                perror(optarg);
190
 
                                stop(NULL, EX_CANTCREAT);
191
 
                        }
192
 
                        regfilename = optarg;
193
 
                        break;
194
 
                case 'I':
195
 
                {
196
 
                        path_entry_t include_dir;
197
 
 
198
 
                        if (strcmp(optarg, "-") == 0) {
199
 
                                if (includes_search_curdir == 0) {
200
 
                                        fprintf(stderr, "%s: Warning - '-I-' "
201
 
                                                        "specified multiple "
202
 
                                                        "times\n", appname);
203
 
                                }
204
 
                                includes_search_curdir = 0;
205
 
                                for (include_dir = SLIST_FIRST(&search_path);
206
 
                                     include_dir != NULL;
207
 
                                     include_dir = SLIST_NEXT(include_dir,
208
 
                                                              links))
209
 
                                        /*
210
 
                                         * All entries before a '-I-' only
211
 
                                         * apply to includes specified with
212
 
                                         * quotes instead of "<>".
213
 
                                         */
214
 
                                        include_dir->quoted_includes_only = 1;
215
 
                        } else {
216
 
                                include_dir =
217
 
                                    (path_entry_t)malloc(sizeof(*include_dir));
218
 
                                if (include_dir == NULL) {
219
 
                                        perror(optarg);
220
 
                                        stop(NULL, EX_OSERR);
221
 
                                }
222
 
                                include_dir->directory = strdup(optarg);
223
 
                                if (include_dir->directory == NULL) {
224
 
                                        perror(optarg);
225
 
                                        stop(NULL, EX_OSERR);
226
 
                                }
227
 
                                include_dir->quoted_includes_only = 0;
228
 
                                SLIST_INSERT_HEAD(&search_path, include_dir,
229
 
                                                  links);
230
 
                        }
231
 
                        break;
232
 
                }
233
 
                case '?':
234
 
                default:
235
 
                        usage();
236
 
                        /* NOTREACHED */
237
 
                }
238
 
        }
239
 
        argc -= optind;
240
 
        argv += optind;
241
 
 
242
 
        if (argc != 1) {
243
 
                fprintf(stderr, "%s: No input file specifiled\n", appname);
244
 
                usage();
245
 
                /* NOTREACHED */
246
 
        }
247
 
 
248
 
        symtable_open();
249
 
        inputfilename = *argv;
250
 
        include_file(*argv, SOURCE_FILE);
251
 
        retval = yyparse();
252
 
        if (retval == 0) {
253
 
                if (SLIST_FIRST(&scope_stack) == NULL
254
 
                 || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) {
255
 
                        stop("Unterminated conditional expression", EX_DATAERR);
256
 
                        /* NOTREACHED */
257
 
                }
258
 
 
259
 
                /* Process outmost scope */
260
 
                process_scope(SLIST_FIRST(&scope_stack));
261
 
                /*
262
 
                 * Decend the tree of scopes and insert/emit
263
 
                 * patches as appropriate.  We perform a depth first
264
 
                 * tranversal, recursively handling each scope.
265
 
                 */
266
 
                /* start at the root scope */
267
 
                dump_scope(SLIST_FIRST(&scope_stack));
268
 
 
269
 
                /* Patch up forward jump addresses */
270
 
                back_patch();
271
 
 
272
 
                if (ofile != NULL)
273
 
                        output_code();
274
 
                if (regfile != NULL) {
275
 
                        symtable_dump(regfile);
276
 
                }
277
 
                if (listfile != NULL)
278
 
                        output_listing(inputfilename);
279
 
        }
280
 
 
281
 
        stop(NULL, 0);
282
 
        /* NOTREACHED */
283
 
        return (0);
284
 
}
285
 
 
286
 
static void
287
 
usage()
288
 
{
289
 
 
290
 
        (void)fprintf(stderr,
291
 
"usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]
292
 
                        [-r register_output_file] [-l program_list_file]
293
 
                        input_file\n",
294
 
                        appname);
295
 
        exit(EX_USAGE);
296
 
}
297
 
 
298
 
static void
299
 
back_patch()
300
 
{
301
 
        struct instruction *cur_instr;
302
 
 
303
 
        for (cur_instr = STAILQ_FIRST(&seq_program);
304
 
             cur_instr != NULL;
305
 
             cur_instr = STAILQ_NEXT(cur_instr, links)) {
306
 
                if (cur_instr->patch_label != NULL) {
307
 
                        struct ins_format3 *f3_instr;
308
 
                        u_int address;
309
 
 
310
 
                        if (cur_instr->patch_label->type != LABEL) {
311
 
                                char buf[255];
312
 
 
313
 
                                snprintf(buf, sizeof(buf),
314
 
                                         "Undefined label %s",
315
 
                                         cur_instr->patch_label->name);
316
 
                                stop(buf, EX_DATAERR);
317
 
                                /* NOTREACHED */
318
 
                        }
319
 
                        f3_instr = &cur_instr->format.format3;
320
 
                        address = f3_instr->address;
321
 
                        address += cur_instr->patch_label->info.linfo->address;
322
 
                        f3_instr->address = address;
323
 
                }
324
 
        }
325
 
}
326
 
 
327
 
static void
328
 
output_code()
329
 
{
330
 
        struct instruction *cur_instr;
331
 
        patch_t *cur_patch;
332
 
        critical_section_t *cs;
333
 
        symbol_node_t *cur_node;
334
 
        int instrcount;
335
 
 
336
 
        instrcount = 0;
337
 
        fprintf(ofile,
338
 
"/*
339
 
 * DO NOT EDIT - This file is automatically generated
340
 
 *               from the following source files:
341
 
 *
342
 
%s */\n", versions);
343
 
 
344
 
        fprintf(ofile, "static uint8_t seqprog[] = {\n");
345
 
        for (cur_instr = STAILQ_FIRST(&seq_program);
346
 
             cur_instr != NULL;
347
 
             cur_instr = STAILQ_NEXT(cur_instr, links)) {
348
 
 
349
 
                fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x",
350
 
                        cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n",
351
 
#if BYTE_ORDER == LITTLE_ENDIAN
352
 
                        cur_instr->format.bytes[0],
353
 
                        cur_instr->format.bytes[1],
354
 
                        cur_instr->format.bytes[2],
355
 
                        cur_instr->format.bytes[3]);
356
 
#else
357
 
                        cur_instr->format.bytes[3],
358
 
                        cur_instr->format.bytes[2],
359
 
                        cur_instr->format.bytes[1],
360
 
                        cur_instr->format.bytes[0]);
361
 
#endif
362
 
                instrcount++;
363
 
        }
364
 
        fprintf(ofile, "\n};\n\n");
365
 
 
366
 
        if (patch_arg_list == NULL)
367
 
                stop("Patch argument list not defined",
368
 
                     EX_DATAERR);
369
 
 
370
 
        /*
371
 
         *  Output patch information.  Patch functions first.
372
 
         */
373
 
        for (cur_node = SLIST_FIRST(&patch_functions);
374
 
             cur_node != NULL;
375
 
             cur_node = SLIST_NEXT(cur_node,links)) {
376
 
                fprintf(ofile,
377
 
"static int aic_patch%d_func(%s);
378
 
 
379
 
static int
380
 
aic_patch%d_func(%s)
381
 
{
382
 
        return (%s);
383
 
}\n\n",
384
 
                        cur_node->symbol->info.condinfo->func_num,
385
 
                        patch_arg_list,
386
 
                        cur_node->symbol->info.condinfo->func_num,
387
 
                        patch_arg_list,
388
 
                        cur_node->symbol->name);
389
 
        }
390
 
 
391
 
        fprintf(ofile,
392
 
"typedef int patch_func_t (%s);
393
 
static struct patch {
394
 
        patch_func_t    *patch_func;
395
 
        uint32_t        begin      :10,
396
 
                        skip_instr :10,
397
 
                        skip_patch :12;
398
 
} patches[] = {\n", patch_arg_list);
399
 
 
400
 
        for (cur_patch = STAILQ_FIRST(&patches);
401
 
             cur_patch != NULL;
402
 
             cur_patch = STAILQ_NEXT(cur_patch,links)) {
403
 
                fprintf(ofile, "%s\t{ aic_patch%d_func, %d, %d, %d }",
404
 
                        cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n",
405
 
                        cur_patch->patch_func, cur_patch->begin,
406
 
                        cur_patch->skip_instr, cur_patch->skip_patch);
407
 
        }
408
 
 
409
 
        fprintf(ofile, "\n};\n");
410
 
 
411
 
        fprintf(ofile,
412
 
"static struct cs {
413
 
        u_int16_t       begin;
414
 
        u_int16_t       end;
415
 
} critical_sections[] = {\n");
416
 
 
417
 
        for (cs = TAILQ_FIRST(&cs_tailq);
418
 
             cs != NULL;
419
 
             cs = TAILQ_NEXT(cs, links)) {
420
 
                fprintf(ofile, "%s\t{ %d, %d }",
421
 
                        cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n",
422
 
                        cs->begin_addr, cs->end_addr);
423
 
        }
424
 
 
425
 
        fprintf(ofile, "\n};\n");
426
 
 
427
 
        fprintf(ofile,
428
 
"static const int num_critical_sections = sizeof(critical_sections)
429
 
                                       / sizeof(*critical_sections);\n");
430
 
 
431
 
        fprintf(stderr, "%s: %d instructions used\n", appname, instrcount);
432
 
}
433
 
 
434
 
static void
435
 
dump_scope(scope_t *scope)
436
 
{
437
 
        scope_t *cur_scope;
438
 
 
439
 
        /*
440
 
         * Emit the first patch for this scope
441
 
         */
442
 
        emit_patch(scope, 0);
443
 
 
444
 
        /*
445
 
         * Dump each scope within this one.
446
 
         */
447
 
        cur_scope = TAILQ_FIRST(&scope->inner_scope);
448
 
 
449
 
        while (cur_scope != NULL) {
450
 
 
451
 
                dump_scope(cur_scope);
452
 
 
453
 
                cur_scope = TAILQ_NEXT(cur_scope, scope_links);
454
 
        }
455
 
 
456
 
        /*
457
 
         * Emit the second, closing, patch for this scope
458
 
         */
459
 
        emit_patch(scope, 1);
460
 
}
461
 
 
462
 
void
463
 
emit_patch(scope_t *scope, int patch)
464
 
{
465
 
        patch_info_t *pinfo;
466
 
        patch_t *new_patch;
467
 
 
468
 
        pinfo = &scope->patches[patch];
469
 
 
470
 
        if (pinfo->skip_instr == 0)
471
 
                /* No-Op patch */
472
 
                return;
473
 
 
474
 
        new_patch = (patch_t *)malloc(sizeof(*new_patch));
475
 
 
476
 
        if (new_patch == NULL)
477
 
                stop("Could not malloc patch structure", EX_OSERR);
478
 
 
479
 
        memset(new_patch, 0, sizeof(*new_patch));
480
 
 
481
 
        if (patch == 0) {
482
 
                new_patch->patch_func = scope->func_num;
483
 
                new_patch->begin = scope->begin_addr;
484
 
        } else {
485
 
                new_patch->patch_func = 0;
486
 
                new_patch->begin = scope->end_addr;
487
 
        }
488
 
        new_patch->skip_instr = pinfo->skip_instr;
489
 
        new_patch->skip_patch = pinfo->skip_patch;
490
 
        STAILQ_INSERT_TAIL(&patches, new_patch, links);
491
 
}
492
 
 
493
 
void
494
 
output_listing(char *ifilename)
495
 
{
496
 
        char buf[1024];
497
 
        FILE *ifile;
498
 
        struct instruction *cur_instr;
499
 
        patch_t *cur_patch;
500
 
        symbol_node_t *cur_func;
501
 
        int *func_values;
502
 
        int instrcount;
503
 
        int instrptr;
504
 
        int line;
505
 
        int func_count;
506
 
        int skip_addr;
507
 
 
508
 
        instrcount = 0;
509
 
        instrptr = 0;
510
 
        line = 1;
511
 
        skip_addr = 0;
512
 
        if ((ifile = fopen(ifilename, "r")) == NULL) {
513
 
                perror(ifilename);
514
 
                stop(NULL, EX_DATAERR);
515
 
        }
516
 
 
517
 
        /*
518
 
         * Determine which options to apply to this listing.
519
 
         */
520
 
        for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions);
521
 
            cur_func != NULL;
522
 
            cur_func = SLIST_NEXT(cur_func, links))
523
 
                func_count++;
524
 
 
525
 
        func_values = NULL;
526
 
        if (func_count != 0) {
527
 
                func_values = (int *)malloc(func_count * sizeof(int));
528
 
 
529
 
                if (func_values == NULL)
530
 
                        stop("Could not malloc", EX_OSERR);
531
 
                
532
 
                func_values[0] = 0; /* FALSE func */
533
 
                func_count--;
534
 
 
535
 
                /*
536
 
                 * Ask the user to fill in the return values for
537
 
                 * the rest of the functions.
538
 
                 */
539
 
                
540
 
                
541
 
                for (cur_func = SLIST_FIRST(&patch_functions);
542
 
                     cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL;
543
 
                     cur_func = SLIST_NEXT(cur_func, links), func_count--) {
544
 
                        int input;
545
 
                        
546
 
                        fprintf(stdout, "\n(%s)\n", cur_func->symbol->name);
547
 
                        fprintf(stdout,
548
 
                                "Enter the return value for "
549
 
                                "this expression[T/F]:");
550
 
 
551
 
                        while (1) {
552
 
 
553
 
                                input = getchar();
554
 
                                input = toupper(input);
555
 
 
556
 
                                if (input == 'T') {
557
 
                                        func_values[func_count] = 1;
558
 
                                        break;
559
 
                                } else if (input == 'F') {
560
 
                                        func_values[func_count] = 0;
561
 
                                        break;
562
 
                                }
563
 
                        }
564
 
                        if (isatty(fileno(stdin)) == 0)
565
 
                                putchar(input);
566
 
                }
567
 
                fprintf(stdout, "\nThanks!\n");
568
 
        }
569
 
 
570
 
        /* Now output the listing */
571
 
        cur_patch = STAILQ_FIRST(&patches);
572
 
        for (cur_instr = STAILQ_FIRST(&seq_program);
573
 
             cur_instr != NULL;
574
 
             cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) {
575
 
 
576
 
                if (check_patch(&cur_patch, instrcount,
577
 
                                &skip_addr, func_values) == 0) {
578
 
                        /* Don't count this instruction as it is in a patch
579
 
                         * that was removed.
580
 
                         */
581
 
                        continue;
582
 
                }
583
 
 
584
 
                while (line < cur_instr->srcline) {
585
 
                        fgets(buf, sizeof(buf), ifile);
586
 
                                fprintf(listfile, "\t\t%s", buf);
587
 
                                line++;
588
 
                }
589
 
                fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr,
590
 
#if BYTE_ORDER == LITTLE_ENDIAN
591
 
                        cur_instr->format.bytes[0],
592
 
                        cur_instr->format.bytes[1],
593
 
                        cur_instr->format.bytes[2],
594
 
                        cur_instr->format.bytes[3]);
595
 
#else
596
 
                        cur_instr->format.bytes[3],
597
 
                        cur_instr->format.bytes[2],
598
 
                        cur_instr->format.bytes[1],
599
 
                        cur_instr->format.bytes[0]);
600
 
#endif
601
 
                fgets(buf, sizeof(buf), ifile);
602
 
                fprintf(listfile, "\t%s", buf);
603
 
                line++;
604
 
                instrptr++;
605
 
        }
606
 
        /* Dump the remainder of the file */
607
 
        while(fgets(buf, sizeof(buf), ifile) != NULL)
608
 
                fprintf(listfile, "\t\t%s", buf);
609
 
 
610
 
        fclose(ifile);
611
 
}
612
 
 
613
 
static int
614
 
check_patch(patch_t **start_patch, int start_instr,
615
 
            int *skip_addr, int *func_vals)
616
 
{
617
 
        patch_t *cur_patch;
618
 
 
619
 
        cur_patch = *start_patch;
620
 
 
621
 
        while (cur_patch != NULL && start_instr == cur_patch->begin) {
622
 
                if (func_vals[cur_patch->patch_func] == 0) {
623
 
                        int skip;
624
 
 
625
 
                        /* Start rejecting code */
626
 
                        *skip_addr = start_instr + cur_patch->skip_instr;
627
 
                        for (skip = cur_patch->skip_patch;
628
 
                             skip > 0 && cur_patch != NULL;
629
 
                             skip--)
630
 
                                cur_patch = STAILQ_NEXT(cur_patch, links);
631
 
                } else {
632
 
                        /* Accepted this patch.  Advance to the next
633
 
                         * one and wait for our intruction pointer to
634
 
                         * hit this point.
635
 
                         */
636
 
                        cur_patch = STAILQ_NEXT(cur_patch, links);
637
 
                }
638
 
        }
639
 
 
640
 
        *start_patch = cur_patch;
641
 
        if (start_instr < *skip_addr)
642
 
                /* Still skipping */
643
 
                return (0);
644
 
 
645
 
        return (1);
646
 
}
647
 
 
648
 
/*
649
 
 * Print out error information if appropriate, and clean up before
650
 
 * terminating the program.
651
 
 */
652
 
void
653
 
stop(const char *string, int err_code)
654
 
{
655
 
        if (string != NULL) {
656
 
                fprintf(stderr, "%s: ", appname);
657
 
                if (yyfilename != NULL) {
658
 
                        fprintf(stderr, "Stopped at file %s, line %d - ",
659
 
                                yyfilename, yylineno);
660
 
                }
661
 
                fprintf(stderr, "%s\n", string);
662
 
        }
663
 
 
664
 
        if (ofile != NULL) {
665
 
                fclose(ofile);
666
 
                if (err_code != 0) {
667
 
                        fprintf(stderr, "%s: Removing %s due to error\n",
668
 
                                appname, ofilename);
669
 
                        unlink(ofilename);
670
 
                }
671
 
        }
672
 
 
673
 
        if (regfile != NULL) {
674
 
                fclose(regfile);
675
 
                if (err_code != 0) {
676
 
                        fprintf(stderr, "%s: Removing %s due to error\n",
677
 
                                appname, regfilename);
678
 
                        unlink(regfilename);
679
 
                }
680
 
        }
681
 
 
682
 
        if (listfile != NULL) {
683
 
                fclose(listfile);
684
 
                if (err_code != 0) {
685
 
                        fprintf(stderr, "%s: Removing %s due to error\n",
686
 
                                appname, listfilename);
687
 
                        unlink(listfilename);
688
 
                }
689
 
        }
690
 
 
691
 
        symlist_free(&patch_functions);
692
 
        symtable_close();
693
 
 
694
 
        exit(err_code);
695
 
}
696
 
 
697
 
struct instruction *
698
 
seq_alloc()
699
 
{
700
 
        struct instruction *new_instr;
701
 
 
702
 
        new_instr = (struct instruction *)malloc(sizeof(struct instruction));
703
 
        if (new_instr == NULL)
704
 
                stop("Unable to malloc instruction object", EX_SOFTWARE);
705
 
        memset(new_instr, 0, sizeof(*new_instr));
706
 
        STAILQ_INSERT_TAIL(&seq_program, new_instr, links);
707
 
        new_instr->srcline = yylineno;
708
 
        return new_instr;
709
 
}
710
 
 
711
 
critical_section_t *
712
 
cs_alloc()
713
 
{
714
 
        critical_section_t *new_cs;
715
 
 
716
 
        new_cs= (critical_section_t *)malloc(sizeof(critical_section_t));
717
 
        if (new_cs == NULL)
718
 
                stop("Unable to malloc critical_section object", EX_SOFTWARE);
719
 
        memset(new_cs, 0, sizeof(*new_cs));
720
 
        
721
 
        TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links);
722
 
        return new_cs;
723
 
}
724
 
 
725
 
scope_t *
726
 
scope_alloc()
727
 
{
728
 
        scope_t *new_scope;
729
 
 
730
 
        new_scope = (scope_t *)malloc(sizeof(scope_t));
731
 
        if (new_scope == NULL)
732
 
                stop("Unable to malloc scope object", EX_SOFTWARE);
733
 
        memset(new_scope, 0, sizeof(*new_scope));
734
 
        TAILQ_INIT(&new_scope->inner_scope);
735
 
        
736
 
        if (SLIST_FIRST(&scope_stack) != NULL) {
737
 
                TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope,
738
 
                                  new_scope, scope_links);
739
 
        }
740
 
        /* This patch is now the current scope */
741
 
        SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links);
742
 
        return new_scope;
743
 
}
744
 
 
745
 
void
746
 
process_scope(scope_t *scope)
747
 
{
748
 
        /*
749
 
         * We are "leaving" this scope.  We should now have
750
 
         * enough information to process the lists of scopes
751
 
         * we encapsulate.
752
 
         */
753
 
        scope_t *cur_scope;
754
 
        u_int skip_patch_count;
755
 
        u_int skip_instr_count;
756
 
 
757
 
        cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq);
758
 
        skip_patch_count = 0;
759
 
        skip_instr_count = 0;
760
 
        while (cur_scope != NULL) {
761
 
                u_int patch0_patch_skip;
762
 
 
763
 
                patch0_patch_skip = 0;
764
 
                switch (cur_scope->type) {
765
 
                case SCOPE_IF:
766
 
                case SCOPE_ELSE_IF:
767
 
                        if (skip_instr_count != 0) {
768
 
                                /* Create a tail patch */
769
 
                                patch0_patch_skip++;
770
 
                                cur_scope->patches[1].skip_patch =
771
 
                                    skip_patch_count + 1;
772
 
                                cur_scope->patches[1].skip_instr =
773
 
                                    skip_instr_count;
774
 
                        }
775
 
 
776
 
                        /* Count Head patch */
777
 
                        patch0_patch_skip++;
778
 
 
779
 
                        /* Count any patches contained in our inner scope */
780
 
                        patch0_patch_skip += cur_scope->inner_scope_patches;
781
 
 
782
 
                        cur_scope->patches[0].skip_patch = patch0_patch_skip;
783
 
                        cur_scope->patches[0].skip_instr =
784
 
                            cur_scope->end_addr - cur_scope->begin_addr;
785
 
 
786
 
                        skip_instr_count += cur_scope->patches[0].skip_instr;
787
 
 
788
 
                        skip_patch_count += patch0_patch_skip;
789
 
                        if (cur_scope->type == SCOPE_IF) {
790
 
                                scope->inner_scope_patches += skip_patch_count;
791
 
                                skip_patch_count = 0;
792
 
                                skip_instr_count = 0;
793
 
                        }
794
 
                        break;
795
 
                case SCOPE_ELSE:
796
 
                        /* Count any patches contained in our innter scope */
797
 
                        skip_patch_count += cur_scope->inner_scope_patches;
798
 
 
799
 
                        skip_instr_count += cur_scope->end_addr
800
 
                                          - cur_scope->begin_addr;
801
 
                        break;
802
 
                case SCOPE_ROOT:
803
 
                        stop("Unexpected scope type encountered", EX_SOFTWARE);
804
 
                        /* NOTREACHED */
805
 
                }
806
 
 
807
 
                cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links);
808
 
        }
809
 
}