#include #include "alloc.h" #include "buffer.h" #include "exit.h" #include "logmsg.h" #include "readclose.h" #include "stralloc.h" #define WHO "columnt" #define BSIZE 4096 char outbuf[BSIZE]; buffer bo = BUFFER_INIT(write, 1, outbuf, sizeof(outbuf)); static void nomem() { logmsg(WHO, 111, FATAL, "out of memory"); } static void die_read() { logmsg(WHO, 110, ERROR, "unable to read input: "); } static void die_write() { logmsg(WHO, 110, ERROR, "unable to write output: "); } stralloc file = {0}; int *width; int maxfield = 0; static void nothing() {} static void printline() { if (buffer_put(&bo, "\n", 1) == -1) die_write(); } static void maxfield_check(int fieldnum, char *buf, int len) { if (fieldnum > maxfield) maxfield = fieldnum; } static void width_check(int fieldnum, char *buf, int len) { if (len > width[fieldnum]) width[fieldnum] = len; } static void width_init() { int i; width = (int *)alloc((maxfield + 1) * sizeof(int)); if (!width) nomem(); for (i = 0; i <= maxfield; ++i) width[i] = 0; } static void printfield(int fieldnum, char *buf, int len) { int i; if (fieldnum < maxfield) for (i = len; i < width[fieldnum]; ++i) if (buffer_put(&bo, " ", 1) == -1) die_write(); if (buffer_put(&bo, buf, len) == -1) die_write(); if (fieldnum < maxfield) if (buffer_put(&bo, " ", 2) == -1) die_write(); } static void split(void (*dofield)(int, char *, int), void (*doline)(void)) { int i; int j; int fieldpos; int fieldnum; for (j = i = 0; j < file.len; ++j) if (file.s[j] == '\n') { fieldnum = 0; for (;;) { while ((file.s[i] == ' ') || (file.s[i] == '\t')) ++i; if (i == j) break; fieldpos = i; while ((file.s[i] != ' ') && (file.s[i] != '\t') && (file.s[i] != '\n')) ++i; dofield(fieldnum++, file.s + fieldpos, i - fieldpos); } doline(); i = j + 1; } } int main() { if (readclose_append(0, &file, BSIZE) == -1) die_read(); if (!file.len) _exit(0); if (file.s[file.len - 1] != '\n') if (!stralloc_append(&file, "\n")) nomem(); split(maxfield_check, nothing); width_init(); split(width_check, nothing); split(printfield, printline); if (buffer_flush(&bo) == -1) die_write(); _exit(0); }