csv2tsv.c - randomcrap - random crap programs of varying quality
(HTM) git clone git://git.codemadness.org/randomcrap
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
csv2tsv.c (1365B)
---
1 /* CSV to TSV: handles newlines in strings and "" quote escaping */
2 #include <stdio.h>
3
4 #define GETCHAR getchar_unlocked
5 #define PUTCHAR putchar_unlocked
6
7 void
8 put(int c)
9 {
10 switch (c) {
11 case '\\': PUTCHAR('\\'); PUTCHAR('\\'); break;
12 case '\n': PUTCHAR('\\'); PUTCHAR('n'); break;
13 case '\t': PUTCHAR('\\'); PUTCHAR('t'); break;
14 default:
15 /* ignore control-characters */
16 if ((unsigned char)c < 0x20 || (unsigned char)c == 0x7f)
17 break;
18 PUTCHAR(c);
19 break;
20 }
21 }
22
23 int
24 main(int argc, char *argv[])
25 {
26 size_t i, v;
27 int c, separator = argc > 1 ? argv[1][0] : ','; /* default separator */
28
29 for (i = v = 0; (c = GETCHAR()) != EOF;) {
30 parse:
31 switch (c) {
32 case '"':
33 while ((c = GETCHAR()) != EOF) {
34 if (c == '"') {
35 if ((c = GETCHAR()) == EOF)
36 goto end;
37 else if (c != '"')
38 goto parse;
39 }
40 put(c);
41 v++;
42 }
43 break;
44 case '\n': /* new record */
45 PUTCHAR('\n');
46 i = v = 0;
47 break;
48 case '\r': /* ignore CR */
49 break;
50 default:
51 if (c == separator) {
52 PUTCHAR('\t');
53 i++;
54 } else {
55 put(c);
56 v++;
57 }
58 }
59 }
60 end:
61 /* handle end of record without newline */
62 if (i || v)
63 PUTCHAR('\n');
64
65 if (ferror(stdin)) {
66 fprintf(stderr, "read error: <stdin>\n");
67 return 2;
68 } else if (fflush(stdout) || ferror(stdout)) {
69 fprintf(stderr, "write error: <stdout>\n");
70 return 2;
71 }
72
73 return 0;
74 }