1 /* $OpenBSD: unexpand.c,v 1.13 2016/10/11 16:22:15 millert Exp $ */
2 /* $NetBSD: unexpand.c,v 1.5 1994/12/24 17:08:05 cgd 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 /*
34 * unexpand - put tabs into a file replacing blanks
35 */
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 char genbuf[BUFSIZ];
43 char linebuf[BUFSIZ];
44
45 void tabify(bool);
46
47 int
main(int argc,char * argv[])48 main(int argc, char *argv[])
49 {
50 bool all = false;
51 char *cp;
52
53 if (pledge("stdio rpath", NULL) == -1) {
54 perror("pledge");
55 exit(1);
56 }
57
58 argc--, argv++;
59 if (argc > 0 && argv[0][0] == '-') {
60 if (strcmp(argv[0], "-a") != 0) {
61 fprintf(stderr, "usage: unexpand [-a] [file ...]\n");
62 exit(1);
63 }
64 all = true;
65 argc--, argv++;
66 }
67 do {
68 if (argc > 0) {
69 if (freopen(argv[0], "r", stdin) == NULL) {
70 perror(argv[0]);
71 exit(1);
72 }
73 argc--, argv++;
74 }
75 while (fgets(genbuf, BUFSIZ, stdin) != NULL) {
76 for (cp = linebuf; *cp; cp++)
77 continue;
78 if (cp > linebuf)
79 cp[-1] = 0;
80 tabify(all);
81 printf("%s", linebuf);
82 }
83 } while (argc > 0);
84 exit(0);
85 }
86
87 void
tabify(bool all)88 tabify(bool all)
89 {
90 char *cp, *dp;
91 int dcol;
92 int ocol;
93 size_t len;
94
95 ocol = 0;
96 dcol = 0;
97 cp = genbuf;
98 dp = linebuf;
99 len = sizeof linebuf;
100
101 for (;;) {
102 switch (*cp) {
103
104 case ' ':
105 dcol++;
106 break;
107
108 case '\t':
109 dcol += 8;
110 dcol &= ~07;
111 break;
112
113 default:
114 while (((ocol + 8) &~ 07) <= dcol) {
115 if (ocol + 1 == dcol)
116 break;
117 if (len > 1) {
118 *dp++ = '\t';
119 len--;
120 }
121 ocol += 8;
122 ocol &= ~07;
123 }
124 while (ocol < dcol) {
125 if (len > 1) {
126 *dp++ = ' ';
127 len--;
128 }
129 ocol++;
130 }
131 if (*cp == '\0' || !all) {
132 strlcpy(dp, cp, len);
133 return;
134 }
135 *dp++ = *cp;
136 len--;
137 ocol++;
138 dcol++;
139 }
140 cp++;
141 }
142 }
143