Expand: A Larger Example

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>

/*
 * expand - expand tabs to equivalent spaces
 */
int     nstops;
int     tabstops[100];

static  void    getstops __P((char *));
        int     main __P((intchar **));
static  void    usage __P((void));

int
main(argc, argv)
        int argc;
        char *argv[];
{
        int c, column;
        int n;

        /* handle obsolete syntax */
        while (argc > 1 && argv[1][0] && isdigit(argv[1][1])) {
                getstops(&argv[1][1]);
                argc--; argv++;
        }

        while ((c = getopt (argc, argv, "t:")) != -1) {
                switch (c) {
                case 't':
                        getstops(optarg);
                        break;
                case '?':
                default:
                        usage();
                        /* NOTREACHED */
                }
        }
        argc -= optind;
        argv += optind;

        do {
                if (argc > 0) {
                        if (freopen(argv[0], "r"stdin) == NULL) {
                                perror(argv[0]);
                                exit(1);
                        }
                        argc--, argv++;
                }
                column = 0;
                while ((c = getchar()) != EOF) {
                        switch (c) {
                        case '\t':
                                if (nstops == 0) {
                                        do {
                                                putchar(' ');
                                                column++;
                                        } while (column & 07);
                                        continue;
                                }
                                if (nstops == 1) {
                                        do {
                                                putchar(' ');
                                                column++;
                                        } while (((column - 1) % tabstops[0]) != (tabstops[0] - 1));
                                        continue;
                                }
                                for (n = 0; n < nstops; n++)
                                        if (tabstops[n] > column)
                                                break;
                                if (n == nstops) {
                                        putchar(' ');
                                        column++;
                                        continue;
                                }
                                while (column < tabstops[n]) {
                                        putchar(' ');
                                        column++;
                                }
                                continue;

                        case '\b':
                                if (column)
                                        column--;
                                putchar('\b');
                                continue;

                        default:
                                putchar(c);
                                column++;
                                continue;

                        case '\n':
                                putchar(c);
                                column = 0;
                                continue;
                        }
                }
        } while (argc > 0);
        exit(0);
}

static void
getstops(cp)
        char *cp;
{
        int i;

        nstops = 0;
        for (;;) {
                i = 0;
                while (*cp >= '0' && *cp <= '9')
                        i = i * 10 + *cp++ - '0';
                if (i <= 0 || i > 256) {
bad:
                        fprintf(stderr"Bad tab stop spec\n");
                        exit(1);
                }
                if (nstops > 0 && i <= tabstops[nstops-1])
                        goto bad;
                tabstops[nstops++] = i;
                if (*cp == 0)
                        break;
                if (*cp != ',' && *cp != ' ')
                        goto bad;
                cp++;
        }
}

static void
usage()
{
        (void)fprintf (stderr"usage: expand [-t tablist] [file ...]\n");
        exit(1);
}