11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3141568Sarchiestatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3727147Scharnier#if 0 381590Srgrimesstatic char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93"; 3958606Scharnier#endif 401590Srgrimes#endif /* not lint */ 4199112Sobrien#include <sys/cdefs.h> 4299112Sobrien__FBSDID("$FreeBSD$"); 431590Srgrimes 4427147Scharnier#include <ctype.h> 4558606Scharnier#include <err.h> 4698251Stjr#include <locale.h> 471590Srgrimes#include <stdio.h> 4878718Sdd#include <stdlib.h> 4927147Scharnier#include <unistd.h> 50131051Stjr#include <wchar.h> 51200462Sdelphij#include <wctype.h> 5227147Scharnier 531590Srgrimes/* 541590Srgrimes * expand - expand tabs to equivalent spaces 551590Srgrimes */ 56227238Sedstatic int nstops; 57227238Sedstatic int tabstops[100]; 581590Srgrimes 5992920Simpstatic void getstops(char *); 6092920Simpstatic void usage(void); 6127147Scharnier 6227147Scharnierint 63102944Sdwmalonemain(int argc, char *argv[]) 641590Srgrimes{ 65131051Stjr const char *curfile; 66131051Stjr wint_t wc; 67102944Sdwmalone int c, column; 68102944Sdwmalone int n; 6997216Stjr int rval; 70131051Stjr int width; 711590Srgrimes 7298251Stjr setlocale(LC_CTYPE, ""); 7398251Stjr 7427147Scharnier /* handle obsolete syntax */ 7598251Stjr while (argc > 1 && argv[1][0] == '-' && 7698251Stjr isdigit((unsigned char)argv[1][1])) { 7727147Scharnier getstops(&argv[1][1]); 7827147Scharnier argc--; argv++; 7927147Scharnier } 8027147Scharnier 8127147Scharnier while ((c = getopt (argc, argv, "t:")) != -1) { 8227147Scharnier switch (c) { 8327147Scharnier case 't': 8427147Scharnier getstops(optarg); 8527147Scharnier break; 8627147Scharnier case '?': 8727147Scharnier default: 8827147Scharnier usage(); 8927147Scharnier /* NOTREACHED */ 9027147Scharnier } 9127147Scharnier } 9227147Scharnier argc -= optind; 9327147Scharnier argv += optind; 9427147Scharnier 9597216Stjr rval = 0; 961590Srgrimes do { 971590Srgrimes if (argc > 0) { 9897216Stjr if (freopen(argv[0], "r", stdin) == NULL) { 9997216Stjr warn("%s", argv[0]); 10097216Stjr rval = 1; 10197216Stjr argc--, argv++; 10297216Stjr continue; 10397216Stjr } 104131051Stjr curfile = argv[0]; 1051590Srgrimes argc--, argv++; 106131051Stjr } else 107131051Stjr curfile = "stdin"; 1081590Srgrimes column = 0; 109131051Stjr while ((wc = getwchar()) != WEOF) { 110131051Stjr switch (wc) { 1111590Srgrimes case '\t': 1121590Srgrimes if (nstops == 0) { 1131590Srgrimes do { 114131051Stjr putwchar(' '); 1151590Srgrimes column++; 1161590Srgrimes } while (column & 07); 1171590Srgrimes continue; 1181590Srgrimes } 1191590Srgrimes if (nstops == 1) { 1201590Srgrimes do { 121131051Stjr putwchar(' '); 1221590Srgrimes column++; 1231590Srgrimes } while (((column - 1) % tabstops[0]) != (tabstops[0] - 1)); 1241590Srgrimes continue; 1251590Srgrimes } 1261590Srgrimes for (n = 0; n < nstops; n++) 1271590Srgrimes if (tabstops[n] > column) 1281590Srgrimes break; 1291590Srgrimes if (n == nstops) { 130131051Stjr putwchar(' '); 1311590Srgrimes column++; 1321590Srgrimes continue; 1331590Srgrimes } 1341590Srgrimes while (column < tabstops[n]) { 135131051Stjr putwchar(' '); 1361590Srgrimes column++; 1371590Srgrimes } 1381590Srgrimes continue; 1391590Srgrimes 1401590Srgrimes case '\b': 1411590Srgrimes if (column) 1421590Srgrimes column--; 143131051Stjr putwchar('\b'); 1441590Srgrimes continue; 1451590Srgrimes 1461590Srgrimes default: 147131051Stjr putwchar(wc); 148131051Stjr if ((width = wcwidth(wc)) > 0) 149131051Stjr column += width; 1501590Srgrimes continue; 1511590Srgrimes 1521590Srgrimes case '\n': 153131051Stjr putwchar(wc); 1541590Srgrimes column = 0; 1551590Srgrimes continue; 1561590Srgrimes } 1571590Srgrimes } 158131051Stjr if (ferror(stdin)) { 159131051Stjr warn("%s", curfile); 160131051Stjr rval = 1; 161131051Stjr } 1621590Srgrimes } while (argc > 0); 16397216Stjr exit(rval); 1641590Srgrimes} 1651590Srgrimes 16627147Scharnierstatic void 167102944Sdwmalonegetstops(char *cp) 1681590Srgrimes{ 169102944Sdwmalone int i; 1701590Srgrimes 1711590Srgrimes nstops = 0; 1721590Srgrimes for (;;) { 1731590Srgrimes i = 0; 1741590Srgrimes while (*cp >= '0' && *cp <= '9') 1751590Srgrimes i = i * 10 + *cp++ - '0'; 17678482Sdd if (i <= 0) 17758606Scharnier errx(1, "bad tab stop spec"); 1781590Srgrimes if (nstops > 0 && i <= tabstops[nstops-1]) 17958606Scharnier errx(1, "bad tab stop spec"); 18091740Sru if (nstops == sizeof(tabstops) / sizeof(*tabstops)) 18191740Sru errx(1, "too many tab stops"); 1821590Srgrimes tabstops[nstops++] = i; 1831590Srgrimes if (*cp == 0) 1841590Srgrimes break; 18598251Stjr if (*cp != ',' && !isblank((unsigned char)*cp)) 18658606Scharnier errx(1, "bad tab stop spec"); 18727147Scharnier cp++; 1881590Srgrimes } 1891590Srgrimes} 19027147Scharnier 19127147Scharnierstatic void 192102944Sdwmaloneusage(void) 19327147Scharnier{ 19427147Scharnier (void)fprintf (stderr, "usage: expand [-t tablist] [file ...]\n"); 19527147Scharnier exit(1); 19627147Scharnier} 197