fungeen

1980's television with knobs displaying random computer code

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAXLINE 1000 #define MAXTABS 20 #define COLSTART 1 #define TABINTERVAL 2 #define TABARRAY 3 #define TOOMANY 4 #define ON 1 #define OFF 0 /* detab syntax detab -[start column] +[tab interval] example: detab -2 +8 detab -t [list of tab stops] example: detab -t 8 16 24 31 60 62 76 detab replaces tabs with spaces. Unless otherwise specified detab uses the value of default_interval as the tab interval. */ int testop(char *); int default_interval = 4, user_interval = OFF, colstart = OFF, tab_array = OFF, tabstops[MAXTABS]; int main(int argc, char *argv[]) { int argi, c, col, coltemp, good = OFF, i, interval, nspaces, ntabs = 0, ntabs_found, len, result = 0, *t1 = tabstops, *t2, tmp, tmp2; char line[MAXLINE], templine[MAXLINE], *lineptr = line, *p1, *p2, *q1, *q2; size_t maxline = MAXLINE; char *p, **pp = argv; for (argi = 1; argi < argc; argi++) { c = testop(*++pp); switch (c) { case COLSTART: colstart = (-1 * atoi(*pp)); /* compensate for hyphen, make positive */ break; case TABINTERVAL: user_interval = atoi(*pp); break; case TABARRAY: good = (isdigit(**pp) && tab_array) ? ON : OFF; /* it's a number, add to array */ if (good) { *t1++ = atoi(*pp); /* convert string to int */ *t1 = -1; /* terminate int array */ ++ntabs; /* count number of tabs in array */ } break; case TOOMANY: printf("detab: too many arguments\n"); argi += argc; result = -1; break; default: printf("detab: illegal option %s\n", *pp); argi += argc; result = -1; break; } } if (argi != argc) { /* error message */ printf("%s\n%3s%s\n", "Usage: detab -[start column] +[tab interval]", "", "ex. detab -4 +8"); printf("%7s%s\n%3s%s\n", "", "detab -t [list of tab stops]", "", "ex. detab -t 4 8 22"); } else while ((len = getline(&lineptr, &maxline, stdin)) > 0) { /* get a line */ ntabs_found = 0; for (i=0; i < (strlen(line)); i++) { /* substitute tabs with spaces */ col = 1, nspaces = 0, p1 = line, q1 = templine, q2 = templine, t2 = tabstops; for (; (*p1 != '\t') && (*p1 != '\0'); col++, p1++) ; good = (*p1 == '\t') ? ON : OFF; if (good) { p2 = p1++, ++ntabs_found; /* record position of tab, increment tab count */ while ((*q1++ = *p1++) != '\n') /* copy everything past tab to templine */ ; *--q1 = '\0'; /* delete '\n', terminate templine */ /*** start todo ***/ if (tab_array) { /* tab array */ if (ntabs_found > ntabs) col = *t2; /* out of tab stops */ else { t2 += (ntabs_found - 1); /* t2 index must correspond to number of tabs found */ if (col == *t2) /* tab found on tab stop */ ++t2; else if (col > *t2) { for (; col > *t2; t2++) /* find nearest tabstop */ ; if (col == *t2) /* tab found on a tab stop */ ++t2; } } } /*** end todo ***/ coltemp = col; /* record column */ interval = (user_interval) ? user_interval : default_interval; if (!tab_array && colstart) { /* start column */ if (col < colstart) /* tab found before start column */ col = colstart; else if (col == colstart) /* tab found on the start column */ col += interval; /* go past it */ else { tmp = colstart, tmp2 = interval; while (col > (tmp + tmp2)) /* find next tab stop */ tmp2 += tmp2; col = (col == tmp + tmp2) ? col += interval : tmp + tmp2; /* if tab found on tab stop, go past it */ } } if (!tab_array && !colstart && !(col % (interval +1))) /* tab was found on a tab stop */ ++col; /* go past it */ while (!tab_array && !colstart && (col++ % interval)) /* find nearest tab stop */ ; nspaces = (tab_array) ? *t2 - col : col - coltemp; /* number of spaces to insert */ while (nspaces-- > 0) /* insert spaces */ *p2++ = '*'; while (*q2 != '\0') /* concatenate templine back to line */ *p2++ = *q2++; *p2 = '\0'; /* terminate line */ } } printf("%s\n", line); result = (good) ? 0 : -1; } return result; } int testop(char *p) /* test arguments are valid */ { int c, good = OFF, result = 0, *t = tabstops; if (*p == '-') { /* may be a start column or a tab stop flag */ good = (!tab_array && !colstart) ? ON : OFF; if (good && isdigit(*++p) && *p != '0') { /* can't start with zero */ while ((c = isdigit(*p++))) /* check contains only digits */ ; if (c == '\0') { /* it's a number */ result = COLSTART; colstart = ON; } } else if (good && *p == 't') { result = TABARRAY; tab_array = ON; } else result = (!good) ? TOOMANY : -1; } else if (*p == '+') { /* may be a tab interval */ good = (!tab_array && !user_interval) ? ON : OFF; if (good && isdigit(*++p) && *p != '0') { /* column interval can't start with zero */ while ((c = isdigit(*p++))) /* check contains only digits */ ; result = (c == '\0') ? TABINTERVAL : -1; user_interval = ON; } else result = (!good) ? TOOMANY : -1; } else if (isdigit(*p) && tab_array) { /* may be a tab stop */ good = (*p != '0') ? ON : OFF; /* can't start with zero */ while (good && isdigit(c = *p++)) /* check contains only digits */ ; good = (c == '\0') ? ON : OFF; result = (good) ? TABARRAY : -1; } else result = -1; /* invalid argument */ return result; }