Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Mar 2002 18:23:24 +1100 (EST)
From:      "Tim J. Robbins" <tim@robbins.dropbear.id.au>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   standards/36126: P1003.1-2001 tabs utility
Message-ID:  <200203200723.g2K7NOa04690@descent.robbins.dropbear.id.au>

next in thread | raw e-mail | index | archive | help

>Number:         36126
>Category:       standards
>Synopsis:       P1003.1-2001 tabs utility
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-standards
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar 19 23:40:02 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Tim J. Robbins
>Release:        FreeBSD 4.5-STABLE i386
>Organization:
>Environment:
System: FreeBSD descent.robbins.dropbear.id.au 4.5-STABLE FreeBSD 4.5-STABLE #8: Tue Mar 19 08:46:39 EST 2002 tim@descent.robbins.dropbear.id.au:/usr/obj/usr/src/sys/DESCENT i386


	
>Description:
FreeBSD is missing the P1003.1-2001 tabs utility, which sets/clears terminal
tab stops and margins.
>How-To-Repeat:
tabs
>Fix:

Here is an implementation of the tabs utility. It works on all the VT100
emulators I've tried, but does not work on ANSI terminals or FreeBSD console.
GNU termutils shares this limitation.

Although it's not very useful, the standard still requires it.

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	tabs.c
#	tabs.1
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X# $FreeBSD$
X# $Id: Makefile,v 1.2 2002/02/17 23:08:53 tim Exp $
X
XPROG=	tabs
XDPADD=	${LIBTERMCAP}
XLDADD=	-ltermcap
X
X.include <bsd.prog.mk>
END-of-Makefile
echo x - tabs.c
sed 's/^X//' >tabs.c << 'END-of-tabs.c'
X/*-
X * Copyright (c) 2002 Tim J. Robbins.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X/*
X * tabs -- set terminal tabs
X *
X * This utility displays a series of characters that reinitialises the
X * terminal hardware tab settings.
X *
X * NOTE: Warnings emitted by gcc such as "passing arg 1 of `tparm' discards
X * qualifiers from pointer target type" are caused by a flaw in <term.h>
X * that causes the "const" to be omitted from the prototypes.
X */
X
X#include <sys/cdefs.h>
X__FBSDID("$FreeBSD$");
X__RCSID("$Id: tabs.c,v 1.9 2002/03/19 10:52:02 tim Exp $");
X
X#include <ctype.h>
X#include <curses.h>
X#include <err.h>
X#include <errno.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <term.h>
X
X
X/* Maximum number of tab stops allowed in table */
X#define NSTOPS		20
X
Xvoid usage(void);
X
X/*
X * Predefined formats, taken from IEEE P1003.1 Draft 7, June 2001. We rely
X * on the fact that the uninitialised elements of the `stops' array will
X * be zeroed.
X */
Xstruct {
X	const char	*name;		/* Format name used on cmd. line */
X	int		stops[NSTOPS];	/* Column positions */
X} formats[] = {
X	{ "a",	{ 1, 10, 16, 36, 72 } },
X	{ "a2",	{ 1, 10, 16, 40, 72 } },
X	{ "c",	{ 1, 8, 12, 16, 20, 55 } },
X	{ "c2",	{ 1, 6, 10, 14, 49 } },
X	{ "c3", { 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 54, 58,
X		62, 67 } },
X	{ "f",	{ 1, 7, 11, 15, 19, 23 } },
X	{ "p",	{ 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57,
X		61 } },
X	{ "s",	{ 1, 10, 55 } },
X	{ "u",	{ 1, 12, 20, 44 } }
X};
X
X#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
X
Xint
Xmain(int argc, char *argv[])
X{
X	char area[1024];
X	int stops[NSTOPS];
X	long inc, nstops, margin;
X	char *arg, *end, *ap;
X	const char *ct, *st, *cr, *ML;
X
X	inc = 0;
X	margin = 0;
X	nstops = -1;
X	while ((arg = *++argv) != NULL && (*arg == '-' || *arg == '+')) {
X		if (*arg == '+') {
X			/*
X			 * +m[n] and +n
X			 */
X			if (*++arg == 'm')
X				arg++;
X			if (*arg != '\0') {
X				errno = 0;
X				margin = strtol(arg + 2, &end, 10);
X				if (errno != 0 || *end != '\0')
X					errx(1, "invalid number");
X			} else
X				margin = 10;
X			continue;
X		}
X		if (isdigit(arg[1])) {
X			/*
X			 * -n
X			 */
X			errno = 0;
X			inc = strtol(arg + 1, &end, 10);
X			if (errno != 0 || *end != '\0')
X				errx(1, "invalid number");
X		} else if (arg[1] == 'T') {
X			/*
X			 * -Ttype or -T type
X			 */
X			if (arg[2] != '\0')
X				setenv("TERM", arg + 2, 1);
X			else {
X				if ((arg = *++argv) == NULL)
X					usage();
X				setenv("TERM", arg, 1);
X			}
X		} else {
X			/*
X			 * The only thing left to try is one of the
X			 * predefined formats.
X			 */
X			int i, j;
X
X			for (i = 0; i < (int)NELEMS(formats); i++)
X				if (strcmp(formats[i].name, arg + 1) == 0)
X					break;
X			if (i == NELEMS(formats))
X				usage();
X			for (j = nstops = 0; j < NSTOPS &&
X			    formats[i].stops[j] != 0; j++)
X				stops[nstops++] = formats[i].stops[j];
X		}
X	}	
X	
X	if (arg != NULL) {
X		char *tok;
X		long last = 0, stop;
X
X		/* List of tab stops */
X		if (nstops != -1 || inc != 0 || argv[1] != NULL)
X			usage();
X
X		for (nstops = 0, tok = strtok(arg, ","); tok != NULL;
X		    tok = strtok(NULL, ",")) {
X			if (nstops >= NSTOPS) {
X				warnx("too many tab stops given");
X				break;
X			}
X			if (*tok == '+' && tok != arg) {
X				errno = 0;
X				stop = strtol(tok + 1, &end, 10);
X				if (errno != 0 || *end != '\0')
X					errx(1, "invalid number");
X				stop += last;
X				if (last > stop)
X					errx(1, "can't go backwards");
X				last = stops[nstops++] = stop;
X			} else {
X				errno = 0;
X				stop = strtol(tok, &end, 10);
X				if (errno != 0 || *end != '\0')
X					errx(1, "invalid number");
X				if (last > stop)
X					errx(1, "can't go backwards");
X				last = stops[nstops++] = stop;
X			}
X		}
X	}
X
X	/* Initialise terminal, get the strings we need */
X	setupterm(NULL, 1, NULL);
X	ap = area;
X	if ((ct = tgetstr("ct", &ap)) == NULL)
X		errx(1, "can't clear tabs");
X	if ((st = tgetstr("st", &ap)) == NULL)
X		errx(1, "can't set tabs");
X	if ((cr = tgetstr("cr", &ap)) == NULL)
X		cr = "\r";
X	ML = tgetstr("ML", &ap);
X
X	/* Clear all tabs */
X	putp(cr);
X	putp(ct);
X
X	if (ML != NULL)
X		putp(tparm(ML, margin));
X	else if (margin != 0)
X		warnx("can't set soft margin");
X
X	if (nstops >= 0) {
X		long i, j;
X
X		/* Optionally output the new ones */
X		if (nstops > 0) {
X			putp(cr);
X			for (j = 1; j < stops[0]; j++)
X				putchar(' ');
X			putp(st);
X			for (i = 1; i < nstops; i++) {
X				for (j = 0; j < stops[i] - stops[i - 1]; j++)
X					putchar(' ');
X				putp(st);
X			}
X			putp(cr);
X		}
X	} else if (inc > 0) {
X		long cols, i, j;
X
X		cols = tgetnum("co");
X		if (cols == 0)
X			cols = atoi(getenv("COLUMNS"));
X		if (cols == 0) {
X			cols = 80;
X			warnx("defaulted to %ld columns", cols);
X		}
X
X		putp(cr);
X		/* Set tab stops every `inc' characters */
X		for (i = 0; i < cols / inc; i++) {
X			putp(st);
X			for (j = 0; j < inc; j++)
X				putchar(' ');
X		}
X		putp(st);
X		putp(cr);
X	}
X
X	return (0);
X}
X
Xvoid
Xusage(void)
X{
X	fprintf(stderr,
X"usage: tabs [-n|-a|-a2|-c|-c2|-c3|-f|-p|-s|-u] [+m[n]] [+n] [-T type]\n");
X	fprintf(stderr,
X"       tabs [+m[n]] [+n] [-T type] n1,[n2,...]\n");
X	exit(1);
X}
END-of-tabs.c
echo x - tabs.1
sed 's/^X//' >tabs.1 << 'END-of-tabs.1'
X.\" Copyright (c) 2002 Tim J. Robbins.
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X.\" SUCH DAMAGE.
X.\"
X.\" $FreeBSD$
X.\" $Id: tabs.1,v 1.5 2002/03/19 11:01:21 tim Exp $
X.\"
X.Dd January 24, 2002
X.Dt TABS 1
X.Os
X.Sh NAME
X.Nm tabs
X.Nd set terminal tabs
X.Sh SYNOPSIS
X.Nm
X.Op Cm +m Ns Op Ar n
X.Op Cm + Ns Ar n
X.Op Fl T Ar type
X.Ar n1 , Ns Op Ar n2 , Ns ...
X.Nm
X.Op Fl Ar n | Fl a | a2 | c | c2 | c3 | f | p | s | u
X.Op Cm +m Ns Op Ar n
X.Op Cm + Ns Ar n
X.Op Fl T Ar type
X.Sh DESCRIPTION
XThe
X.Nm
Xutility displays a series of characters that clear the hardware terminal
Xtab settings then optionally initialise tab stops at specified positions.
X.Pp
XIn the first synopsis form, tab stops are set at positions
X.Ar n1 , Ar n2 ,
Xetc.
XIf a position is preceded by a
X.Ql + ,
Xit is relative to the previous position set.
X.Pp
XIn the second synopsis form, the tab stops set depend on the command line
Xoptions used, and may be one of the predefined formats or at regular
Xintervals.
X.Pp
XThe options are as follows:
X.Bl -tag -width indent
X.It Fl Ar n
XSet a tab stop every
X.Ar n
Xcolumns.
X.It Fl a
XAssembler format (columns 1, 10, 16, 36, 72).
X.It Fl a2
XAssembler format (columns 1, 10, 16, 40, 72).
X.It Fl c
XCOBOL normal format (columns 1, 8, 12, 16, 20, 55)
X.It Fl c2
XCOBOL compact format (columns 1, 6, 10, 14, 49)
X.It Fl c3
XCOBOL compact format (columns 1, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46,
X50, 54, 58, 62, 67).
X.It Fl f
XFORTRAN format (columns 1, 7, 11, 15, 19, 23).
X.It Fl p
XPL/1 format (columns 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53,
X57, 61).
X.It Fl s
XSNOBOL format (columns 1, 10, 55).
X.It Fl u
XAssembler format (columns 1, 12, 20, 44).
X.It Cm + Ns Ar n
XSet an
X.Ar n
Xcharacter margin.
X.It Cm +m Ns Op Ar n
XSet an
X.Ar n
Xcharacter margin, or 10 if
X.Ar n
Xis omitted.
X.It Fl T Ar type
XOutput escape sequence for the terminal type
X.Ar type .
X.El
X.Sh ENVIRONMENT
X.Bl -tag -width indent
X.It Ev TERM
XTerminal type unless overridden by the
X.Fl T
Xoption.
X.Sh DIAGNOSTICS
X.Ex -std
X.Sh SEE ALSO
X.Xr expand 1 ,
X.Xr stty 1 ,
X.Xr tput 1 ,
X.Xr unexpand 1 ,
X.Xr termcap 5
X.Sh STANDARDS
XThe
X.Nm
Xutility is designed to comply with the
X.St -p1003.1-2001
Xspecification.
END-of-tabs.1
exit

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-standards" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200203200723.g2K7NOa04690>