summaryrefslogtreecommitdiff
path: root/src/columnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/columnt.c')
-rw-r--r--src/columnt.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/columnt.c b/src/columnt.c
new file mode 100644
index 0000000..9e4cf0e
--- /dev/null
+++ b/src/columnt.c
@@ -0,0 +1,104 @@
+#include <unistd.h>
+#include "alloc.h"
+#include "logmsg.h"
+#include "buffer.h"
+#include "stralloc.h"
+#include "exit.h"
+#include "readclose.h"
+
+#define WHO "columnt"
+
+#define BSIZE 4096
+
+char outbuf[BSIZE];
+buffer bo = BUFFER_INIT(write,1,outbuf,sizeof(outbuf));
+
+void nomem() { logmsg(WHO,111,FATAL,"out of memory"); }
+void die_read() { logmsg(WHO,110,ERROR,"unable to read input: "); }
+void die_write() { logmsg(WHO,110,ERROR,"unable to write output: "); }
+
+stralloc file = {0};
+int *width;
+int maxfield = 0;
+
+void nothing()
+{
+ ;
+}
+
+void printline()
+{
+ if (buffer_put(&bo,"\n",1) == -1) die_write();
+}
+
+void maxfield_check(int fieldnum,char *buf,int len)
+{
+ if (fieldnum > maxfield) maxfield = fieldnum;
+}
+
+void width_check(int fieldnum,char *buf,int len)
+{
+ if (len > width[fieldnum]) width[fieldnum] = len;
+}
+
+void width_init()
+{
+ int i;
+
+ width = (int *) alloc((maxfield + 1) * sizeof(int));
+ if (!width) nomem();
+ for (i = 0; i <= maxfield; ++i)
+ width[i] = 0;
+}
+
+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();
+}
+
+void split(void (*dofield)(), void (*doline)())
+{
+ 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);
+}