Importing usr.bin/expand

Change-Id: I4089d86d4ae1dcade0c82ed30ecd5685802acfd3
This commit is contained in:
Lionel Sambuc 2013-08-23 23:51:18 +02:00
parent 0b8a9e801d
commit 563dd2c8f4
10 changed files with 284 additions and 142 deletions

View File

@ -8,7 +8,7 @@ SUBDIR= add_route arp ash at backup btrace \
comm compress cp crc cron crontab cut \
dd decomp16 DESCRIBE devmand devsize df dhcpd \
dhrystone diff diskctl dumpcore \
eject env expand factor fbdctl \
eject env factor fbdctl \
find fix fold format fortune fsck.mfs \
gcore gcov-pull getty grep hexdump host \
hostaddr id ifconfig ifdef \

View File

@ -1,4 +0,0 @@
PROG= expand
MAN=
.include <bsd.prog.mk>

View File

@ -1,99 +0,0 @@
/* expand - expand tabs to spaces Author: Terrence W. Holm */
/* Usage: expand [ -tab1,tab2,tab3,... ] [ file ... ] */
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_TABS 32
int column = 0; /* Current column, retained between files */
int main(int argc, char **argv);
void Expand(FILE *f, int tab_index, int tabs []);
int main(argc, argv)
int argc;
char *argv[];
{
int tabs[MAX_TABS];
int tab_index = 0; /* Default one tab */
int i;
FILE *f;
tabs[0] = 8; /* Default tab stop */
if (argc > 1 && argv[1][0] == '-') {
char *p = argv[1];
int last_tab_stop = 0;
for (tab_index = 0; tab_index < MAX_TABS; ++tab_index) {
if ((tabs[tab_index] = atoi(p + 1)) <= last_tab_stop) {
fprintf(stderr, "Bad tab stop spec\n");
exit(1);
}
last_tab_stop = tabs[tab_index];
if ((p = strchr(p + 1, ',')) == NULL) break;
}
--argc;
++argv;
}
if (argc == 1)
Expand(stdin, tab_index, tabs);
else
for (i = 1; i < argc; ++i) {
if ((f = fopen(argv[i], "r")) == NULL) {
perror(argv[i]);
exit(1);
}
Expand(f, tab_index, tabs);
fclose(f);
}
return(0);
}
void Expand(f, tab_index, tabs)
FILE *f;
int tab_index;
int tabs[];
{
int next;
int c;
int i;
while ((c = getc(f)) != EOF) {
if (c == '\t') {
if (tab_index == 0)
next = (column / tabs[0] + 1) * tabs[0];
else {
for (i = 0; i <= tab_index && tabs[i] <= column; ++i);
if (i > tab_index)
next = column + 1;
else
next = tabs[i];
}
do {
++column;
putchar(' ');
} while (column < next);
continue;
}
if (c == '\b')
column = column > 0 ? column - 1 : 0;
else if (c == '\n' || c == '\r')
column = 0;
else
++column;
putchar(c);
}
}

View File

@ -4,7 +4,7 @@ MAN= ash.1 at.1 \
cp.1 crc.1 crontab.1 dd.1 \
df.1 dhrystone.1 dosdir.1 dosread.1 doswrite.1 \
dumpcore.1 eject.1 \
env.1 expand.1 factor.1 \
env.1 factor.1 \
flexdoc.1 fold.1 format.1 fortune.1 \
fsck.mfs.1 host.1 hostaddr.1 ifdef.1 \
isodir.1 isoinfo.1 isoread.1 \

View File

@ -1,32 +0,0 @@
.TH EXPAND 1
.SH NAME
expand \- convert tabs to spaces
.SH SYNOPSIS
\fBexpand\fR [\fB\-\fIt1,t2, ...\fR]\fR [\fIfile\fR]\fR
.br
.de FL
.TP
\\fB\\$1\\fR
\\$2
..
.de EX
.TP 20
\\fB\\$1\\fR
# \\$2
..
.SH OPTIONS
.TP 5
.B \-\fIt\fR
# Tab stop positions
.SH EXAMPLES
.TP 20
.B expand \-16,32,48,64
# Expand \fIstdin\fR with tabs every 16 columns
.SH DESCRIPTION
.PP
\fIExpand\fR replaces tabs in the named files with the equivalent numbers
of spaces. If no files are listed, \fIstdin\fR is given. If only one
tab is given, the rest are multiples of it. The default is a tab every 8
spaces.
.SH "SEE ALSO"
.BR unexpand (1).

View File

@ -154,6 +154,7 @@
2012/10/17 12:00:00,usr.bin/ctags
2012/10/17 12:00:00,usr.bin/dirname
2011/09/01 13:37:33,usr.bin/du
2012/10/17 12:00:00,usr.bin/expand
2013/05/31 12:00:00,usr.bin/finger
2013/03/22 12:00:00,usr.bin/from
2013/04/05 12:00:00,usr.bin/ftp

View File

@ -9,10 +9,10 @@ SUBDIR= \
cal chpass cksum \
col ctags \
dirname du \
finger \
from ftp \
genassym getopt head \
indent infocmp join \
expand \
finger from \
ftp genassym getopt \
head indent infocmp join \
ldd \
login logname lorder m4 \
make man \
@ -30,7 +30,6 @@ SUBDIR= \
toproto \
uniq \
\
\
wc whatis who \
xinstall yes

