1 /* $OpenBSD: expand.c,v 1.12 2013/11/26 13:18:55 deraadt Exp $ */ 2 /* $NetBSD: expand.c,v 1.5 1995/09/02 06:19:46 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1980, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <ctype.h> 36 #include <unistd.h> 37 #include <err.h> 38 39 /* 40 * expand - expand tabs to equivalent spaces 41 */ 42 int nstops; 43 int tabstops[100]; 44 45 static void getstops(char *); 46 static void usage(void); 47 48 int 49 main(int argc, char *argv[]) 50 { 51 int c, column; 52 int n; 53 54 /* handle obsolete syntax */ 55 while (argc > 1 && argv[1][0] == '-' && 56 isdigit((unsigned char)argv[1][1])) { 57 getstops(&argv[1][1]); 58 argc--; argv++; 59 } 60 61 while ((c = getopt (argc, argv, "t:")) != -1) { 62 switch (c) { 63 case 't': 64 getstops(optarg); 65 break; 66 case '?': 67 default: 68 usage(); 69 /* NOTREACHED */ 70 } 71 } 72 argc -= optind; 73 argv += optind; 74 75 do { 76 if (argc > 0) { 77 if (freopen(argv[0], "r", stdin) == NULL) 78 err(1, "%s", argv[0]); 79 argc--, argv++; 80 } 81 column = 0; 82 while ((c = getchar()) != EOF) { 83 switch (c) { 84 case '\t': 85 if (nstops == 0) { 86 do { 87 putchar(' '); 88 column++; 89 } while (column & 07); 90 continue; 91 } 92 if (nstops == 1) { 93 do { 94 putchar(' '); 95 column++; 96 } while (((column - 1) % 97 tabstops[0]) != (tabstops[0] - 1)); 98 continue; 99 } 100 for (n = 0; n < nstops; n++) 101 if (tabstops[n] > column) 102 break; 103 if (n == nstops) { 104 putchar(' '); 105 column++; 106 continue; 107 } 108 while (column < tabstops[n]) { 109 putchar(' '); 110 column++; 111 } 112 continue; 113 114 case '\b': 115 if (column) 116 column--; 117 putchar('\b'); 118 continue; 119 120 default: 121 putchar(c); 122 column++; 123 continue; 124 125 case '\n': 126 putchar(c); 127 column = 0; 128 continue; 129 } 130 } 131 } while (argc > 0); 132 exit(0); 133 } 134 135 static void 136 getstops(char *cp) 137 { 138 int i; 139 140 nstops = 0; 141 for (;;) { 142 i = 0; 143 while (*cp >= '0' && *cp <= '9') 144 i = i * 10 + *cp++ - '0'; 145 if (i <= 0 || i > 256) { 146 bad: 147 errx(1, "Bad tab stop spec"); 148 } 149 if (nstops > 0 && i <= tabstops[nstops-1]) 150 goto bad; 151 if (nstops >= sizeof(tabstops) / sizeof(tabstops[0])) 152 errx(1, "Too many tab stops"); 153 tabstops[nstops++] = i; 154 if (*cp == 0) 155 break; 156 if (*cp != ',' && *cp != ' ') 157 goto bad; 158 cp++; 159 } 160 } 161 162 static void 163 usage(void) 164 { 165 extern char *__progname; 166 fprintf (stderr, "usage: %s [-t tablist] [file ...]\n", __progname); 167 exit(1); 168 } 169