static void dump_node (FILE* outfile, astree* node) { // Remove TOK prefix. char* tname = (char*) get_yytname(node->symbol); if (strstr(tname, "TOK_")) tname += 4; attr_bitset attr = node_attrs(node); // Output tree node. fprintf(outfile, "%s \"%s\" %zu.%zu.%zu {%zu} %s", tname, node->lexinfo->c_str(), node->filenr, node->linenr, node->offset, node->block_nr, do_type_string(attr, node->type_str).c_str()); if (node->sym and node->sym->node != node) { fprintf(outfile, "(%ld.%ld.%ld)\n", node->sym->filenr, node->sym->linenr, node->sym->offset); } else { fprintf(outfile, "\n"); } }
int main(int argc, char **argv) { int c; int i; buffer_t buffer; boolean_t first = B_TRUE; boolean_t doall = B_FALSE; boolean_t same = B_FALSE; boolean_t newarg = B_FALSE; off_t offset = 0; off_t skip = 0; char *eptr; char *offstr = 0; input = stdin; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); while ((c = getopt(argc, argv, "A:bCcdDfFj:N:oOsSxXvt:")) != EOF) { switch (c) { case 'A': newarg = B_TRUE; if (strlen(optarg) > 1) { afmt = NULL; } switch (*optarg) { case 'o': afmt = "%07llo"; cfmt = " "; break; case 'd': afmt = "%07lld"; cfmt = " "; break; case 'x': afmt = "%07llx"; cfmt = " "; break; case 'n': /* * You could argue that the code should * use the same 7 spaces. Legacy uses 8 * though. Oh well. Better to avoid * gratuitous change. */ afmt = " "; cfmt = " "; break; default: afmt = NULL; break; } if (strlen(optarg) != 1) { afmt = NULL; } if (afmt == NULL) warnx(_("invalid address base, " "must be o, d, x, or n")); break; case 'b': add_out(&output_oct_b); break; case 'c': case 'C': add_out(&output_char); break; case 'f': add_out(&output_float); break; case 'F': add_out(&output_double); break; case 'd': add_out(&output_dec_w); break; case 'D': add_out(&output_dec_d); break; case 't': newarg = B_TRUE; do_type_string(optarg); break; case 'o': add_out(&output_oct_w); break; case 'O': add_out(&output_oct_d); break; case 's': add_out(&output_sig_w); break; case 'S': add_out(&output_sig_d); break; case 'x': add_out(&output_hex_w); break; case 'X': add_out(&output_hex_d); break; case 'v': doall = B_TRUE; break; case 'j': newarg = B_TRUE; skip = strtoll(optarg, &eptr, 0); if (*eptr == 'b') { skip <<= 9; /* 512 bytes */ eptr++; } else if (*eptr == 'k') { skip <<= 10; /* 1k */ eptr++; } else if (*eptr == 'm') { skip <<= 20; /* 1m */ eptr++; } else if (*eptr == 'g') { skip <<= 30; /* 1g */ eptr++; } if ((skip < 0) || (eptr[0] != 0)) { warnx(_("invalid skip count '%s' specified"), optarg); exit(1); } break; case 'N': newarg = B_TRUE; limit = strtoll(optarg, &eptr, 0); /* * POSIX doesn't specify this, but I think these * may be helpful. */ if (*eptr == 'b') { limit <<= 9; eptr++; } else if (*eptr == 'k') { limit <<= 10; eptr++; } else if (*eptr == 'm') { limit <<= 20; eptr++; } else if (*eptr == 'g') { limit <<= 30; eptr++; } if ((limit < 0) || (eptr[0] != 0)) { warnx(_("invalid byte count '%s' specified"), optarg); exit(1); } break; default: usage(); break; } } /* this finds the smallest power of two size we can use */ buffer.mask = (1 << (ffs(blocksize * 3) + 1)) - 1; buffer.data = memalign(16, buffer.mask + 1); if (buffer.data == NULL) { err(1, "memalign"); } /* * Wow. This option parsing is hideous. * * If the we've not seen a new option, and there is just one * operand, if it starts with a "+", then treat it as an * offset. Otherwise if two operands, and the second operand * starts with + or a digit, then it is an offset. */ if (!newarg) { if (((argc - optind) == 1) && (argv[optind][0] == '+')) { offstr = argv[optind]; argc--; } else if (((argc - optind) == 2) && (strchr("+0123456789", (argv[optind + 1][0])) != NULL)) { offstr = argv[optind + 1]; argc--; } } if (offstr) { int base = 0; int mult = 1; int l; if (*offstr == '+') { offstr++; } l = strlen(offstr); if ((strncmp(offstr, "0x", 2) == 0)) { afmt = "%07llx"; base = 16; offstr += 2; if (offstr[l - 1] == 'B') { offstr[l - 1] = 0; l--; mult = 512; } } else { base = 8; afmt = "%07llo"; if ((offstr[l - 1] == 'B') || (offstr[l - 1] == 'b')) { offstr[l - 1] = 0; l--; mult = 512; } if (offstr[l - 1] == '.') { offstr[l - 1] = 0; base = 10; afmt = "%07lld"; } } skip = strtoll(offstr, &eptr, base); if (*eptr != '\0') { errx(1, _("invalid offset string specified")); } skip *= mult; offset += skip; } /* * Allocate an array for all the input files. */ if (argc > optind) { files = calloc(sizeof (char *), argc - optind); for (i = 0; i < argc - optind; i++) { files[i] = argv[optind + i]; numfiles++; } input = next_input(); } else { input = stdin; } /* * We need to seek ahead. fseek would be faster. */ while (skip && (input != NULL)) { struct stat sbuf; /* * Only fseek() on regular files. (Others * we have to read(). */ if (fstat(fileno(input), &sbuf) < 0) { warn("fstat: %s", files[curfile-1]); input = next_input(); continue; } if (S_ISREG(sbuf.st_mode)) { /* * No point in seeking a file that is too * short to begin with. */ if (sbuf.st_size < skip) { skip -= sbuf.st_size; input = next_input(); continue; } if (fseeko(input, skip, SEEK_SET) < 0) { err(1, "fseek:%s", files[curfile-1]); } /* Done seeking. */ skip = 0; break; } /* * fgetc seems like it would be slow, but it uses * buffered I/O, so it should be fast enough. */ flockfile(input); while (skip) { if (getc_unlocked(input) == EOF) { funlockfile(input); if (ferror(input)) { warn("read: %s", files[curfile-1]); } input = next_input(); if (input != NULL) { flockfile(input); } break; } skip--; } if (input != NULL) funlockfile(input); } if (head == NULL) { add_out(&output_oct_w); } buffer.navail = 0; buffer.prod = 0; buffer.cons = 0; for (refill(&buffer); buffer.navail > 0; refill(&buffer)) { output_t *out; int mx; int j, k; /* * If this buffer was the same as last, then just * dump an asterisk. */ if ((!first) && (buffer.navail >= blocksize) && (!doall)) { j = buffer.cons; k = j - blocksize; for (i = 0; i < blocksize; i++) { if (buffer.data[j & buffer.mask] != buffer.data[k & buffer.mask]) { break; } j++; k++; } if (i == blocksize) { if (!same) { (void) fputs("*\n", stdout); same = B_TRUE; } buffer.navail -= blocksize; offset += blocksize; buffer.cons += blocksize; buffer.cons &= buffer.mask; continue; } } first = B_FALSE; same = B_FALSE; mx = (buffer.navail > blocksize) ? blocksize : buffer.navail; for (out = head; out != NULL; out = out->next) { if (out == head) { /*LINTED E_SEC_PRINTF_VAR_FMT*/ (void) printf(afmt, offset); } else { (void) fputs(cfmt, stdout); } for (i = 0, j = buffer.cons; i < mx; i += out->width) { out->func(&buffer, j); j += out->width; j &= buffer.mask; } (void) fputs("\n", stdout); } buffer.cons += mx; buffer.cons &= buffer.mask; offset += mx; buffer.navail -= mx; } /*LINTED E_SEC_PRINTF_VAR_FMT*/ (void) printf(afmt, offset); (void) fputs("\n", stdout); return (0); }