#include #include #include #include static void wr2(Biobuf *bo, short n) { Bwrite(bo, &n, 2); } static void wrn(Biobuf *bo, void *buf, int len) { Bwrite(bo, buf, len); } static void str(Biobuf *bo, int r, int c, char *s) { int len; len = strlen(s); wr2(bo, 0x0204); /* string object */ wr2(bo, len + 8); /* bytes following */ wr2(bo, r); wr2(bo, c); wr2(bo, 0); /* format type - none */ wr2(bo, len); /* string length */ wrn(bo, s, len); } static void num(Biobuf *bo, int r, int c, double n) { wr2(bo, 0x0203); /* number object */ wr2(bo, 14); /* bytes following */ wr2(bo, r); wr2(bo, c); wr2(bo, 0); /* format type - none */ wrn(bo, &n, sizeof(double)); } static void cell(Biobuf *bo, int r, int c, char *s) { char *t; double n; n = strtod(s, &t); if(*s == 0 || *t != 0) str(bo, r, c, s); else num(bo, r, c, n); } static void usage(void) { fprint(2, "usage: %s [-d c] []\n", argv0); fprint(2, " -d c set field deliminator\n"); exits("usage"); } void main(int argc, char *argv[]) { int n, r, c; char *delim, *line, *a[128]; Biobuf bout, *bo = &bout; Biobuf binp, *bi = &binp; delim = "|"; ARGBEGIN{ case 'd': delim = EARGF(usage()); break; default: usage(); break; }ARGEND; switch(argc){ case 1: bi = Bopen(argv[0], OREAD); if(bi == nil) sysfatal("%s cannot open - %r\n", argv[0]); break; case 0: Binit(bi, OREAD, 0); break; default: usage(); break; } Binit(bo, OWRITE, 1); wr2(bo, 0x0809); /* Start of file */ wr2(bo, 4); /* bytes following */ wr2(bo, 0x500); /* Biff V5 file */ wr2(bo, 0x10); /* is a worksheet */ while((line = Brdline(bi, '\n')) != nil){ line[Blinelen(bi) -1] = 0; n = getfields(line, a, nelem(a), 0, delim); if(n < 2) /* blank lines */ continue; if(a[0][0] == '#') /* comments */ continue; r = atoi(a[0]) -1; /* -1 as excel ordinates start at zero */ for(c = 1; c < n; c++) cell(bo, r, c-1, a[c]); /* -1 as excel ordinates start at zero */ } wr2(bo, 0xa); /* End of file */ wr2(bo, 0); /* bytes following */ Bterm(bi); Bterm(bo); exits(nil); }