Esempio n. 1
0
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");
   }
}
Esempio n. 2
0
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);
}