7
usr.bin/expand/Makefile Normal file
View File

@ -0,0 +1,7 @@
# @(#)Makefile 8.1 (Berkeley) 6/9/93
# $NetBSD: Makefile,v 1.5 2009/04/14 22:15:19 lukem Exp $
PROG= expand
MLINKS= expand.1 unexpand.1
.include <bsd.prog.mk>

87
usr.bin/expand/expand.1 Normal file
View File

@ -0,0 +1,87 @@
.\" $NetBSD: expand.1,v 1.12 2012/05/12 14:52:57 reed Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)expand.1 8.1 (Berkeley) 6/9/93
.\"
.Dd December 20, 2008
.Dt EXPAND 1
.Os
.Sh NAME
.Nm expand ,
.Nm unexpand
.Nd expand tabs to spaces, and vice versa
.Sh SYNOPSIS
.Nm
.Op Fl t Ar tabstop
.Op Fl t Ar tab1,tab2,...,tabn
.Op Ar
.Nm unexpand
.Op Fl a
.Op Fl t Ar tab1,tab2,...,tabn
.Op Ar
.Sh DESCRIPTION
.Nm
processes the named files or the standard input writing
the standard output with tabs changed into blanks.
Backspace characters are preserved into the output and decrement
the column count for tab calculations.
.Nm
is useful for pre-processing character files
(before sorting, looking at specific columns, etc.) that
contain tabs.
.Pp
If a single
.Ar tabstop
argument is given, then tabs are set
.Ar tabstop
spaces apart instead of the default 8.
If multiple tabstops are given then the tabs are set at those
specific columns.
.Pp
.Nm unexpand
puts tabs back into the data from the standard input or the named
files and writes the result on the standard output.
.Pp
Option (with
.Nm unexpand
only):
.Bl -tag -width flag
.It Fl a
By default, only leading blanks and tabs
are reconverted to maximal strings of tabs.
If the
.Fl a
option is given, then tabs are inserted whenever they would compress the
resultant file by replacing two or more characters.
.El
.Sh HISTORY
The
.Nm
command appeared in
.Bx 1 .

183
usr.bin/expand/expand.c Normal file
View File

@ -0,0 +1,183 @@
/* $NetBSD: expand.c,v 1.13 2009/04/12 02:51:36 lukem Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93";
#endif
__RCSID("$NetBSD: expand.c,v 1.13 2009/04/12 02:51:36 lukem Exp $");
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <err.h>
/*
* expand - expand tabs to equivalent spaces
*/
size_t nstops;
size_t tabstops[100];
static void getstops(const char *);
int main(int, char **);
static void usage(void) __dead;
int
main(int argc, char *argv[])
{
int c;
size_t n, column;
setprogname(argv[0]);
/* handle obsolete syntax */
while (argc > 1 &&
argv[1][0] == '-' && isdigit((unsigned char)argv[1][1])) {
getstops(&argv[1][1]);
argc--; argv++;
}
while ((c = getopt (argc, argv, "t:")) != -1) {
switch (c) {
case 't':
getstops(optarg);
break;
case '?':
default:
usage();
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
do {
if (argc > 0) {
if (freopen(argv[0], "r", stdin) == NULL)
err(EXIT_FAILURE, "Cannot open `%s'", argv[0]);
argc--, argv++;
}
column = 0;
while ((c = getchar()) != EOF) {
switch (c) {
case '\t':
if (nstops == 0) {
do {
putchar(' ');
column++;
} while (column & 07);
continue;
}
if (nstops == 1) {
do {
putchar(' ');
column++;
} while (((column - 1) % tabstops[0])
!= (tabstops[0] - 1));
continue;
}
for (n = 0; n < nstops; n++)
if (tabstops[n] > column)
break;
if (n == nstops) {
putchar(' ');
column++;
continue;
}
while (column < tabstops[n]) {
putchar(' ');
column++;
}
continue;
case '\b':
if (column)
column--;
putchar('\b');
continue;
default:
putchar(c);
column++;
continue;
case '\n':
putchar(c);
column = 0;
continue;
}
}
} while (argc > 0);
return EXIT_SUCCESS;
}
static void
getstops(const char *spec)
{
int i;
const char *cp = spec;
nstops = 0;
for (;;) {
i = 0;
while (*cp >= '0' && *cp <= '9')
i = i * 10 + *cp++ - '0';
if (i <= 0 || i > 256)
errx(EXIT_FAILURE, "Too large tab stop spec `%d'", i);
if (nstops > 0 && (size_t)i <= tabstops[nstops-1])
errx(EXIT_FAILURE, "Out of order tabstop spec `%d'", i);
if (nstops == sizeof(tabstops) / sizeof(tabstops[0]) - 1)
errx(EXIT_FAILURE, "Too many tabstops");
tabstops[nstops++] = i;
if (*cp == '\0')
break;
if (*cp != ',' && *cp != ' ')
errx(EXIT_FAILURE, "Illegal tab stop spec `%s'", spec);
cp++;
}
}
static void
usage(void)
{
(void)fprintf(stderr, "Usage: %s [-t tablist] [file ...]\n",
getprogname());
exit(EXIT_FAILURE);
}