expand.c revision 131051
1234285Sdim/* 2234285Sdim * Copyright (c) 1980, 1993 3234285Sdim * The Regents of the University of California. All rights reserved. 4234285Sdim * 5234285Sdim * Redistribution and use in source and binary forms, with or without 6234285Sdim * modification, are permitted provided that the following conditions 7234285Sdim * are met: 8234285Sdim * 1. Redistributions of source code must retain the above copyright 9234285Sdim * notice, this list of conditions and the following disclaimer. 10263508Sdim * 2. Redistributions in binary form must reproduce the above copyright 11263508Sdim * notice, this list of conditions and the following disclaimer in the 12263508Sdim * documentation and/or other materials provided with the distribution. 13263508Sdim * 3. All advertising materials mentioning features or use of this software 14263508Sdim * must display the following acknowledgement: 15263508Sdim * This product includes software developed by the University of 16263508Sdim * California, Berkeley and its contributors. 17263508Sdim * 4. Neither the name of the University nor the names of its contributors 18263508Sdim * may be used to endorse or promote products derived from this software 19263508Sdim * without specific prior written permission. 20263508Sdim * 21263508Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22263508Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23263508Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24263508Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25263508Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26263508Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27263508Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28263508Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29263508Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30263508Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31263508Sdim * SUCH DAMAGE. 32263508Sdim */ 33263508Sdim 34263508Sdim#ifndef lint 35263508Sdimstatic const char copyright[] = 36263508Sdim"@(#) Copyright (c) 1980, 1993\n\ 37263508Sdim The Regents of the University of California. All rights reserved.\n"; 38263508Sdim#endif /* not lint */ 39263508Sdim 40263508Sdim#ifndef lint 41263508Sdim#if 0 42263508Sdimstatic char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93"; 43263508Sdim#endif 44263508Sdim#endif /* not lint */ 45263508Sdim#include <sys/cdefs.h> 46263508Sdim__FBSDID("$FreeBSD: head/usr.bin/expand/expand.c 131051 2004-06-24 13:42:26Z tjr $"); 47263508Sdim 48263508Sdim#include <ctype.h> 49263508Sdim#include <err.h> 50263508Sdim#include <locale.h> 51263508Sdim#include <stdio.h> 52234285Sdim#include <stdlib.h> 53234285Sdim#include <unistd.h> 54234285Sdim#include <wchar.h> 55234285Sdim#include <wctype.h> 56234285Sdim 57234285Sdim/* 58234285Sdim * expand - expand tabs to equivalent spaces 59234285Sdim */ 60234285Sdimint nstops; 61234285Sdimint tabstops[100]; 62263508Sdim 63263508Sdimstatic void getstops(char *); 64263508Sdimstatic void usage(void); 65263508Sdim 66263508Sdimint 67263508Sdimmain(int argc, char *argv[]) 68263508Sdim{ 69263508Sdim const char *curfile; 70263508Sdim wint_t wc; 71263508Sdim int c, column; 72263508Sdim int n; 73263508Sdim int rval; 74263508Sdim int width; 75234285Sdim 76234285Sdim setlocale(LC_CTYPE, ""); 77249423Sdim 78249423Sdim /* handle obsolete syntax */ 79234285Sdim while (argc > 1 && argv[1][0] == '-' && 80234285Sdim isdigit((unsigned char)argv[1][1])) { 81243830Sdim getstops(&argv[1][1]); 82243830Sdim argc--; argv++; 83234285Sdim } 84234285Sdim 85234285Sdim while ((c = getopt (argc, argv, "t:")) != -1) { 86243830Sdim switch (c) { 87243830Sdim case 't': 88243830Sdim getstops(optarg); 89234285Sdim break; 90234285Sdim case '?': 91234285Sdim default: 92234285Sdim usage(); 93239462Sdim /* NOTREACHED */ 94234285Sdim } 95249423Sdim } 96234285Sdim argc -= optind; 97234285Sdim argv += optind; 98234285Sdim 99234285Sdim rval = 0; 100234285Sdim do { 101234285Sdim if (argc > 0) { 102234285Sdim if (freopen(argv[0], "r", stdin) == NULL) { 103234285Sdim warn("%s", argv[0]); 104234285Sdim rval = 1; 105234285Sdim argc--, argv++; 106234285Sdim continue; 107239462Sdim } 108239462Sdim curfile = argv[0]; 109239462Sdim argc--, argv++; 110239462Sdim } else 111234285Sdim curfile = "stdin"; 112234285Sdim column = 0; 113234285Sdim while ((wc = getwchar()) != WEOF) { 114234285Sdim switch (wc) { 115234285Sdim case '\t': 116234285Sdim if (nstops == 0) { 117234285Sdim do { 118234285Sdim putwchar(' '); 119234285Sdim column++; 120234285Sdim } while (column & 07); 121234285Sdim continue; 122234285Sdim } 123234285Sdim if (nstops == 1) { 124234285Sdim do { 125234285Sdim putwchar(' '); 126234285Sdim column++; 127234285Sdim } while (((column - 1) % tabstops[0]) != (tabstops[0] - 1)); 128234285Sdim continue; 129234285Sdim } 130234285Sdim for (n = 0; n < nstops; n++) 131234285Sdim if (tabstops[n] > column) 132234285Sdim break; 133234285Sdim if (n == nstops) { 134234285Sdim putwchar(' '); 135234285Sdim column++; 136234285Sdim continue; 137234285Sdim } 138234285Sdim while (column < tabstops[n]) { 139234285Sdim putwchar(' '); 140234285Sdim column++; 141234285Sdim } 142234285Sdim continue; 143243830Sdim 144243830Sdim case '\b': 145263508Sdim if (column) 146263508Sdim column--; 147263508Sdim putwchar('\b'); 148263508Sdim continue; 149263508Sdim 150263508Sdim default: 151263508Sdim putwchar(wc); 152263508Sdim if ((width = wcwidth(wc)) > 0) 153263508Sdim column += width; 154263508Sdim continue; 155263508Sdim 156263508Sdim case '\n': 157263508Sdim putwchar(wc); 158263508Sdim column = 0; 159263508Sdim continue; 160263508Sdim } 161243830Sdim } 162243830Sdim if (ferror(stdin)) { 163263508Sdim warn("%s", curfile); 164263508Sdim rval = 1; 165263508Sdim } 166243830Sdim } while (argc > 0); 167263508Sdim exit(rval); 168243830Sdim} 169243830Sdim 170243830Sdimstatic void 171263508Sdimgetstops(char *cp) 172263508Sdim{ 173263508Sdim int i; 174263508Sdim 175263508Sdim nstops = 0; 176263508Sdim for (;;) { 177263508Sdim i = 0; 178263508Sdim while (*cp >= '0' && *cp <= '9') 179263508Sdim i = i * 10 + *cp++ - '0'; 180243830Sdim if (i <= 0) 181243830Sdim errx(1, "bad tab stop spec"); 182243830Sdim if (nstops > 0 && i <= tabstops[nstops-1]) 183243830Sdim errx(1, "bad tab stop spec"); 184243830Sdim if (nstops == sizeof(tabstops) / sizeof(*tabstops)) 185243830Sdim errx(1, "too many tab stops"); 186243830Sdim tabstops[nstops++] = i; 187243830Sdim if (*cp == 0) 188243830Sdim break; 189243830Sdim if (*cp != ',' && !isblank((unsigned char)*cp)) 190243830Sdim errx(1, "bad tab stop spec"); 191243830Sdim cp++; 192249423Sdim } 193249423Sdim} 194249423Sdim 195243830Sdimstatic void 196243830Sdimusage(void) 197243830Sdim{ 198243830Sdim (void)fprintf (stderr, "usage: expand [-t tablist] [file ...]\n"); 199243830Sdim exit(1); 200243830Sdim} 201243830Sdim