diff --git a/commands/Makefile b/commands/Makefile index 9bbf621d8..d8362e4f7 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -27,7 +27,7 @@ SUBDIR= add_route arp ash at backup btrace \ stty svclog svrctl swifi synctree sysenv \ syslogd tail tcpd tcpdp tcpstat tee telnet \ telnetd term termcap tget time touch tr \ - truncate tty udpstat umount uname unexpand \ + truncate tty udpstat umount uname \ unstack update uud uue version vol \ whereis which write writeisofs fetch \ xargs zdump zmodem pkgin_cd pkgin_all \ diff --git a/commands/unexpand/Makefile b/commands/unexpand/Makefile deleted file mode 100644 index ef5cf3045..000000000 --- a/commands/unexpand/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -PROG= unexpand -MAN= - -.include diff --git a/commands/unexpand/unexpand.c b/commands/unexpand/unexpand.c deleted file mode 100644 index 786020346..000000000 --- a/commands/unexpand/unexpand.c +++ /dev/null @@ -1,121 +0,0 @@ -/* unexpand - convert spaces to tabs Author: Terrence W. Holm */ - -/* Usage: unexpand [ -a ] [ file ... ] */ - -#include -#include -#include - -#define TAB 8 - - -int column = 0; /* Current column, retained between files */ -int spaces = 0; /* Spaces since last tab stop */ -int leading_blank = 1; /* Only unexpand leading blanks, */ -/* Overruled by -a option */ - -int main(int argc, char **argv); -void Unexpand(FILE *f, int all); - -int main(argc, argv) -int argc; -char *argv[]; - -{ - int all = 0; /* -a flag means unexpand all spaces */ - int i; - FILE *f; - - if (argc > 1 && argv[1][0] == '-') { - if (strcmp(argv[1], "-a") == 0) - all = 1; - else { - fprintf(stderr, "Usage: unexpand [ -a ] [ file ... ]\n"); - exit(1); - } - - --argc; - ++argv; - } - if (argc == 1) - Unexpand(stdin, all); - else - for (i = 1; i < argc; ++i) { - if ((f = fopen(argv[i], "r")) == NULL) { - perror(argv[i]); - exit(1); - } - Unexpand(f, all); - fclose(f); - } - - - /* If there are pending spaces print them. */ - - while (spaces > 0) { - putchar(' '); - --spaces; - } - - return(0); -} - -void Unexpand(f, all) -FILE *f; -int all; - -{ - int c; - - while ((c = getc(f)) != EOF) { - if (c == ' ' && (all || leading_blank)) { - ++column; - ++spaces; - - /* If we have white space up to a tab stop, then output */ - /* A tab. If only one space is required, use a ' '. */ - - if (column % TAB == 0) { - if (spaces == 1) - putchar(' '); - else - putchar('\t'); - - spaces = 0; - } - continue; - } - - /* If a tab character is encountered in the input then */ - /* Simply echo it. Any accumulated spaces can only be */ - /* Since the last tab stop, so ignore them. */ - if (c == '\t') { - column = (column / TAB + 1) * TAB; - spaces = 0; - putchar('\t'); - continue; - } - - /* A non-space character is to be printed. If there */ - /* Are pending spaces, then print them. There will be */ - /* At most TAB-1 spaces to print. */ - while (spaces > 0) { - putchar(' '); - --spaces; - } - - if (c == '\n' || c == '\r') { - column = 0; - leading_blank = 1; - putchar(c); - continue; - } - if (c == '\b') - column = column > 0 ? column - 1 : 0; - else - ++column; - - leading_blank = 0; - putchar(c); - } -} diff --git a/man/man1/Makefile b/man/man1/Makefile index c3ac89157..206158ae0 100644 --- a/man/man1/Makefile +++ b/man/man1/Makefile @@ -19,7 +19,7 @@ MAN= ash.1 at.1 \ split.1 stty.1 svc.1 svrctl.1 \ synctree.1 sysenv.1 sz.1 tail.1 tee.1 telnet.1 template.1 \ term.1 termcap.1 tget.1 time.1 tr.1 true.1 \ - truncate.1 tty.1 umount.1 uname.1 unexpand.1 \ + truncate.1 tty.1 umount.1 uname.1 \ uud.1 uue.1 vol.1 whereis.1 which.1 \ write.1 xargs.1 yap.1 linkfarm.1 pkg_view.1 diff --git a/man/man1/unexpand.1 b/man/man1/unexpand.1 deleted file mode 100644 index 8751b7c2a..000000000 --- a/man/man1/unexpand.1 +++ /dev/null @@ -1,32 +0,0 @@ -.TH UNEXPAND 1 -.SH NAME -unexpand \- convert spaces to tabs -.SH SYNOPSIS -\fBunexpand\fR [\fB\-a\fR]\fR -.br -.de FL -.TP -\\fB\\$1\\fR -\\$2 -.. -.de EX -.TP 20 -\\fB\\$1\\fR -# \\$2 -.. -.SH OPTIONS -.TP 5 -.B \-a -# All spaces are unexpanded -.SH EXAMPLES -.TP 20 -.B unexpand oldfile >newfile -# Convert leading spaces to tabs -.SH DESCRIPTION -.PP -\fIUnexpand\fR replaces spaces in the named files with tabs. -If no files are listed, \fIstdin\fR is given. -The \fB\-a\fR flag is used to force all sequences of spaces to be -expanded, instead of just leading spaces (the default). -.SH "SEE ALSO" -.BR expand (1). diff --git a/usr.bin/Makefile b/usr.bin/Makefile index b92601186..9eb86975e 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -26,7 +26,7 @@ SUBDIR= \ shuffle sed seq \ sort stat su \ tic tput \ - tsort \ + tsort unexpand \ toproto \ uniq \ \ diff --git a/usr.bin/unexpand/Makefile b/usr.bin/unexpand/Makefile new file mode 100644 index 000000000..427252c49 --- /dev/null +++ b/usr.bin/unexpand/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.8 2009/04/14 22:15:28 lukem Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +NOMAN= # defined + +PROG= unexpand +LDADD+=-lutil +DPADD+=${LIBUTIL} + +.include diff --git a/usr.bin/unexpand/unexpand.c b/usr.bin/unexpand/unexpand.c new file mode 100644 index 000000000..3b41974a0 --- /dev/null +++ b/usr.bin/unexpand/unexpand.c @@ -0,0 +1,218 @@ +/* $NetBSD: unexpand.c,v 1.14 2008/12/21 02:33:13 christos 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 +#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[] = "@(#)unexpand.c 8.1 (Berkeley) 6/6/93"; +#endif +__RCSID("$NetBSD: unexpand.c,v 1.14 2008/12/21 02:33:13 christos Exp $"); +#endif /* not lint */ + +/* + * unexpand - put tabs into a file replacing blanks + */ +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DSTOP 8 +static int all; +static size_t nstops; +static size_t maxstops; +static size_t *tabstops; + +static void tabify(const char *, size_t); +static void usage(void) __attribute__((__noreturn__)); + +static void +usage(void) +{ + (void)fprintf(stderr, "Usage: %s [-a] [-t tabstop] [file ...]\n", + getprogname()); + exit(EXIT_FAILURE); +} + +int +main(int argc, char **argv) +{ + int c; + char *ep, *tab; + char *line; + size_t len; + unsigned long i; + + setprogname(argv[0]); + + while ((c = getopt(argc, argv, "at:")) != -1) { + switch (c) { + case 'a': + if (nstops) + usage(); + all++; + break; + case 't': + if (all) + usage(); + while ((tab = strsep(&optarg, ", \t")) != NULL) { + if (*tab == '\0') + continue; + errno = 0; + i = strtoul(tab, &ep, 0); + if (*ep || (errno == ERANGE && i == ULONG_MAX)) + errx(EXIT_FAILURE, + "Invalid tabstop `%s'", tab); + if (nstops >= maxstops) { + maxstops += 20; + tabstops = erealloc(tabstops, maxstops); + } + if (nstops && tabstops[nstops - 1] >= (size_t)i) + errx(EXIT_FAILURE, + "Bad tabstop spec `%s', must be " + "greater than the previous `%zu'", + tab, tabstops[nstops - 1]); + tabstops[nstops++] = i; + } + break; + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + for (i = 0; i < nstops; i++) + fprintf(stderr, "%lu %zu\n", i, tabstops[i]); + + do { + if (argc > 0) { + if (freopen(argv[0], "r", stdin) == NULL) + err(EXIT_FAILURE, "Cannot open `%s'", argv[0]); + argc--, argv++; + } + while ((line = fgetln(stdin, &len)) != NULL) + tabify(line, len); + } while (argc > 0); + return EXIT_SUCCESS; +} + +static void +tabify(const char *line, size_t len) +{ + const char *e, *p; + size_t dcol, ocol, limit, n; + + dcol = ocol = 0; + limit = nstops == 0 ? UINT_MAX : tabstops[nstops - 1] - 1; + e = line + len; + for (p = line; p < e; p++) { + if (*p == ' ') { + dcol++; + continue; + } else if (*p == '\t') { + if (nstops == 0) { + dcol = (1 + dcol / DSTOP) * DSTOP; + continue; + } else { + for (n = 0; tabstops[n] - 1 < dcol && + n < nstops; n++) + continue; + if (n < nstops - 1 && tabstops[n] - 1 < limit) { + dcol = tabstops[n]; + continue; + } + } + } + + /* Output our tabs */ + if (nstops == 0) { + while (((ocol + DSTOP) / DSTOP) <= (dcol / DSTOP)) { + if (dcol - ocol < 2) + break; + if (putchar('\t') == EOF) + goto out; + ocol = (1 + ocol / DSTOP) * DSTOP; + } + } else { + for (n = 0; tabstops[n] <= ocol && n < nstops; n++) + continue; + while (tabstops[n] <= dcol && ocol < dcol && + n < nstops && ocol < limit) { + if (putchar('\t') == EOF) + goto out; + ocol = tabstops[n++]; + } + } + + /* Output remaining spaces */ + while (ocol < dcol && ocol < limit) { + if (putchar(' ') == EOF) + goto out; + ocol++; + } + + /* Output our char */ + if (putchar(*p) == EOF) + goto out; + if (*p == '\b') { + if (ocol > 0) { + ocol--; + dcol--; + } + } else { + ocol++; + dcol++; + } + + /* Output remainder of line */ + if (!all || dcol >= limit) { + for (p++; p < e; p++) + if (putchar(*p) == EOF) + goto out; + return; + } + } + return; +out: + err(EXIT_FAILURE, "write failed"); +}