Example #1
0
int main(int argc, char *argv[])
{
	char *fmt, *start;
	int fieldwidth, precision;
	char nextch;
	char *format;
	int ch;
	int error;

#if !defined(SHELL) && !defined(BUILTIN)
	(void)setlocale (LC_ALL, "");
#endif

	while ((ch = getopt(argc, argv, "")) != -1) {
		switch (ch) {
		case '?':
		default:
			usage();
			return 1;
		}
	}
	argc -= optind;
	argv += optind;

	if (argc < 1) {
		usage();
		return 1;
	}

	format = *argv;
	gargv = ++argv;

#define SKIP1	"#-+ 0"
#define SKIP2	"0123456789"
	do {
		/*
		 * Basic algorithm is to scan the format string for conversion
		 * specifications -- once one is found, find out if the field
		 * width or precision is a '*'; if it is, gather up value. 
		 * Note, format strings are reused as necessary to use up the
		 * provided arguments, arguments of zero/null string are 
		 * provided to use up the format string.
		 */

		/* find next format specification */
		for (fmt = format; (ch = *fmt++) != '\0';) {
			if (ch == '\\') {
				char c_ch;
				fmt = conv_escape(fmt, &c_ch);
				putchar(c_ch);
				continue;
			}
			if (ch != '%' || (*fmt == '%' && ++fmt)) {
				(void)putchar(ch);
				continue;
			}

			/* Ok - we've found a format specification,
			   Save its address for a later printf(). */
			start = fmt - 1;

			/* skip to field width */
			fmt += strspn(fmt, SKIP1);
			if (*fmt == '*') {
				fmt++;
				fieldwidth = getwidth();
			} else
				fieldwidth = -1;

			/* skip to possible '.', get following precision */
			fmt += strspn(fmt, SKIP2);
			if (*fmt == '.') {
				fmt++;
				if (*fmt == '*') {
					fmt++;
					precision = getwidth();
				} else
					precision = -1;
			} else
				precision = -1;

			fmt += strspn(fmt, SKIP2);

			ch = *fmt;
			if (!ch) {
				warnx("missing format character");
				return (1);
			}
			/* null terminate format string to we can use it
			   as an argument to printf. */
			nextch = fmt[1];
			fmt[1] = 0;
			switch (ch) {

			case 'B': {
				const char *p = conv_expand(getstr());
				if (p == NULL)
					goto out;
				*fmt = 's';
				PF(start, p);
				if (error < 0)
					goto out;
				break;
			}
			case 'b': {
				/* There has to be a better way to do this,
				 * but the string we generate might have
				 * embedded nulls. */
				static char *a, *t;
				char *cp = getstr();
				/* Free on entry in case shell longjumped out */
				if (a != NULL)
					free(a);
				a = NULL;
				if (t != NULL)
					free(t);
				t = NULL;
				/* Count number of bytes we want to output */
				b_length = 0;
				conv_escape_str(cp, b_count);
				t = malloc(b_length + 1);
				if (t == NULL)
					goto out;
				(void)memset(t, 'x', b_length);
				t[b_length] = 0;
				/* Get printf to calculate the lengths */
				*fmt = 's';
				abort();
/* APF(&a, start, t); */
				if (error == -1)
					goto out;
				b_fmt = a;
				/* Output leading spaces and data bytes */
				conv_escape_str(cp, b_output);
				/* Add any trailing spaces */
				printf("%s", b_fmt);
				break;
			}
			case 'c': {
				char p = getchr();
				PF(start, p);
				if (error < 0)
					goto out;
				break;
			}
			case 's': {
				char *p = getstr();
				PF(start, p);
				if (error < 0)
					goto out;
				break;
			}
			case 'd':
			case 'i': {
				intmax_t p = getintmax();
				char *f = mklong(start, ch);
				PF(f, p);
				if (error < 0)
					goto out;
				break;
			}
			case 'o':
			case 'u':
			case 'x':
			case 'X': {
				uintmax_t p = getuintmax();
				char *f = mklong(start, ch);
				PF(f, p);
				if (error < 0)
					goto out;
				break;
			}
			case 'e':
			case 'E':
			case 'f':
			case 'g':
			case 'G': {
				double p = getdouble();
				PF(start, p);
				if (error < 0)
					goto out;
				break;
			}
			default:
				warnx("%s: invalid directive", start);
				return 1;
			}
			*fmt++ = ch;
			*fmt = nextch;
			/* escape if a \c was encountered */
			if (rval & 0x100)
				return rval & ~0x100;
		}
	} while (gargv != argv && *gargv);

	return rval & ~0x100;
out:
	warn("print failed");
	return 1;
}
Example #2
0
int printfcmd(int argc, char *argv[])
{
	char *fmt;
	char *format;
	int ch;

	rval = 0;

	nextopt(nullstr);

	argv = argptr;
	format = *argv;

	if (!format) {
		warnx("usage: printf format [arg ...]");
		goto err;
	}

	gargv = ++argv;

#define SKIP1	"#-+ 0"
#define SKIP2	"*0123456789"
	do {
		/*
		 * Basic algorithm is to scan the format string for conversion
		 * specifications -- once one is found, find out if the field
		 * width or precision is a '*'; if it is, gather up value. 
		 * Note, format strings are reused as necessary to use up the
		 * provided arguments, arguments of zero/null string are 
		 * provided to use up the format string.
		 */

		/* find next format specification */
		for (fmt = format; (ch = *fmt++) ;) {
			char *start;
			char nextch;
			int array[2];
			int *param;

			if (ch == '\\') {
				int c_ch;
				fmt = conv_escape(fmt, &c_ch);
				ch = c_ch;
				goto pc;
			}
			if (ch != '%' || (*fmt == '%' && (++fmt || 1))) {
pc:
				blt_putchar(ch);
				continue;
			}

			/* Ok - we've found a format specification,
			   Save its address for a later blt_printf(). */
			start = fmt - 1;
			param = array;

			/* skip to field width */
			fmt += strspn(fmt, SKIP1);
			if (*fmt == '*')
				*param++ = getintmax();

			/* skip to possible '.', get following precision */
			fmt += strspn(fmt, SKIP2);
			if (*fmt == '.')
				++fmt;
			if (*fmt == '*')
				*param++ = getintmax();

			fmt += strspn(fmt, SKIP2);

			ch = *fmt;
			if (!ch) {
				warnx("missing format character");
				goto err;
			}
			/* null terminate format string to we can use it
			   as an argument to printf. */
			nextch = fmt[1];
			fmt[1] = 0;
			switch (ch) {

			case 'b': {
				int done = conv_escape_str(getstr());
				char *p = stackblock();
				*fmt = 's';
				PF(start, p);
				/* escape if a \c was encountered */
				if (done)
					goto out;
				*fmt = 'b';
				break;
			}
			case 'c': {
				int p = getchr();
				PF(start, p);
				break;
			}
			case 's': {
				char *p = getstr();
				PF(start, p);
				break;
			}
			case 'd':
			case 'i': {
				intmax_t p = getintmax();
				char *f = mklong(start, fmt);
				PF(f, p);
				break;
			}
			case 'o':
			case 'u':
			case 'x':
			case 'X': {
				uintmax_t p = getuintmax();
				char *f = mklong(start, fmt);
				PF(f, p);
				break;
			}
			case 'e':
			case 'E':
			case 'f':
			case 'g':
			case 'G': {
				double p = getdouble();
				PF(start, p);
				break;
			}
			default:
				warnx("%s: invalid directive", start);
				goto err;
			}
			*++fmt = nextch;
		}
	} while (gargv != argv && *gargv);

out:
	return rval;
err:
	return 1;
}
Example #3
0
main(int argc, char *argv[])
#endif
{
	char *fmt, *start;
	int fieldwidth, precision;
	char convch, nextch;
	char *format;

#if !defined(SHELL) && !defined(BUILTIN)
	setlocale (LC_ALL, "");
#endif

	/* Need to accept/ignore "--" option. */
	if (argc > 1 && strcmp(argv[1], "--") == 0) {
		argc--;
		argv++;
	}

	if (argc < 2) {
		usage();
		return (1);
	}

	format = *++argv;
	gargv = ++argv;

#define SKIP1	"#-+ 0"
#define SKIP2	"*0123456789"
	do {
		/*
		 * Basic algorithm is to scan the format string for conversion
		 * specifications -- once one is found, find out if the field
		 * width or precision is a '*'; if it is, gather up value. 
		 * Note, format strings are reused as necessary to use up the
		 * provided arguments, arguments of zero/null string are 
		 * provided to use up the format string.
		 */

		/* find next format specification */
		for (fmt = format; *fmt; fmt++) {
			switch (*fmt) {
			case '%':
				start = fmt++;

				if (*fmt == '%') {
					putchar ('%');
					break;
				} else if (*fmt == 'b') {
					char *p = getstr();
					if (print_escape_str(p)) {
						return (rval);
					}
					break;
				}

				/* skip to field width */
				for (; strchr(SKIP1, *fmt); ++fmt) ;
				fieldwidth = *fmt == '*' ? getint() : 0;

				/* skip to possible '.', get following precision */
				for (; strchr(SKIP2, *fmt); ++fmt) ;
				if (*fmt == '.')
					++fmt;
				precision = *fmt == '*' ? getint() : 0;

				for (; strchr(SKIP2, *fmt); ++fmt) ;
				if (!*fmt) {
					warnx ("missing format character");
					return(1);
				}

				convch = *fmt;
				nextch = *(fmt + 1);
				*(fmt + 1) = '\0';
				switch(convch) {
				case 'c': {
					char p = getchr();
					PF(start, p);
					break;
				}
				case 's': {
					char *p = getstr();
					PF(start, p);
					break;
				}
				case 'd':
				case 'i': {
					long p;
					char *f = mklong(start, convch);
					if (!f) {
						warnx("out of memory");
						return (1);
					}
					p = getlong();
					PF(f, p);
					break;
				}
				case 'o':
				case 'u':
				case 'x':
				case 'X': {
					unsigned long p;
					char *f = mklong(start, convch);
					if (!f) {
						warnx("out of memory");
						return (1);
					}
					p = getulong();
					PF(f, p);
					break;
				}
				case 'e':
				case 'E':
				case 'f':
				case 'g':
				case 'G': {
					double p = getdouble();
					PF(start, p);
					break;
				}
				default:
					warnx ("%s: invalid directive", start);
					return(1);
				}
				*(fmt + 1) = nextch;
				break;

			case '\\':
				fmt += print_escape(fmt);
				break;

			default:
				putchar (*fmt);
				break;
			}
		}
	} while (gargv > argv && *gargv);

	return (rval);
}