summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-11-19 12:56:13 +0000
committerjilles <jilles@FreeBSD.org>2010-11-19 12:56:13 +0000
commit129853101d5707b7d18f28f39e748fa65a36add2 (patch)
treebf15bc2b264e5ca2469d76c04865a14c1e99127c
parent7be275d6a786ef414ab769fb1b61fa9a4b041f4d (diff)
downloadFreeBSD-src-129853101d5707b7d18f28f39e748fa65a36add2.zip
FreeBSD-src-129853101d5707b7d18f28f39e748fa65a36add2.tar.gz
sh: Add printf builtin.
This was removed in 2001 but I think it is appropriate to add it back: * I do not want to encourage people to write fragile and non-portable echo commands by making printf much slower than echo. * Recent versions of Autoconf use it a lot. * Almost no software still wants to support systems that do not have printf(1) at all. * In many other shells printf is already a builtin. Side effect: printf is now always the builtin version (which behaves identically to /usr/bin/printf) and cannot be overridden via PATH (except via the undocumented %builtin mechanism). Code size increases about 5K on i386. Embedded folks might want to replace /usr/bin/printf with a hard link to /usr/bin/alias.
-rw-r--r--bin/sh/Makefile5
-rw-r--r--bin/sh/builtins.def2
-rw-r--r--bin/sh/sh.16
-rw-r--r--share/man/man1/builtin.15
-rw-r--r--usr.bin/printf/printf.111
-rw-r--r--usr.bin/printf/printf.c30
6 files changed, 47 insertions, 12 deletions
diff --git a/bin/sh/Makefile b/bin/sh/Makefile
index 1b0738b..a606c9b 100644
--- a/bin/sh/Makefile
+++ b/bin/sh/Makefile
@@ -5,7 +5,7 @@ PROG= sh
INSTALLFLAGS= -S
SHSRCS= alias.c arith.y arith_lex.l cd.c echo.c error.c eval.c exec.c expand.c \
histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
- mystring.c options.c output.c parser.c redir.c show.c \
+ mystring.c options.c output.c parser.c printf.c redir.c show.c \
test.c trap.c var.c
GENSRCS= builtins.c init.c nodes.c syntax.c
GENHDRS= builtins.h nodes.h syntax.h token.h
@@ -26,7 +26,8 @@ WARNS?= 2
WFORMAT=0
.PATH: ${.CURDIR}/bltin \
- ${.CURDIR}/../test
+ ${.CURDIR}/../test \
+ ${.CURDIR}/../../usr.bin/printf
CLEANFILES+= mkinit mkinit.o mknodes mknodes.o \
mksyntax mksyntax.o
diff --git a/bin/sh/builtins.def b/bin/sh/builtins.def
index 75f83b5..b72f887 100644
--- a/bin/sh/builtins.def
+++ b/bin/sh/builtins.def
@@ -71,7 +71,7 @@ histcmd -h fc
jobidcmd jobid
jobscmd jobs
localcmd local
-#printfcmd printf
+printfcmd printf
pwdcmd pwd
readcmd read
returncmd -s return
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 7b1eb61..ba06a0c 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd November 12, 2010
+.Dd November 19, 2010
.Dt SH 1
.Os
.Sh NAME
@@ -2049,6 +2049,9 @@ line.
See the
.Sx Functions
subsection.
+.It Ic printf
+A built-in equivalent of
+.Xr printf 1 .
.It Ic pwd Op Fl L | P
Print the path of the current directory.
The built-in command may
@@ -2470,6 +2473,7 @@ will return the argument.
.Xr echo 1 ,
.Xr ed 1 ,
.Xr emacs 1 ,
+.Xr printf 1 ,
.Xr pwd 1 ,
.Xr test 1 ,
.Xr vi 1 ,
diff --git a/share/man/man1/builtin.1 b/share/man/man1/builtin.1
index cbfc873..5a6b5ae 100644
--- a/share/man/man1/builtin.1
+++ b/share/man/man1/builtin.1
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 9, 2010
+.Dd November 19, 2010
.Dt BUILTIN 1
.Os
.Sh NAME
@@ -99,6 +99,7 @@
.Nm onintr ,
.Nm popd ,
.Nm printenv ,
+.Nm printf ,
.Nm pushd ,
.Nm pwd ,
.Nm read ,
@@ -263,6 +264,7 @@ but are implemented as scripts using a builtin command of the same name.
.It Ic onintr Ta \&No Ta Yes Ta \&No
.It Ic popd Ta \&No Ta Yes Ta \&No
.It Ic printenv Ta Yes Ta Yes Ta \&No
+.It Ic printf Ta Yes Ta \&No Ta Yes
.It Ic pushd Ta \&No Ta Yes Ta \&No
.It Ic pwd Ta Yes Ta \&No Ta Yes
.It Ic read Ta No** Ta \&No Ta Yes
@@ -313,6 +315,7 @@ but are implemented as scripts using a builtin command of the same name.
.Xr nice 1 ,
.Xr nohup 1 ,
.Xr printenv 1 ,
+.Xr printf 1 ,
.Xr pwd 1 ,
.Xr sh 1 ,
.Xr test 1 ,
diff --git a/usr.bin/printf/printf.1 b/usr.bin/printf/printf.1
index 6caea65..6008b68 100644
--- a/usr.bin/printf/printf.1
+++ b/usr.bin/printf/printf.1
@@ -35,7 +35,7 @@
.\" @(#)printf.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd September 5, 2010
+.Dd November 19, 2010
.Dt PRINTF 1
.Os
.Sh NAME
@@ -306,6 +306,13 @@ character is defined in the program's locale (category
In no case does a non-existent or small field width cause truncation of
a field; padding takes place only if the specified field width exceeds
the actual width.
+.Pp
+Some shells may provide a builtin
+.Nm
+command which is similar or identical to this utility.
+Consult the
+.Xr builtin 1
+manual page.
.Sh EXIT STATUS
.Ex -std
.Sh COMPATIBILITY
@@ -316,7 +323,9 @@ with a digit to the
.Tn ASCII
code of the first character is not supported.
.Sh SEE ALSO
+.Xr builtin 1 ,
.Xr echo 1 ,
+.Xr sh 1 ,
.Xr printf 3
.Sh STANDARDS
The
diff --git a/usr.bin/printf/printf.c b/usr.bin/printf/printf.c
index 5e7a935..4ac23c6 100644
--- a/usr.bin/printf/printf.c
+++ b/usr.bin/printf/printf.c
@@ -62,6 +62,7 @@ static const char rcsid[] =
#define main printfcmd
#include "bltin/bltin.h"
#include "memalloc.h"
+#include "error.h"
#else
#define warnx1(a, b, c) warnx(a)
#define warnx2(a, b, c) warnx(a, b)
@@ -90,7 +91,7 @@ static const char rcsid[] =
} while (0)
static int asciicode(void);
-static char *doformat(char *, int *);
+static char *printf_doformat(char *, int *);
static int escape(char *, int, size_t *);
static int getchr(void);
static int getfloating(long double *, int);
@@ -114,9 +115,12 @@ main(int argc, char *argv[])
int ch, chopped, end, rval;
char *format, *fmt, *start;
-#ifndef BUILTIN
+#if !defined(BUILTIN) && !defined(SHELL)
(void) setlocale(LC_NUMERIC, "");
#endif
+#ifdef SHELL
+ optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
+#endif
while ((ch = getopt(argc, argv, "")) != -1)
switch (ch) {
case '?':
@@ -132,6 +136,9 @@ main(int argc, char *argv[])
return (1);
}
+#ifdef SHELL
+ INTOFF;
+#endif
/*
* Basic algorithm is to scan the format string for conversion
* specifications -- once one is found, find out if the field
@@ -154,9 +161,13 @@ main(int argc, char *argv[])
putchar('%');
fmt += 2;
} else {
- fmt = doformat(fmt, &rval);
- if (fmt == NULL)
+ fmt = printf_doformat(fmt, &rval);
+ if (fmt == NULL) {
+#ifdef SHELL
+ INTON;
+#endif
return (1);
+ }
end = 0;
}
start = fmt;
@@ -166,11 +177,18 @@ main(int argc, char *argv[])
if (end == 1) {
warnx1("missing format character", NULL, NULL);
+#ifdef SHELL
+ INTON;
+#endif
return (1);
}
fwrite(start, 1, fmt - start, stdout);
- if (chopped || !*gargv)
+ if (chopped || !*gargv) {
+#ifdef SHELL
+ INTON;
+#endif
return (rval);
+ }
/* Restart at the beginning of the format string. */
fmt = format;
end = 1;
@@ -180,7 +198,7 @@ main(int argc, char *argv[])
static char *
-doformat(char *start, int *rval)
+printf_doformat(char *start, int *rval)
{
static const char skip1[] = "#'-+ 0";
static const char skip2[] = "0123456789";
OpenPOWER on IntegriCloud