PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
entab.c File Reference
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
Include dependency graph for entab.c:

Go to the source code of this file.

Macros

#define PG_BINARY_R   "r"
 
#define NUL   '\0'
 
#define TRUE   1
 
#define FALSE   0
 

Functions

static void output_accumulated_spaces (int *prv_spaces, char **dst)
 
static void trim_trailing_whitespace (int *prv_spaces, char **dst, char *out_line)
 
int main (int argc, char **argv)
 

Variables

char * optarg
 
int optind
 

Macro Definition Documentation

#define FALSE   0

Definition at line 24 of file entab.c.

Referenced by main().

#define NUL   '\0'

Definition at line 18 of file entab.c.

Referenced by main().

#define PG_BINARY_R   "r"

Definition at line 15 of file entab.c.

Referenced by main().

#define TRUE   1

Definition at line 21 of file entab.c.

Referenced by main().

Function Documentation

int main ( int  argc,
char **  argv 
)

Definition at line 50 of file entab.c.

References FALSE, getopt(), NUL, NULL, optarg, optind, output_accumulated_spaces(), PG_BINARY_R, strerror(), trim_trailing_whitespace(), and TRUE.

51 {
52  int tab_size = 8,
53  min_spaces = 2,
54  only_comment_periods = FALSE,
55  protect_quotes = FALSE,
56  protect_leading_whitespace = FALSE,
57  del_tabs = FALSE,
58  clip_lines = FALSE,
59  in_comment = FALSE,
60  was_period = FALSE,
61  prv_spaces,
62  col_in_tab,
63  escaped,
64  nxt_spaces,
65  in_leading_whitespace;
66  char in_line[BUFSIZ],
67  out_line[BUFSIZ],
68  *src,
69  *dst,
70  quote_char,
71  *cp;
72  int ch;
73  FILE *in_file;
74 
75  if ((cp = strrchr(argv[0], '/')) != NULL)
76  ++cp;
77  else
78  cp = argv[0];
79  if (strcmp(cp, "detab") == 0)
80  del_tabs = 1;
81 
82  while ((ch = getopt(argc, argv, "cdhlmqs:t:")) != -1)
83  switch (ch)
84  {
85  case 'c':
86  clip_lines = TRUE;
87  break;
88  case 'd':
89  del_tabs = TRUE;
90  break;
91  case 'l':
92  protect_leading_whitespace = TRUE;
93  break;
94  case 'm':
95  /* only process text followed by periods in C comments */
96  only_comment_periods = TRUE;
97  break;
98  case 'q':
99  protect_quotes = TRUE;
100  break;
101  case 's':
102  min_spaces = atoi(optarg);
103  break;
104  case 't':
105  tab_size = atoi(optarg);
106  break;
107  case 'h':
108  case '?':
109  fprintf(stderr, "USAGE: %s [ -cdqst ] [file ...]\n\
110  -c (clip trailing whitespace)\n\
111  -d (delete tabs)\n\
112  -l (protect leading whitespace)\n\
113  -m (only C comment periods)\n\
114  -q (protect quotes)\n\
115  -s minimum_spaces\n\
116  -t tab_width\n",
117  cp);
118  exit(0);
119  }
120 
121  argv += optind;
122  argc -= optind;
123 
124  /* process arguments */
125  do
126  {
127  if (argc < 1)
128  in_file = stdin;
129  else
130  {
131  if ((in_file = fopen(*argv, PG_BINARY_R)) == NULL)
132  {
133  fprintf(stderr, "Cannot open file %s: %s\n", argv[0], strerror(errno));
134  exit(1);
135  }
136  argv++;
137  }
138 
139  escaped = FALSE;
140 
141  /* process lines */
142  while (fgets(in_line, sizeof(in_line), in_file) != NULL)
143  {
144  col_in_tab = 0;
145  prv_spaces = 0;
146  src = in_line; /* points to current processed char */
147  dst = out_line; /* points to next unallocated char */
148  if (escaped == FALSE)
149  quote_char = ' ';
150  escaped = FALSE;
151  in_leading_whitespace = TRUE;
152 
153  /* process line */
154  while (*src != NUL)
155  {
156  col_in_tab++;
157 
158  /* look backward so we handle slash-star-slash properly */
159  if (!in_comment && src > in_line &&
160  *(src - 1) == '/' && *src == '*')
161  in_comment = TRUE;
162  else if (in_comment && *src == '*' && *(src + 1) == '/')
163  in_comment = FALSE;
164 
165  /* Is this a potential space/tab replacement? */
166  if ((!only_comment_periods || (in_comment && was_period)) &&
167  (!protect_leading_whitespace || !in_leading_whitespace) &&
168  quote_char == ' ' && (*src == ' ' || *src == '\t'))
169  {
170  if (*src == '\t')
171  {
172  prv_spaces += tab_size - col_in_tab + 1;
173  col_in_tab = tab_size;
174  }
175  else
176  prv_spaces++;
177 
178  /* Are we at a tab stop? */
179  if (col_in_tab == tab_size)
180  {
181  /*
182  * Is the next character going to be a tab? We do tab
183  * replacement in the current spot if the next char is
184  * going to be a tab and ignore min_spaces.
185  */
186  nxt_spaces = 0;
187  while (1)
188  {
189  /* Have we reached non-whitespace? */
190  if (*(src + nxt_spaces + 1) == NUL ||
191  (*(src + nxt_spaces + 1) != ' ' &&
192  *(src + nxt_spaces + 1) != '\t'))
193  break;
194  /* count spaces */
195  if (*(src + nxt_spaces + 1) == ' ')
196  ++nxt_spaces;
197  /* Have we found a forward tab? */
198  if (*(src + nxt_spaces + 1) == '\t' ||
199  nxt_spaces == tab_size)
200  {
201  nxt_spaces = tab_size;
202  break;
203  }
204  }
205  /* Do tab replacment for spaces? */
206  if ((prv_spaces >= min_spaces ||
207  nxt_spaces == tab_size) &&
208  del_tabs == FALSE)
209  {
210  *(dst++) = '\t';
211  prv_spaces = 0;
212  }
213  else
214  output_accumulated_spaces(&prv_spaces, &dst);
215  }
216  }
217  /* Not a potential space/tab replacement */
218  else
219  {
220  /* allow leading stars in comments */
221  if (in_leading_whitespace && *src != ' ' && *src != '\t' &&
222  (!in_comment || *src != '*'))
223  in_leading_whitespace = FALSE;
224  was_period = (*src == '.');
225  /* output accumulated spaces */
226  output_accumulated_spaces(&prv_spaces, &dst);
227  /* This can only happen in a quote. */
228  if (*src == '\t')
229  col_in_tab = 0;
230  /* visual backspace? */
231  if (*src == '\b')
232  col_in_tab -= 2;
233  /* Do we process quotes? */
234  if (escaped == FALSE && protect_quotes == TRUE)
235  {
236  if (*src == '\\')
237  escaped = TRUE;
238  /* Is this a quote character? */
239  if (*src == '"' || *src == '\'')
240  {
241  /* toggle quote mode */
242  if (quote_char == ' ')
243  quote_char = *src;
244  else if (*src == quote_char)
245  quote_char = ' ';
246  }
247  }
248  /* newlines/CRs do not terminate escapes */
249  else if (*src != '\r' && *src != '\n')
250  escaped = FALSE;
251 
252  /* reached newline/CR; clip line? */
253  if ((*src == '\r' || *src == '\n') &&
254  clip_lines == TRUE &&
255  quote_char == ' ' &&
256  escaped == FALSE)
257  trim_trailing_whitespace(&prv_spaces, &dst, out_line);
258  *(dst++) = *src;
259  }
260  col_in_tab %= tab_size;
261  ++src;
262  }
263  /* for cases where the last line of file has no newline */
264  if (clip_lines == TRUE && escaped == FALSE)
265  trim_trailing_whitespace(&prv_spaces, &dst, out_line);
266  output_accumulated_spaces(&prv_spaces, &dst);
267  *dst = NUL;
268 
269  if (fputs(out_line, stdout) == EOF)
270  {
271  fprintf(stderr, "Cannot write to output file %s: %s\n", argv[0], strerror(errno));
272  exit(1);
273  }
274  }
275  } while (--argc > 0);
276  return 0;
277 }
static void output_accumulated_spaces(int *prv_spaces, char **dst)
Definition: entab.c:32
int getopt(int nargc, char *const *nargv, const char *ostr)
Definition: getopt.c:72
#define TRUE
Definition: entab.c:21
#define FALSE
Definition: entab.c:24
#define PG_BINARY_R
Definition: entab.c:15
int optind
Definition: getopt.c:51
char * optarg
Definition: getopt.c:53
#define NULL
Definition: c.h:229
const char * strerror(int errnum)
Definition: strerror.c:19
#define NUL
Definition: entab.c:18
static void trim_trailing_whitespace(int *prv_spaces, char **dst, char *out_line)
Definition: entab.c:40
static void output_accumulated_spaces ( int *  prv_spaces,
char **  dst 
)
static

Definition at line 32 of file entab.c.

Referenced by main().

33 {
34  for (; *prv_spaces > 0; (*prv_spaces)--)
35  *((*dst)++) = ' ';
36 }
static void trim_trailing_whitespace ( int *  prv_spaces,
char **  dst,
char *  out_line 
)
static

Definition at line 40 of file entab.c.

Referenced by main().

41 {
42  while (*dst > out_line &&
43  (*((*dst) - 1) == ' ' || *((*dst) - 1) == '\t'))
44  (*dst)--;
45  *prv_spaces = 0;
46 }

Variable Documentation

char* optarg

Definition at line 53 of file getopt.c.

Referenced by getopt(), and main().

int optind

Definition at line 51 of file getopt.c.

Referenced by getopt(), and main().