]> git.cameronkatri.com Git - apple_cmds.git/blob - text_cmds/expand/expand.c
setup.sh: Initial commit
[apple_cmds.git] / text_cmds / expand / expand.c
1 /*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1980, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)expand.c 8.1 (Berkeley) 6/9/93";
43 #endif
44 #endif /* not lint */
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD: src/usr.bin/expand/expand.c,v 1.15 2004/06/24 13:42:26 tjr Exp $");
47
48 #include <ctype.h>
49 #include <err.h>
50 #include <locale.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <wchar.h>
55 #include <wctype.h>
56
57 /*
58 * expand - expand tabs to equivalent spaces
59 */
60 int nstops;
61 int tabstops[100];
62
63 static void getstops(char *);
64 static void usage(void);
65
66 int
67 main(int argc, char *argv[])
68 {
69 const char *curfile;
70 wint_t wc;
71 int c, column;
72 int n;
73 int rval;
74 int width;
75
76 setlocale(LC_CTYPE, "");
77
78 /* handle obsolete syntax */
79 while (argc > 1 && argv[1] && argv[1][0] == '-' &&
80 isdigit((unsigned char)argv[1][1])) {
81 getstops(&argv[1][1]);
82 argc--; argv++;
83 }
84
85 while ((c = getopt (argc, argv, "t:")) != -1) {
86 switch (c) {
87 case 't':
88 getstops(optarg);
89 break;
90 case '?':
91 default:
92 usage();
93 /* NOTREACHED */
94 }
95 }
96 argc -= optind;
97 argv += optind;
98
99 rval = 0;
100 do {
101 if (argc > 0 && *argv) {
102 if (freopen(argv[0], "r", stdin) == NULL) {
103 warn("%s", argv[0]);
104 rval = 1;
105 argc--, argv++;
106 continue;
107 }
108 curfile = argv[0];
109 argc--, argv++;
110 } else
111 curfile = "stdin";
112 column = 0;
113 while ((wc = getwchar()) != WEOF) {
114 switch (wc) {
115 case '\t':
116 if (nstops == 0) {
117 do {
118 putwchar(' ');
119 column++;
120 } while (column & 07);
121 continue;
122 }
123 if (nstops == 1) {
124 do {
125 putwchar(' ');
126 column++;
127 } while (((column - 1) % tabstops[0]) != (tabstops[0] - 1));
128 continue;
129 }
130 for (n = 0; n < nstops; n++)
131 if (tabstops[n] > column)
132 break;
133 if (n == nstops) {
134 putwchar(' ');
135 column++;
136 continue;
137 }
138 while (column < tabstops[n]) {
139 putwchar(' ');
140 column++;
141 }
142 continue;
143
144 case '\b':
145 if (column)
146 column--;
147 putwchar('\b');
148 continue;
149
150 default:
151 putwchar(wc);
152 if ((width = wcwidth(wc)) > 0)
153 column += width;
154 continue;
155
156 case '\n':
157 putwchar(wc);
158 column = 0;
159 continue;
160 }
161 }
162 if (ferror(stdin)) {
163 warn("%s", curfile);
164 rval = 1;
165 }
166 } while (argc > 0);
167 exit(rval);
168 }
169
170 static void
171 getstops(char *cp)
172 {
173 int i;
174
175 nstops = 0;
176 for (;;) {
177 i = 0;
178 while (*cp >= '0' && *cp <= '9')
179 i = i * 10 + *cp++ - '0';
180 if (i <= 0)
181 errx(1, "bad tab stop spec");
182 if (nstops > 0 && i <= tabstops[nstops-1])
183 errx(1, "bad tab stop spec");
184 if (nstops == sizeof(tabstops) / sizeof(*tabstops))
185 errx(1, "too many tab stops");
186 tabstops[nstops++] = i;
187 if (*cp == 0)
188 break;
189 if (*cp != ',' && !isblank((unsigned char)*cp))
190 errx(1, "bad tab stop spec");
191 cp++;
192 }
193 }
194
195 static void
196 usage(void)
197 {
198 (void)fprintf (stderr, "usage: expand [-t tablist] [file ...]\n");
199 exit(1);
200 }