diff options
Diffstat (limited to 'usr.bin/tabs')
-rw-r--r-- | usr.bin/tabs/tabs.1 | 166 | ||||
-rw-r--r-- | usr.bin/tabs/tabs.c | 232 |
2 files changed, 398 insertions, 0 deletions
diff --git a/usr.bin/tabs/tabs.1 b/usr.bin/tabs/tabs.1 new file mode 100644 index 0000000..e88b29a --- /dev/null +++ b/usr.bin/tabs/tabs.1 @@ -0,0 +1,166 @@ +.\" $NetBSD: tabs.1,v 1.6 2014/03/18 18:20:45 riastradh Exp $ +.\" +.\" Copyright (c) 2008 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Roy Marples. +.\" +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. +.\" +.Dd April 5, 2012 +.Dt TABS 1 +.Os +.Sh NAME +.Nm tabs +.Nd set terminal tabs +.Sh SYNOPSIS +.Nm +.Op Fl n Ns | Ns Fl a Ns | Ns Fl a2 Ns | Ns Fl c Ns | Ns Fl c2 \ +Ns | Ns Fl c3 Ns | Ns Fl f Ns | Ns Fl p Ns | Ns Fl s Ns | Ns Fl u +.Op +m Ns Op n +.Op Fl T Ar type +.Nm +.Op Fl T Ar type +.Op + Ns Op n +.Ar n1 Ns Op , Ns Ar n2 , Ns Ar ... +.Sh DESCRIPTION +The +.Nm +utility displays a series of characters that first clears the hardware terminal +tab settings and then initializes the tab stops at the specified positions +and optionally adjusts the margin. +.Pp +The phrase "tab-stop position N" means that, from the start of a line of +output, tabbing to position N shall cause the next character output to be in +the (N+1)th column on that line. +.Pp +The following options are supported: +.Bl -tag -width Fl +.It Fl Ar n +Specifies repetitive tab stops separated by a uniform number of columns, +.Ar n , +where +.Ar n +is a single digit decimal number. +The default usage of +.Nm +with no arguments is equivalent to +.Nm +.Fl 8 . +When +.Fl 0 +is used, the tab stops are cleared and no new ones set. +.It Fl a +Assembler, applicable to some mainframes. +Equivalent to +.Nm +1,10,16,36,72 . +.It Fl a2 +Assembler, applicable to some mainframes. +Equivalent to +.Nm +1,10,16,40,72 +.It Fl c +.Tn COBOL , +normal format. +Equivalent to +.Nm +1,8,12,16,20,55 +.It Fl c2 +.Tn COBOL , +compact format (columns 1 to 6 omitted). +Equivalent to +.Nm +1,6,10,14,49 +.It Fl c3 +.Tn COBOL , +compact format (columns 1 to 6 omitted), with more tabs than +.Fl c2 . +Equivalent to +.Nm +1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67 +.It Fl f +.Tn FORTRAN . +Equivalent to +.Nm +1,7,11,15,19,23 +.It Fl p +.Tn PL/1 . +Equivalent to +.Nm +1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61 +.It Fl s +.Tn SNOBOL . +Equivalent to +.Nm +1,10,55 +.It Fl T Ar type +Indicates the type of terminal. +.It Fl u +Assembler, applicable to some mainframes. +Equivalent to +.Nm +1,12,20,44 +.El +.Sh ENVIRONMENT +The +.Ev COLUMNS +and +.Ev TERM +environment variables affect the execution of +.Nm +as described in +.Xr environ 7 . +.Pp +The +.Fl T +option overrides +.Ev TERM . +If neither +.Ev TERM +nor the +.Fl T +option are present, +.Nm +will fail. +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr expand 1 , +.Xr stty 1 , +.Xr tput 1 , +.Xr unexpand 1 , +.Xr terminfo 5 +.Sh STANDARDS +The +.Nm +utility conforms to +.St -p1003.1 . +.Sh HISTORY +A +.Nm +utility first appeared in PWB UNIX. +This implementation was introduced in +.Nx 6.0 . +.Sh AUTHORS +.An Roy Marples Aq Mt roy@NetBSD.org diff --git a/usr.bin/tabs/tabs.c b/usr.bin/tabs/tabs.c new file mode 100644 index 0000000..9e017a0 --- /dev/null +++ b/usr.bin/tabs/tabs.c @@ -0,0 +1,232 @@ +/* $NetBSD: tabs.c,v 1.5 2019/02/01 08:29:04 mrg Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Roy Marples. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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) 2008 \ +The NetBSD Foundation, inc. All rights reserved."); +__RCSID("$NetBSD: tabs.c,v 1.5 2019/02/01 08:29:04 mrg Exp $"); +#endif /* not lint */ + +#include <sys/ioctl.h> +#include <sys/types.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <term.h> +#include <unistd.h> + +#define NSTOPS 20 + +struct tabspec { + const char *opt; + const char *spec; +}; +static const struct tabspec tabspecs[] = { + {"a", "1,10,16,36,72"}, + {"a2", "1,10,16,40,72"}, + {"c", "1,8,12,16,20,55"}, + {"c2", "1,6,10,14,49"}, + {"c3", "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67"}, + {"f", "1,7,11,15,19,23"}, + {"p", "1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61"}, + {"s", "1,10,55"}, + {"u", "1,12,20,44"} +}; +static const size_t ntabspecs = sizeof(tabspecs) / sizeof(tabspecs[0]); + +__dead static void +usage(void) +{ + fprintf(stderr, + "usage: tabs [-n|-a|-a2|-c|-c2|-c3|-f|-p|-s|-u] [+m[n]]" + " [-T type]\n" + " tabs [-T type] [+[n]] n1[,n2,...]\n"); + exit(EXIT_FAILURE); + /* NOTREACHED */ +} + +int +main(int argc, char **argv) +{ + char *term, *arg, *token, *end, *tabs = NULL, *p; + const char *cr, *spec = NULL; + int i, n, inc = 8, stops[NSTOPS], nstops, last, cols, margin = 0; + size_t j; + struct winsize ws; + + term = getenv("TERM"); + for (i = 1; i < argc; i++) { + if (argv[i][0] == '+') { + arg = argv[i] + 1; + if (arg[0] == 'm') + arg++; + if (arg[0] == '\0') + margin = 10; + else { + errno = 0; + margin = strtol(arg, &end, 10); + if (errno != 0 || *end != '\0' || margin < 0) + errx(EXIT_FAILURE, + "%s: invalid margin", arg); + } + continue; + } + if (argv[i][0] != '-') { + tabs = argv[i]; + break; + } + arg = argv[i] + 1; + if (arg[0] == '\0') + usage(); + if (arg[0] == '-' && arg[1] == '\0') { + if (argv[i + 1] != NULL) + tabs = argv[i + 1]; + break; + } + if (arg[0] == 'T' && arg[1] == '\0') { + term = argv[++i]; + if (term == NULL) + usage(); + continue; + } + if (isdigit((int)arg[0])) { + if (arg[1] != '\0') + errx(EXIT_FAILURE, + "%s: invalid increament", arg); + inc = arg[0] - '0'; + continue; + } + for (j = 0; j < ntabspecs; j++) { + if (arg[0] == tabspecs[j].opt[0] && + arg[1] == tabspecs[j].opt[1]) { + spec = tabspecs[j].spec; + break; + } + } + if (j == ntabspecs) + usage(); + } + if (tabs == NULL && spec != NULL) + tabs = strdup(spec); + + if (tabs != NULL) + last = nstops = 0; + else + nstops = -1; + p = tabs; + while ((token = strsep(&p, ", ")) != NULL) { + if (*token == '\0') + continue; + if (nstops >= NSTOPS) + errx(EXIT_FAILURE, + "too many tab stops (max %d)", NSTOPS); + errno = 0; + n = strtol(token, &end, 10); + if (errno != 0 || *end != '\0' || n <= 0) + errx(EXIT_FAILURE, "%s: invalid tab stop", token); + if (*token == '+') { + if (nstops == 0) + errx(EXIT_FAILURE, + "first tab stop may not be relative"); + n += last; + } + if (last > n) + errx(EXIT_FAILURE, "tab stops may not go backwards"); + last = stops[nstops++] = n; + } + + if (term == NULL) + errx(EXIT_FAILURE, "no value for $TERM and -T not given"); + if (setupterm(term, STDOUT_FILENO, NULL) != 0) + err(EXIT_FAILURE, "setupterm:"); + cr = carriage_return; + if (cr == NULL) + cr = "\r"; + if (clear_all_tabs == NULL) + errx(EXIT_FAILURE, "terminal cannot clear tabs"); + if (set_tab == NULL) + errx(EXIT_FAILURE, "terminal cannot set tabs"); + + /* Clear existing tabs */ + putp(cr); + putp(clear_all_tabs); + putp(cr); + + if (set_lr_margin != NULL) { + printf("%*s", margin, ""); + putp(set_lr_margin); + } else if (margin != 0) + warnx("terminal cannot set left margin"); + + if (nstops >= 0) { + printf("%*s", stops[0] - 1, ""); + putp(set_tab); + for (i = 1; i < nstops; i++) { + printf("%*s", stops[i] - stops[i - 1], ""); + putp(set_tab); + } + } else if (inc > 0) { + cols = 0; + term = getenv("COLUMNS"); + if (term != NULL) { + errno = 0; + cols = strtol(term, &end, 10); + if (errno != 0 || *end != '\0' || cols < 0) + cols = 0; + } + if (cols == 0) { + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) + cols = ws.ws_col; + else { + cols = tigetnum("cols"); + if (cols == 0) { + cols = 80; + warnx("terminal does not specify number" + "columns; defaulting to %d", + cols); + } + } + } + for (i = 0; i < cols / inc; i++) { + printf("%*s", inc, ""); + putp(set_tab); + } + } + putp(cr); + + exit(EXIT_SUCCESS); + /* NOTREACHED */ +} |