blob: 5345c657f5758b748d1b62baac6b24dcf237cb37 [file] [log] [blame]
/*
** entab.c - add tabs to a text file
** by Bruce Momjian (root@candle.pha.pa.us)
**
** src/tools/entab/entab.c
**
** version 1.3
**
** tabsize = 4
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#if defined(WIN32) || defined(__CYGWIN__)
#define PG_BINARY_R "rb"
#else
#define PG_BINARY_R "r"
#endif
#define NUL '\0'
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
void halt();
extern char *optarg;
extern int optind;
int
main(int argc, char **argv)
{
int tab_size = 8,
min_spaces = 2,
protect_quotes = FALSE,
del_tabs = FALSE,
clip_lines = FALSE,
prv_spaces,
col_in_tab,
escaped,
nxt_spaces;
char in_line[BUFSIZ],
out_line[BUFSIZ],
*src,
*dst,
quote_char,
*cp;
int ch;
FILE *in_file;
if ((cp = strrchr(argv[0], '/')) != NULL)
++cp;
else
cp = argv[0];
if (strcmp(cp, "detab") == 0)
del_tabs = 1;
while ((ch = getopt(argc, argv, "cdhqs:t:")) != -1)
switch (ch)
{
case 'c':
clip_lines = TRUE;
break;
case 'd':
del_tabs = TRUE;
break;
case 'q':
protect_quotes = TRUE;
break;
case 's':
min_spaces = atoi(optarg);
break;
case 't':
tab_size = atoi(optarg);
break;
case 'h':
case '?':
halt("USAGE: %s [ -cdqst ] [file ...]\n\
-c (clip trailing whitespace)\n\
-d (delete tabs)\n\
-q (protect quotes)\n\
-s minimum_spaces\n\
-t tab_width\n",
cp);
}
argv += optind;
argc -= optind;
do
{
if (argc < 1)
in_file = stdin;
else
{
if ((in_file = fopen(*argv, PG_BINARY_R)) == NULL)
halt("PERROR: Cannot open file %s\n", argv[0]);
argv++;
}
escaped = FALSE;
while (fgets(in_line, sizeof(in_line), in_file) != NULL)
{
col_in_tab = 0;
prv_spaces = 0;
src = in_line; /* points to current processed char */
dst = out_line; /* points to next unallocated char */
if (escaped == FALSE)
quote_char = ' ';
escaped = FALSE;
while (*src != NUL)
{
col_in_tab++;
if (quote_char == ' ' && (*src == ' ' || *src == '\t'))
{
if (*src == '\t')
{
prv_spaces += tab_size - col_in_tab + 1;
col_in_tab = tab_size;
}
else
prv_spaces++;
if (col_in_tab == tab_size)
{
/*
* Is the next character going to be a tab? Needed to
* do tab replacement in current spot if next char is
* going to be a tab, ignoring min_spaces
*/
nxt_spaces = 0;
while (1)
{
if (*(src + nxt_spaces + 1) == NUL ||
(*(src + nxt_spaces + 1) != ' ' &&
*(src + nxt_spaces + 1) != '\t'))
break;
if (*(src + nxt_spaces + 1) == ' ')
++nxt_spaces;
if (*(src + nxt_spaces + 1) == '\t' ||
nxt_spaces == tab_size)
{
nxt_spaces = tab_size;
break;
}
}
if ((prv_spaces >= min_spaces ||
nxt_spaces == tab_size) &&
del_tabs == FALSE)
{
*(dst++) = '\t';
prv_spaces = 0;
}
else
{
for (; prv_spaces > 0; prv_spaces--)
*(dst++) = ' ';
}
}
}
else
{
for (; prv_spaces > 0; prv_spaces--)
*(dst++) = ' ';
if (*src == '\t') /* only when in quote */
col_in_tab = 0;
if (*src == '\b')
col_in_tab -= 2;
if (escaped == FALSE && protect_quotes == TRUE)
{
if (*src == '\\')
escaped = TRUE;
if (*src == '"' || *src == '\'')
if (quote_char == ' ')
quote_char = *src;
else if (*src == quote_char)
quote_char = ' ';
}
else if (*src != '\r' && *src != '\n')
escaped = FALSE;
if ((*src == '\r' || *src == '\n') &&
quote_char == ' ' &&
clip_lines == TRUE &&
escaped == FALSE)
{
while (dst > out_line &&
(*(dst - 1) == ' ' || *(dst - 1) == '\t'))
dst--;
prv_spaces = 0;
}
*(dst++) = *src;
}
col_in_tab %= tab_size;
++src;
}
/* for cases where the last line of file has no newline */
if (clip_lines == TRUE && escaped == FALSE)
{
while (dst > out_line &&
(*(dst - 1) == ' ' || *(dst - 1) == '\t'))
dst--;
prv_spaces = 0;
}
for (; prv_spaces > 0; prv_spaces--)
*(dst++) = ' ';
*dst = NUL;
if (fputs(out_line, stdout) == EOF)
halt("PERROR: Error writing output.\n");
}
} while (--argc > 0);
return 0;
}