]> granicus.if.org Git - postgresql/blob - src/tools/entab/entab.c
Reduce WAL activity for page splits:
[postgresql] / src / tools / entab / entab.c
1 /*
2 **              entab.c                 - add tabs to a text file
3 **              by Bruce Momjian (root@candle.pha.pa.us)
4 **
5 ** $PostgreSQL: pgsql/src/tools/entab/entab.c,v 1.17 2007/02/01 19:10:30 momjian Exp $
6 **
7 **      version 1.3
8 **
9 **              tabsize = 4
10 **
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <stdarg.h>
17
18 #if defined(WIN32) || defined(__CYGWIN__)
19 #define PG_BINARY_R "rb"
20 #else
21 #define PG_BINARY_R "r"
22 #endif
23
24 #define NUL                             '\0'
25
26 #ifndef TRUE
27 #define TRUE    1
28 #endif
29 #ifndef FALSE
30 #define FALSE   0
31 #endif
32
33 void            halt();
34
35 extern char *optarg;
36 extern int      optind;
37
38 int
39 main(int argc, char **argv)
40 {
41         int                     tab_size = 8,
42                                 min_spaces = 2,
43                                 protect_quotes = FALSE,
44                                 del_tabs = FALSE,
45                                 clip_lines = FALSE,
46                                 prv_spaces,
47                                 col_in_tab,
48                                 escaped,
49                                 nxt_spaces;
50         char            in_line[BUFSIZ],
51                                 out_line[BUFSIZ],
52                            *src,
53                            *dst,
54                                 quote_char,
55                            *cp;
56         int                     ch;
57         FILE       *in_file;
58
59         if ((cp = strrchr(argv[0], '/')) != NULL)
60                 ++cp;
61         else
62                 cp = argv[0];
63         if (strcmp(cp, "detab") == 0)
64                 del_tabs = 1;
65
66         while ((ch = getopt(argc, argv, "cdhqs:t:")) != -1)
67                 switch (ch)
68                 {
69                         case 'c':
70                                 clip_lines = TRUE;
71                                 break;
72                         case 'd':
73                                 del_tabs = TRUE;
74                                 break;
75                         case 'q':
76                                 protect_quotes = TRUE;
77                                 break;
78                         case 's':
79                                 min_spaces = atoi(optarg);
80                                 break;
81                         case 't':
82                                 tab_size = atoi(optarg);
83                                 break;
84                         case 'h':
85                         case '?':
86                                 halt("USAGE: %s [ -cdqst ] [file ...]\n\
87         -c (clip trailing whitespace)\n\
88         -d (delete tabs)\n\
89         -q (protect quotes)\n\
90         -s minimum_spaces\n\
91         -t tab_width\n",
92                                          cp);
93                 }
94
95         argv += optind;
96         argc -= optind;
97
98         do
99         {
100                 if (argc < 1)
101                         in_file = stdin;
102                 else
103                 {
104                         if ((in_file = fopen(*argv, PG_BINARY_R)) == NULL)
105                                 halt("PERROR:  Cannot open file %s\n", argv[0]);
106                         argv++;
107                 }
108
109                 escaped = FALSE;
110
111                 while (fgets(in_line, BUFSIZ, in_file) != NULL)
112                 {
113                         col_in_tab = 0;
114                         prv_spaces = 0;
115                         src = in_line;          /* points to current processed char */
116                         dst = out_line;         /* points to next unallocated char */
117                         if (escaped == FALSE)
118                                 quote_char = ' ';
119                         escaped = FALSE;
120
121                         while (*src != NUL)
122                         {
123                                 col_in_tab++;
124                                 if (quote_char == ' ' && (*src == ' ' || *src == '\t'))
125                                 {
126                                         if (*src == '\t')
127                                         {
128                                                 prv_spaces += tab_size - col_in_tab + 1;
129                                                 col_in_tab = tab_size;
130                                         }
131                                         else
132                                                 prv_spaces++;
133
134                                         if (col_in_tab == tab_size)
135                                         {
136                                                 /*
137                                                  * Is the next character going to be a tab? Needed to
138                                                  * do tab replacement in current spot if next char is
139                                                  * going to be a tab, ignoring min_spaces
140                                                  */
141                                                 nxt_spaces = 0;
142                                                 while (1)
143                                                 {
144                                                         if (*(src + nxt_spaces + 1) == NUL ||
145                                                                 (*(src + nxt_spaces + 1) != ' ' &&
146                                                                  *(src + nxt_spaces + 1) != '\t'))
147                                                                 break;
148                                                         if (*(src + nxt_spaces + 1) == ' ')
149                                                                 ++nxt_spaces;
150                                                         if (*(src + nxt_spaces + 1) == '\t' ||
151                                                                 nxt_spaces == tab_size)
152                                                         {
153                                                                 nxt_spaces = tab_size;
154                                                                 break;
155                                                         }
156                                                 }
157                                                 if ((prv_spaces >= min_spaces ||
158                                                          nxt_spaces == tab_size) &&
159                                                         del_tabs == FALSE)
160                                                 {
161                                                         *(dst++) = '\t';
162                                                         prv_spaces = 0;
163                                                 }
164                                                 else
165                                                 {
166                                                         for (; prv_spaces > 0; prv_spaces--)
167                                                                 *(dst++) = ' ';
168                                                 }
169                                         }
170                                 }
171                                 else
172                                 {
173                                         for (; prv_spaces > 0; prv_spaces--)
174                                                 *(dst++) = ' ';
175                                         if (*src == '\t')       /* only when in quote */
176                                                 col_in_tab = 0;
177                                         if (*src == '\b')
178                                                 col_in_tab -= 2;
179                                         if (escaped == FALSE && protect_quotes == TRUE)
180                                         {
181                                                 if (*src == '\\')
182                                                         escaped = TRUE;
183                                                 if (*src == '"' || *src == '\'')
184                                                         if (quote_char == ' ')
185                                                                 quote_char = *src;
186                                                         else if (*src == quote_char)
187                                                                 quote_char = ' ';
188                                         }
189                                         else if (*src != '\r' && *src != '\n')
190                                                 escaped = FALSE;
191
192                                         if ((*src == '\r' || *src == '\n') &&
193                                                 quote_char == ' ' &&
194                                                 clip_lines == TRUE &&
195                                                 escaped == FALSE)
196                                         {
197                                                 while (dst > out_line &&
198                                                            (*(dst - 1) == ' ' || *(dst - 1) == '\t'))
199                                                         dst--;
200                                                 prv_spaces = 0;
201                                         }
202                                         *(dst++) = *src;
203                                 }
204                                 col_in_tab %= tab_size;
205                                 ++src;
206                         }
207                         /* for cases where the last line of file has no newline */
208                         if (clip_lines == TRUE && escaped == FALSE)
209                         {
210                                 while (dst > out_line &&
211                                            (*(dst - 1) == ' ' || *(dst - 1) == '\t'))
212                                         dst--;
213                                 prv_spaces = 0;
214                         }
215                         for (; prv_spaces > 0; prv_spaces--)
216                                 *(dst++) = ' ';
217                         *dst = NUL;
218                         if (fputs(out_line, stdout) == EOF)
219                                 halt("PERROR:  Error writing output.\n");
220                 }
221         } while (--argc > 0);
222         return 0;
223 }