diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/scsi/aic7xxx/aicasm/aicasm.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/scsi/aic7xxx/aicasm/aicasm.c')
-rw-r--r-- | drivers/scsi/aic7xxx/aicasm/aicasm.c | 835 |
1 files changed, 835 insertions, 0 deletions
diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm.c b/drivers/scsi/aic7xxx/aicasm/aicasm.c new file mode 100644 index 000000000000..c34639481904 --- /dev/null +++ b/drivers/scsi/aic7xxx/aicasm/aicasm.c | |||
@@ -0,0 +1,835 @@ | |||
1 | /* | ||
2 | * Aic7xxx SCSI host adapter firmware asssembler | ||
3 | * | ||
4 | * Copyright (c) 1997, 1998, 2000, 2001 Justin T. Gibbs. | ||
5 | * Copyright (c) 2001, 2002 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#22 $ | ||
41 | * | ||
42 | * $FreeBSD$ | ||
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 | char *stock_include_file; | ||
89 | FILE *ofile; | ||
90 | char *ofilename; | ||
91 | char *regfilename; | ||
92 | FILE *regfile; | ||
93 | char *listfilename; | ||
94 | FILE *listfile; | ||
95 | char *regdiagfilename; | ||
96 | FILE *regdiagfile; | ||
97 | int src_mode; | ||
98 | int dst_mode; | ||
99 | |||
100 | static STAILQ_HEAD(,instruction) seq_program; | ||
101 | struct cs_tailq cs_tailq; | ||
102 | struct scope_list scope_stack; | ||
103 | symlist_t patch_functions; | ||
104 | |||
105 | #if DEBUG | ||
106 | extern int yy_flex_debug; | ||
107 | extern int mm_flex_debug; | ||
108 | extern int yydebug; | ||
109 | extern int mmdebug; | ||
110 | #endif | ||
111 | extern FILE *yyin; | ||
112 | extern int yyparse(void); | ||
113 | |||
114 | int main(int argc, char *argv[]); | ||
115 | |||
116 | int | ||
117 | main(int argc, char *argv[]) | ||
118 | { | ||
119 | extern char *optarg; | ||
120 | extern int optind; | ||
121 | int ch; | ||
122 | int retval; | ||
123 | char *inputfilename; | ||
124 | scope_t *sentinal; | ||
125 | |||
126 | STAILQ_INIT(&patches); | ||
127 | SLIST_INIT(&search_path); | ||
128 | STAILQ_INIT(&seq_program); | ||
129 | TAILQ_INIT(&cs_tailq); | ||
130 | SLIST_INIT(&scope_stack); | ||
131 | |||
132 | /* Set Sentinal scope node */ | ||
133 | sentinal = scope_alloc(); | ||
134 | sentinal->type = SCOPE_ROOT; | ||
135 | |||
136 | includes_search_curdir = 1; | ||
137 | appname = *argv; | ||
138 | regfile = NULL; | ||
139 | listfile = NULL; | ||
140 | #if DEBUG | ||
141 | yy_flex_debug = 0; | ||
142 | mm_flex_debug = 0; | ||
143 | yydebug = 0; | ||
144 | mmdebug = 0; | ||
145 | #endif | ||
146 | while ((ch = getopt(argc, argv, "d:i:l:n:o:p:r:I:")) != -1) { | ||
147 | switch(ch) { | ||
148 | case 'd': | ||
149 | #if DEBUG | ||
150 | if (strcmp(optarg, "s") == 0) { | ||
151 | yy_flex_debug = 1; | ||
152 | mm_flex_debug = 1; | ||
153 | } else if (strcmp(optarg, "p") == 0) { | ||
154 | yydebug = 1; | ||
155 | mmdebug = 1; | ||
156 | } else { | ||
157 | fprintf(stderr, "%s: -d Requires either an " | ||
158 | "'s' or 'p' argument\n", appname); | ||
159 | usage(); | ||
160 | } | ||
161 | #else | ||
162 | stop("-d: Assembler not built with debugging " | ||
163 | "information", EX_SOFTWARE); | ||
164 | #endif | ||
165 | break; | ||
166 | case 'i': | ||
167 | stock_include_file = optarg; | ||
168 | break; | ||
169 | case 'l': | ||
170 | /* Create a program listing */ | ||
171 | if ((listfile = fopen(optarg, "w")) == NULL) { | ||
172 | perror(optarg); | ||
173 | stop(NULL, EX_CANTCREAT); | ||
174 | } | ||
175 | listfilename = optarg; | ||
176 | break; | ||
177 | case 'n': | ||
178 | /* Don't complain about the -nostdinc directrive */ | ||
179 | if (strcmp(optarg, "ostdinc")) { | ||
180 | fprintf(stderr, "%s: Unknown option -%c%s\n", | ||
181 | appname, ch, optarg); | ||
182 | usage(); | ||
183 | /* NOTREACHED */ | ||
184 | } | ||
185 | break; | ||
186 | case 'o': | ||
187 | if ((ofile = fopen(optarg, "w")) == NULL) { | ||
188 | perror(optarg); | ||
189 | stop(NULL, EX_CANTCREAT); | ||
190 | } | ||
191 | ofilename = optarg; | ||
192 | break; | ||
193 | case 'p': | ||
194 | /* Create Register Diagnostic "printing" Functions */ | ||
195 | if ((regdiagfile = fopen(optarg, "w")) == NULL) { | ||
196 | perror(optarg); | ||
197 | stop(NULL, EX_CANTCREAT); | ||
198 | } | ||
199 | regdiagfilename = optarg; | ||
200 | break; | ||
201 | case 'r': | ||
202 | if ((regfile = fopen(optarg, "w")) == NULL) { | ||
203 | perror(optarg); | ||
204 | stop(NULL, EX_CANTCREAT); | ||
205 | } | ||
206 | regfilename = optarg; | ||
207 | break; | ||
208 | case 'I': | ||
209 | { | ||
210 | path_entry_t include_dir; | ||
211 | |||
212 | if (strcmp(optarg, "-") == 0) { | ||
213 | if (includes_search_curdir == 0) { | ||
214 | fprintf(stderr, "%s: Warning - '-I-' " | ||
215 | "specified multiple " | ||
216 | "times\n", appname); | ||
217 | } | ||
218 | includes_search_curdir = 0; | ||
219 | for (include_dir = SLIST_FIRST(&search_path); | ||
220 | include_dir != NULL; | ||
221 | include_dir = SLIST_NEXT(include_dir, | ||
222 | links)) | ||
223 | /* | ||
224 | * All entries before a '-I-' only | ||
225 | * apply to includes specified with | ||
226 | * quotes instead of "<>". | ||
227 | */ | ||
228 | include_dir->quoted_includes_only = 1; | ||
229 | } else { | ||
230 | include_dir = | ||
231 | (path_entry_t)malloc(sizeof(*include_dir)); | ||
232 | if (include_dir == NULL) { | ||
233 | perror(optarg); | ||
234 | stop(NULL, EX_OSERR); | ||
235 | } | ||
236 | include_dir->directory = strdup(optarg); | ||
237 | if (include_dir->directory == NULL) { | ||
238 | perror(optarg); | ||
239 | stop(NULL, EX_OSERR); | ||
240 | } | ||
241 | include_dir->quoted_includes_only = 0; | ||
242 | SLIST_INSERT_HEAD(&search_path, include_dir, | ||
243 | links); | ||
244 | } | ||
245 | break; | ||
246 | } | ||
247 | case '?': | ||
248 | default: | ||
249 | usage(); | ||
250 | /* NOTREACHED */ | ||
251 | } | ||
252 | } | ||
253 | argc -= optind; | ||
254 | argv += optind; | ||
255 | |||
256 | if (argc != 1) { | ||
257 | fprintf(stderr, "%s: No input file specifiled\n", appname); | ||
258 | usage(); | ||
259 | /* NOTREACHED */ | ||
260 | } | ||
261 | |||
262 | if (regdiagfile != NULL | ||
263 | && (regfile == NULL || stock_include_file == NULL)) { | ||
264 | fprintf(stderr, | ||
265 | "%s: The -p option requires the -r and -i options.\n", | ||
266 | appname); | ||
267 | usage(); | ||
268 | /* NOTREACHED */ | ||
269 | } | ||
270 | symtable_open(); | ||
271 | inputfilename = *argv; | ||
272 | include_file(*argv, SOURCE_FILE); | ||
273 | retval = yyparse(); | ||
274 | if (retval == 0) { | ||
275 | if (SLIST_FIRST(&scope_stack) == NULL | ||
276 | || SLIST_FIRST(&scope_stack)->type != SCOPE_ROOT) { | ||
277 | stop("Unterminated conditional expression", EX_DATAERR); | ||
278 | /* NOTREACHED */ | ||
279 | } | ||
280 | |||
281 | /* Process outmost scope */ | ||
282 | process_scope(SLIST_FIRST(&scope_stack)); | ||
283 | /* | ||
284 | * Decend the tree of scopes and insert/emit | ||
285 | * patches as appropriate. We perform a depth first | ||
286 | * tranversal, recursively handling each scope. | ||
287 | */ | ||
288 | /* start at the root scope */ | ||
289 | dump_scope(SLIST_FIRST(&scope_stack)); | ||
290 | |||
291 | /* Patch up forward jump addresses */ | ||
292 | back_patch(); | ||
293 | |||
294 | if (ofile != NULL) | ||
295 | output_code(); | ||
296 | if (regfile != NULL) | ||
297 | symtable_dump(regfile, regdiagfile); | ||
298 | if (listfile != NULL) | ||
299 | output_listing(inputfilename); | ||
300 | } | ||
301 | |||
302 | stop(NULL, 0); | ||
303 | /* NOTREACHED */ | ||
304 | return (0); | ||
305 | } | ||
306 | |||
307 | static void | ||
308 | usage() | ||
309 | { | ||
310 | |||
311 | (void)fprintf(stderr, | ||
312 | "usage: %-16s [-nostdinc] [-I-] [-I directory] [-o output_file]\n" | ||
313 | " [-r register_output_file [-p register_diag_file -i includefile]]\n" | ||
314 | " [-l program_list_file]\n" | ||
315 | " input_file\n", appname); | ||
316 | exit(EX_USAGE); | ||
317 | } | ||
318 | |||
319 | static void | ||
320 | back_patch() | ||
321 | { | ||
322 | struct instruction *cur_instr; | ||
323 | |||
324 | for (cur_instr = STAILQ_FIRST(&seq_program); | ||
325 | cur_instr != NULL; | ||
326 | cur_instr = STAILQ_NEXT(cur_instr, links)) { | ||
327 | if (cur_instr->patch_label != NULL) { | ||
328 | struct ins_format3 *f3_instr; | ||
329 | u_int address; | ||
330 | |||
331 | if (cur_instr->patch_label->type != LABEL) { | ||
332 | char buf[255]; | ||
333 | |||
334 | snprintf(buf, sizeof(buf), | ||
335 | "Undefined label %s", | ||
336 | cur_instr->patch_label->name); | ||
337 | stop(buf, EX_DATAERR); | ||
338 | /* NOTREACHED */ | ||
339 | } | ||
340 | f3_instr = &cur_instr->format.format3; | ||
341 | address = f3_instr->address; | ||
342 | address += cur_instr->patch_label->info.linfo->address; | ||
343 | f3_instr->address = address; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | static void | ||
349 | output_code() | ||
350 | { | ||
351 | struct instruction *cur_instr; | ||
352 | patch_t *cur_patch; | ||
353 | critical_section_t *cs; | ||
354 | symbol_node_t *cur_node; | ||
355 | int instrcount; | ||
356 | |||
357 | instrcount = 0; | ||
358 | fprintf(ofile, | ||
359 | "/*\n" | ||
360 | " * DO NOT EDIT - This file is automatically generated\n" | ||
361 | " * from the following source files:\n" | ||
362 | " *\n" | ||
363 | "%s */\n", versions); | ||
364 | |||
365 | fprintf(ofile, "static uint8_t seqprog[] = {\n"); | ||
366 | for (cur_instr = STAILQ_FIRST(&seq_program); | ||
367 | cur_instr != NULL; | ||
368 | cur_instr = STAILQ_NEXT(cur_instr, links)) { | ||
369 | |||
370 | fprintf(ofile, "%s\t0x%02x, 0x%02x, 0x%02x, 0x%02x", | ||
371 | cur_instr == STAILQ_FIRST(&seq_program) ? "" : ",\n", | ||
372 | #if BYTE_ORDER == LITTLE_ENDIAN | ||
373 | cur_instr->format.bytes[0], | ||
374 | cur_instr->format.bytes[1], | ||
375 | cur_instr->format.bytes[2], | ||
376 | cur_instr->format.bytes[3]); | ||
377 | #else | ||
378 | cur_instr->format.bytes[3], | ||
379 | cur_instr->format.bytes[2], | ||
380 | cur_instr->format.bytes[1], | ||
381 | cur_instr->format.bytes[0]); | ||
382 | #endif | ||
383 | instrcount++; | ||
384 | } | ||
385 | fprintf(ofile, "\n};\n\n"); | ||
386 | |||
387 | if (patch_arg_list == NULL) | ||
388 | stop("Patch argument list not defined", | ||
389 | EX_DATAERR); | ||
390 | |||
391 | /* | ||
392 | * Output patch information. Patch functions first. | ||
393 | */ | ||
394 | fprintf(ofile, | ||
395 | "typedef int %spatch_func_t (%s);\n", prefix, patch_arg_list); | ||
396 | |||
397 | for (cur_node = SLIST_FIRST(&patch_functions); | ||
398 | cur_node != NULL; | ||
399 | cur_node = SLIST_NEXT(cur_node,links)) { | ||
400 | fprintf(ofile, | ||
401 | "static %spatch_func_t %spatch%d_func;\n" | ||
402 | "\n" | ||
403 | "static int\n" | ||
404 | "%spatch%d_func(%s)\n" | ||
405 | "{\n" | ||
406 | " return (%s);\n" | ||
407 | "}\n\n", | ||
408 | prefix, | ||
409 | prefix, | ||
410 | cur_node->symbol->info.condinfo->func_num, | ||
411 | prefix, | ||
412 | cur_node->symbol->info.condinfo->func_num, | ||
413 | patch_arg_list, | ||
414 | cur_node->symbol->name); | ||
415 | } | ||
416 | |||
417 | fprintf(ofile, | ||
418 | "static struct patch {\n" | ||
419 | " %spatch_func_t *patch_func;\n" | ||
420 | " uint32_t begin :10,\n" | ||
421 | " skip_instr :10,\n" | ||
422 | " skip_patch :12;\n" | ||
423 | "} patches[] = {\n", prefix); | ||
424 | |||
425 | for (cur_patch = STAILQ_FIRST(&patches); | ||
426 | cur_patch != NULL; | ||
427 | cur_patch = STAILQ_NEXT(cur_patch,links)) { | ||
428 | fprintf(ofile, "%s\t{ %spatch%d_func, %d, %d, %d }", | ||
429 | cur_patch == STAILQ_FIRST(&patches) ? "" : ",\n", | ||
430 | prefix, | ||
431 | cur_patch->patch_func, cur_patch->begin, | ||
432 | cur_patch->skip_instr, cur_patch->skip_patch); | ||
433 | } | ||
434 | |||
435 | fprintf(ofile, "\n};\n\n"); | ||
436 | |||
437 | fprintf(ofile, | ||
438 | "static struct cs {\n" | ||
439 | " uint16_t begin;\n" | ||
440 | " uint16_t end;\n" | ||
441 | "} critical_sections[] = {\n"); | ||
442 | |||
443 | for (cs = TAILQ_FIRST(&cs_tailq); | ||
444 | cs != NULL; | ||
445 | cs = TAILQ_NEXT(cs, links)) { | ||
446 | fprintf(ofile, "%s\t{ %d, %d }", | ||
447 | cs == TAILQ_FIRST(&cs_tailq) ? "" : ",\n", | ||
448 | cs->begin_addr, cs->end_addr); | ||
449 | } | ||
450 | |||
451 | fprintf(ofile, "\n};\n\n"); | ||
452 | |||
453 | fprintf(ofile, | ||
454 | "static const int num_critical_sections = sizeof(critical_sections)\n" | ||
455 | " / sizeof(*critical_sections);\n"); | ||
456 | |||
457 | fprintf(stderr, "%s: %d instructions used\n", appname, instrcount); | ||
458 | } | ||
459 | |||
460 | static void | ||
461 | dump_scope(scope_t *scope) | ||
462 | { | ||
463 | scope_t *cur_scope; | ||
464 | |||
465 | /* | ||
466 | * Emit the first patch for this scope | ||
467 | */ | ||
468 | emit_patch(scope, 0); | ||
469 | |||
470 | /* | ||
471 | * Dump each scope within this one. | ||
472 | */ | ||
473 | cur_scope = TAILQ_FIRST(&scope->inner_scope); | ||
474 | |||
475 | while (cur_scope != NULL) { | ||
476 | |||
477 | dump_scope(cur_scope); | ||
478 | |||
479 | cur_scope = TAILQ_NEXT(cur_scope, scope_links); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * Emit the second, closing, patch for this scope | ||
484 | */ | ||
485 | emit_patch(scope, 1); | ||
486 | } | ||
487 | |||
488 | void | ||
489 | emit_patch(scope_t *scope, int patch) | ||
490 | { | ||
491 | patch_info_t *pinfo; | ||
492 | patch_t *new_patch; | ||
493 | |||
494 | pinfo = &scope->patches[patch]; | ||
495 | |||
496 | if (pinfo->skip_instr == 0) | ||
497 | /* No-Op patch */ | ||
498 | return; | ||
499 | |||
500 | new_patch = (patch_t *)malloc(sizeof(*new_patch)); | ||
501 | |||
502 | if (new_patch == NULL) | ||
503 | stop("Could not malloc patch structure", EX_OSERR); | ||
504 | |||
505 | memset(new_patch, 0, sizeof(*new_patch)); | ||
506 | |||
507 | if (patch == 0) { | ||
508 | new_patch->patch_func = scope->func_num; | ||
509 | new_patch->begin = scope->begin_addr; | ||
510 | } else { | ||
511 | new_patch->patch_func = 0; | ||
512 | new_patch->begin = scope->end_addr; | ||
513 | } | ||
514 | new_patch->skip_instr = pinfo->skip_instr; | ||
515 | new_patch->skip_patch = pinfo->skip_patch; | ||
516 | STAILQ_INSERT_TAIL(&patches, new_patch, links); | ||
517 | } | ||
518 | |||
519 | void | ||
520 | output_listing(char *ifilename) | ||
521 | { | ||
522 | char buf[1024]; | ||
523 | FILE *ifile; | ||
524 | struct instruction *cur_instr; | ||
525 | patch_t *cur_patch; | ||
526 | symbol_node_t *cur_func; | ||
527 | int *func_values; | ||
528 | int instrcount; | ||
529 | int instrptr; | ||
530 | int line; | ||
531 | int func_count; | ||
532 | int skip_addr; | ||
533 | |||
534 | instrcount = 0; | ||
535 | instrptr = 0; | ||
536 | line = 1; | ||
537 | skip_addr = 0; | ||
538 | if ((ifile = fopen(ifilename, "r")) == NULL) { | ||
539 | perror(ifilename); | ||
540 | stop(NULL, EX_DATAERR); | ||
541 | } | ||
542 | |||
543 | /* | ||
544 | * Determine which options to apply to this listing. | ||
545 | */ | ||
546 | for (func_count = 0, cur_func = SLIST_FIRST(&patch_functions); | ||
547 | cur_func != NULL; | ||
548 | cur_func = SLIST_NEXT(cur_func, links)) | ||
549 | func_count++; | ||
550 | |||
551 | func_values = NULL; | ||
552 | if (func_count != 0) { | ||
553 | func_values = (int *)malloc(func_count * sizeof(int)); | ||
554 | |||
555 | if (func_values == NULL) | ||
556 | stop("Could not malloc", EX_OSERR); | ||
557 | |||
558 | func_values[0] = 0; /* FALSE func */ | ||
559 | func_count--; | ||
560 | |||
561 | /* | ||
562 | * Ask the user to fill in the return values for | ||
563 | * the rest of the functions. | ||
564 | */ | ||
565 | |||
566 | |||
567 | for (cur_func = SLIST_FIRST(&patch_functions); | ||
568 | cur_func != NULL && SLIST_NEXT(cur_func, links) != NULL; | ||
569 | cur_func = SLIST_NEXT(cur_func, links), func_count--) { | ||
570 | int input; | ||
571 | |||
572 | fprintf(stdout, "\n(%s)\n", cur_func->symbol->name); | ||
573 | fprintf(stdout, | ||
574 | "Enter the return value for " | ||
575 | "this expression[T/F]:"); | ||
576 | |||
577 | while (1) { | ||
578 | |||
579 | input = getchar(); | ||
580 | input = toupper(input); | ||
581 | |||
582 | if (input == 'T') { | ||
583 | func_values[func_count] = 1; | ||
584 | break; | ||
585 | } else if (input == 'F') { | ||
586 | func_values[func_count] = 0; | ||
587 | break; | ||
588 | } | ||
589 | } | ||
590 | if (isatty(fileno(stdin)) == 0) | ||
591 | putchar(input); | ||
592 | } | ||
593 | fprintf(stdout, "\nThanks!\n"); | ||
594 | } | ||
595 | |||
596 | /* Now output the listing */ | ||
597 | cur_patch = STAILQ_FIRST(&patches); | ||
598 | for (cur_instr = STAILQ_FIRST(&seq_program); | ||
599 | cur_instr != NULL; | ||
600 | cur_instr = STAILQ_NEXT(cur_instr, links), instrcount++) { | ||
601 | |||
602 | if (check_patch(&cur_patch, instrcount, | ||
603 | &skip_addr, func_values) == 0) { | ||
604 | /* Don't count this instruction as it is in a patch | ||
605 | * that was removed. | ||
606 | */ | ||
607 | continue; | ||
608 | } | ||
609 | |||
610 | while (line < cur_instr->srcline) { | ||
611 | fgets(buf, sizeof(buf), ifile); | ||
612 | fprintf(listfile, "\t\t%s", buf); | ||
613 | line++; | ||
614 | } | ||
615 | fprintf(listfile, "%03x %02x%02x%02x%02x", instrptr, | ||
616 | #if BYTE_ORDER == LITTLE_ENDIAN | ||
617 | cur_instr->format.bytes[0], | ||
618 | cur_instr->format.bytes[1], | ||
619 | cur_instr->format.bytes[2], | ||
620 | cur_instr->format.bytes[3]); | ||
621 | #else | ||
622 | cur_instr->format.bytes[3], | ||
623 | cur_instr->format.bytes[2], | ||
624 | cur_instr->format.bytes[1], | ||
625 | cur_instr->format.bytes[0]); | ||
626 | #endif | ||
627 | fgets(buf, sizeof(buf), ifile); | ||
628 | fprintf(listfile, "\t%s", buf); | ||
629 | line++; | ||
630 | instrptr++; | ||
631 | } | ||
632 | /* Dump the remainder of the file */ | ||
633 | while(fgets(buf, sizeof(buf), ifile) != NULL) | ||
634 | fprintf(listfile, "\t\t%s", buf); | ||
635 | |||
636 | fclose(ifile); | ||
637 | } | ||
638 | |||
639 | static int | ||
640 | check_patch(patch_t **start_patch, int start_instr, | ||
641 | int *skip_addr, int *func_vals) | ||
642 | { | ||
643 | patch_t *cur_patch; | ||
644 | |||
645 | cur_patch = *start_patch; | ||
646 | |||
647 | while (cur_patch != NULL && start_instr == cur_patch->begin) { | ||
648 | if (func_vals[cur_patch->patch_func] == 0) { | ||
649 | int skip; | ||
650 | |||
651 | /* Start rejecting code */ | ||
652 | *skip_addr = start_instr + cur_patch->skip_instr; | ||
653 | for (skip = cur_patch->skip_patch; | ||
654 | skip > 0 && cur_patch != NULL; | ||
655 | skip--) | ||
656 | cur_patch = STAILQ_NEXT(cur_patch, links); | ||
657 | } else { | ||
658 | /* Accepted this patch. Advance to the next | ||
659 | * one and wait for our intruction pointer to | ||
660 | * hit this point. | ||
661 | */ | ||
662 | cur_patch = STAILQ_NEXT(cur_patch, links); | ||
663 | } | ||
664 | } | ||
665 | |||
666 | *start_patch = cur_patch; | ||
667 | if (start_instr < *skip_addr) | ||
668 | /* Still skipping */ | ||
669 | return (0); | ||
670 | |||
671 | return (1); | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * Print out error information if appropriate, and clean up before | ||
676 | * terminating the program. | ||
677 | */ | ||
678 | void | ||
679 | stop(const char *string, int err_code) | ||
680 | { | ||
681 | if (string != NULL) { | ||
682 | fprintf(stderr, "%s: ", appname); | ||
683 | if (yyfilename != NULL) { | ||
684 | fprintf(stderr, "Stopped at file %s, line %d - ", | ||
685 | yyfilename, yylineno); | ||
686 | } | ||
687 | fprintf(stderr, "%s\n", string); | ||
688 | } | ||
689 | |||
690 | if (ofile != NULL) { | ||
691 | fclose(ofile); | ||
692 | if (err_code != 0) { | ||
693 | fprintf(stderr, "%s: Removing %s due to error\n", | ||
694 | appname, ofilename); | ||
695 | unlink(ofilename); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | if (regfile != NULL) { | ||
700 | fclose(regfile); | ||
701 | if (err_code != 0) { | ||
702 | fprintf(stderr, "%s: Removing %s due to error\n", | ||
703 | appname, regfilename); | ||
704 | unlink(regfilename); | ||
705 | } | ||
706 | } | ||
707 | |||
708 | if (listfile != NULL) { | ||
709 | fclose(listfile); | ||
710 | if (err_code != 0) { | ||
711 | fprintf(stderr, "%s: Removing %s due to error\n", | ||
712 | appname, listfilename); | ||
713 | unlink(listfilename); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | symlist_free(&patch_functions); | ||
718 | symtable_close(); | ||
719 | |||
720 | exit(err_code); | ||
721 | } | ||
722 | |||
723 | struct instruction * | ||
724 | seq_alloc() | ||
725 | { | ||
726 | struct instruction *new_instr; | ||
727 | |||
728 | new_instr = (struct instruction *)malloc(sizeof(struct instruction)); | ||
729 | if (new_instr == NULL) | ||
730 | stop("Unable to malloc instruction object", EX_SOFTWARE); | ||
731 | memset(new_instr, 0, sizeof(*new_instr)); | ||
732 | STAILQ_INSERT_TAIL(&seq_program, new_instr, links); | ||
733 | new_instr->srcline = yylineno; | ||
734 | return new_instr; | ||
735 | } | ||
736 | |||
737 | critical_section_t * | ||
738 | cs_alloc() | ||
739 | { | ||
740 | critical_section_t *new_cs; | ||
741 | |||
742 | new_cs= (critical_section_t *)malloc(sizeof(critical_section_t)); | ||
743 | if (new_cs == NULL) | ||
744 | stop("Unable to malloc critical_section object", EX_SOFTWARE); | ||
745 | memset(new_cs, 0, sizeof(*new_cs)); | ||
746 | |||
747 | TAILQ_INSERT_TAIL(&cs_tailq, new_cs, links); | ||
748 | return new_cs; | ||
749 | } | ||
750 | |||
751 | scope_t * | ||
752 | scope_alloc() | ||
753 | { | ||
754 | scope_t *new_scope; | ||
755 | |||
756 | new_scope = (scope_t *)malloc(sizeof(scope_t)); | ||
757 | if (new_scope == NULL) | ||
758 | stop("Unable to malloc scope object", EX_SOFTWARE); | ||
759 | memset(new_scope, 0, sizeof(*new_scope)); | ||
760 | TAILQ_INIT(&new_scope->inner_scope); | ||
761 | |||
762 | if (SLIST_FIRST(&scope_stack) != NULL) { | ||
763 | TAILQ_INSERT_TAIL(&SLIST_FIRST(&scope_stack)->inner_scope, | ||
764 | new_scope, scope_links); | ||
765 | } | ||
766 | /* This patch is now the current scope */ | ||
767 | SLIST_INSERT_HEAD(&scope_stack, new_scope, scope_stack_links); | ||
768 | return new_scope; | ||
769 | } | ||
770 | |||
771 | void | ||
772 | process_scope(scope_t *scope) | ||
773 | { | ||
774 | /* | ||
775 | * We are "leaving" this scope. We should now have | ||
776 | * enough information to process the lists of scopes | ||
777 | * we encapsulate. | ||
778 | */ | ||
779 | scope_t *cur_scope; | ||
780 | u_int skip_patch_count; | ||
781 | u_int skip_instr_count; | ||
782 | |||
783 | cur_scope = TAILQ_LAST(&scope->inner_scope, scope_tailq); | ||
784 | skip_patch_count = 0; | ||
785 | skip_instr_count = 0; | ||
786 | while (cur_scope != NULL) { | ||
787 | u_int patch0_patch_skip; | ||
788 | |||
789 | patch0_patch_skip = 0; | ||
790 | switch (cur_scope->type) { | ||
791 | case SCOPE_IF: | ||
792 | case SCOPE_ELSE_IF: | ||
793 | if (skip_instr_count != 0) { | ||
794 | /* Create a tail patch */ | ||
795 | patch0_patch_skip++; | ||
796 | cur_scope->patches[1].skip_patch = | ||
797 | skip_patch_count + 1; | ||
798 | cur_scope->patches[1].skip_instr = | ||
799 | skip_instr_count; | ||
800 | } | ||
801 | |||
802 | /* Count Head patch */ | ||
803 | patch0_patch_skip++; | ||
804 | |||
805 | /* Count any patches contained in our inner scope */ | ||
806 | patch0_patch_skip += cur_scope->inner_scope_patches; | ||
807 | |||
808 | cur_scope->patches[0].skip_patch = patch0_patch_skip; | ||
809 | cur_scope->patches[0].skip_instr = | ||
810 | cur_scope->end_addr - cur_scope->begin_addr; | ||
811 | |||
812 | skip_instr_count += cur_scope->patches[0].skip_instr; | ||
813 | |||
814 | skip_patch_count += patch0_patch_skip; | ||
815 | if (cur_scope->type == SCOPE_IF) { | ||
816 | scope->inner_scope_patches += skip_patch_count; | ||
817 | skip_patch_count = 0; | ||
818 | skip_instr_count = 0; | ||
819 | } | ||
820 | break; | ||
821 | case SCOPE_ELSE: | ||
822 | /* Count any patches contained in our innter scope */ | ||
823 | skip_patch_count += cur_scope->inner_scope_patches; | ||
824 | |||
825 | skip_instr_count += cur_scope->end_addr | ||
826 | - cur_scope->begin_addr; | ||
827 | break; | ||
828 | case SCOPE_ROOT: | ||
829 | stop("Unexpected scope type encountered", EX_SOFTWARE); | ||
830 | /* NOTREACHED */ | ||
831 | } | ||
832 | |||
833 | cur_scope = TAILQ_PREV(cur_scope, scope_tailq, scope_links); | ||
834 | } | ||
835 | } | ||