expand.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       expand.c (2300B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <stdint.h>
            3 #include <stdlib.h>
            4 #include <string.h>
            5 
            6 #include "utf.h"
            7 #include "util.h"
            8 
            9 static int     iflag      = 0;
           10 static size_t *tablist    = NULL;
           11 static size_t  tablistlen = 0;
           12 
           13 static size_t
           14 parselist(const char *s)
           15 {
           16         size_t i;
           17         char  *p, *tmp;
           18 
           19         tmp = estrdup(s);
           20         for (i = 0; (p = strsep(&tmp, " ,")); i++) {
           21                 if (*p == '\0')
           22                         eprintf("empty field in tablist\n");
           23                 tablist = ereallocarray(tablist, i + 1, sizeof(*tablist));
           24                 tablist[i] = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX));
           25                 if (i > 0 && tablist[i - 1] >= tablist[i])
           26                         eprintf("tablist must be ascending\n");
           27         }
           28         tablist = ereallocarray(tablist, i + 1, sizeof(*tablist));
           29         /* tab length = 1 for the overflowing case later in the matcher */
           30         tablist[i] = 1;
           31 
           32         return i;
           33 }
           34 
           35 static int
           36 expand(const char *file, FILE *fp)
           37 {
           38         size_t bol = 1, col = 0, i;
           39         Rune r;
           40 
           41         while (efgetrune(&r, fp, file)) {
           42                 switch (r) {
           43                 case '\t':
           44                         if (tablistlen == 1)
           45                                 i = 0;
           46                         else for (i = 0; i < tablistlen; i++)
           47                                 if (col < tablist[i])
           48                                         break;
           49                         if (bol || !iflag) {
           50                                 do {
           51                                         col++;
           52                                         putchar(' ');
           53                                 } while (col % tablist[i]);
           54                         } else {
           55                                 putchar('\t');
           56                                 col = tablist[i];
           57                         }
           58                         break;
           59                 case '\b':
           60                         bol = 0;
           61                         if (col)
           62                                 col--;
           63                         putchar('\b');
           64                         break;
           65                 case '\n':
           66                         bol = 1;
           67                         col = 0;
           68                         putchar('\n');
           69                         break;
           70                 default:
           71                         col++;
           72                         if (r != ' ')
           73                                 bol = 0;
           74                         efputrune(&r, stdout, "<stdout>");
           75                         break;
           76                 }
           77         }
           78 
           79         return 0;
           80 }
           81 
           82 static void
           83 usage(void)
           84 {
           85         eprintf("usage: %s [-i] [-t tablist] [file ...]\n", argv0);
           86 }
           87 
           88 int
           89 main(int argc, char *argv[])
           90 {
           91         FILE *fp;
           92         int ret = 0;
           93         char *tl = "8";
           94 
           95         ARGBEGIN {
           96         case 'i':
           97                 iflag = 1;
           98                 break;
           99         case 't':
          100                 tl = EARGF(usage());
          101                 if (!*tl)
          102                         eprintf("tablist cannot be empty\n");
          103                 break;
          104         default:
          105                 usage();
          106         } ARGEND
          107 
          108         tablistlen = parselist(tl);
          109 
          110         if (!argc) {
          111                 expand("<stdin>", stdin);
          112         } else {
          113                 for (; *argv; argc--, argv++) {
          114                         if (!strcmp(*argv, "-")) {
          115                                 *argv = "<stdin>";
          116                                 fp = stdin;
          117                         } else if (!(fp = fopen(*argv, "r"))) {
          118                                 weprintf("fopen %s:", *argv);
          119                                 ret = 1;
          120                                 continue;
          121                         }
          122                         expand(*argv, fp);
          123                         if (fp != stdin && fshut(fp, *argv))
          124                                 ret = 1;
          125                 }
          126         }
          127 
          128         ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
          129 
          130         return ret;
          131 }