Commit | Line | Data |
---|---|---|
3b600ead TL |
1 | # |
2 | /* paste: concatenate corresponding lines of each file in parallel(GWRL) */ | |
3 | /* (-s option: serial concatenation like old (127's) paste command */ | |
4 | /* make : cc paste.c -lS */ | |
5 | # include <stdio.h> | |
6 | # define MAXOPNF 12 /* maximal no. of open files (not with -s option) */ | |
7 | # define MAXLINE 512 /* maximal line length */ | |
8 | #define RUB '\177' | |
9 | char del[MAXLINE] = {"\t"}; | |
10 | ||
11 | main(argc, argv) | |
12 | int argc; | |
13 | char ** argv; | |
14 | { | |
15 | int i, j, k, eofcount, nfiles; | |
16 | int delcount = { 1 } ; | |
17 | int onefile = { 0 } ; | |
18 | char outbuf[MAXLINE], c, l ; | |
19 | register char *p; | |
20 | FILE *inptr[MAXOPNF]; | |
21 | ||
22 | while (argc > 1 && argv[1][0] == '-' && (c = argv[1][1]) != '\0'){ | |
23 | switch (c) { | |
24 | case 's' : onefile++; | |
25 | c = argv[1][2]; | |
26 | argv[1]++; | |
27 | break ; | |
28 | case 'd' : argv[1] += 2; | |
29 | if((delcount = move(argv[1], &del[0])) == 0) diag("no delimiters\n",1);; | |
30 | break; | |
31 | default : | |
32 | diag("Usage: paste [-s] [-d<delimiterstring>] file1 file2 ...", 1); | |
33 | break; | |
34 | } | |
35 | --argc; | |
36 | ++argv; | |
37 | } /* end options */ | |
38 | --argc; | |
39 | ||
40 | if ( ! onefile) { /* not -s option: parallel line merging */ | |
41 | for (i = 0; argc >0 && i < MAXOPNF; i++) { | |
42 | if (argv[i + 1][0] == '-') { | |
43 | inptr[i] = stdin; | |
44 | } else inptr[i] = fopen(argv[i + 1], "r"); | |
45 | if (inptr[i] == NULL) { | |
46 | diag(argv[i + 1], 0); | |
47 | diag(" : cannot open\n", 1); | |
48 | } | |
49 | argc--; | |
50 | } | |
51 | if (argc > 0) diag("too many files\n",1); | |
52 | nfiles = i; | |
53 | ||
54 | do { | |
55 | p = &outbuf[0]; | |
56 | eofcount = 0; | |
57 | j = k = 0; | |
58 | for (i = 0; i < nfiles; i++) { | |
59 | while((c = getc(inptr[i])) != '\n' && c != EOF) { | |
60 | if (++j <= MAXLINE - 2) *p++ = c ; | |
61 | else { | |
62 | diag("line too long\n",1); | |
63 | } | |
64 | } | |
65 | if ( (l = del[k]) != RUB) *p++ = l; | |
66 | k = (k + 1) % delcount; | |
67 | if( c == EOF) eofcount++; | |
68 | } | |
69 | if (l != RUB) *--p = '\n'; else *p = '\n'; | |
70 | *++p = 0; | |
71 | if (eofcount < nfiles) fputs(outbuf, stdout); | |
72 | }while (eofcount < nfiles); | |
73 | ||
74 | } else { /* -s option: serial file pasting (old 127 paste command) */ | |
75 | p = &outbuf[0]; | |
76 | j = 0; | |
77 | k = 0; | |
78 | for (i = 1; i <= argc; i++) { | |
79 | if (argv[i][0] == '-') { | |
80 | inptr[0] = stdin; | |
81 | } else inptr[0] = fopen(argv[i], "r"); | |
82 | if (inptr[0] == NULL) { | |
83 | diag(argv[i], 0); | |
84 | diag(" : cannot open\n", 1); | |
85 | } | |
86 | ||
87 | while((c = getc(inptr[0])) != EOF) { | |
88 | if(c != '\n') { | |
89 | if (++j <= MAXLINE - 2) *p++ = c ; | |
90 | else diag("line too long\n",1); | |
91 | } else { | |
92 | l = del[k]; | |
93 | if (l != RUB) *p++ = l ; | |
94 | k = (k + 1) % delcount; | |
95 | *p = 0; | |
96 | fputs(outbuf, stdout); | |
97 | p = &outbuf[0]; | |
98 | j = 0; | |
99 | } | |
100 | } | |
101 | } | |
102 | if (l != '\n') fputs("\n", stdout); | |
103 | } | |
104 | } | |
105 | diag(s,r) | |
106 | char *s; | |
107 | int r; | |
108 | { | |
109 | write(2, "paste : ", 8); | |
110 | while(*s)write(2,s++,1); | |
111 | if(r != 0) exit(r); | |
112 | } | |
113 | ||
114 | move(from, to) | |
115 | char *from, *to; | |
116 | { | |
117 | int c, i; | |
118 | i = 0; | |
119 | do { | |
120 | c = *from++; | |
121 | i++; | |
122 | if (c != '\\') *to++ = c; | |
123 | else { c = *from++; | |
124 | switch (c) { | |
125 | case '0' : *to++ = RUB; | |
126 | break; | |
127 | case 't' : *to++ = '\t'; | |
128 | break; | |
129 | case 'n' : *to++ = '\n'; | |
130 | break; | |
131 | default : *to++ = c; | |
132 | break; | |
133 | } | |
134 | } | |
135 | } while (c) ; | |
136 | return(--i); | |
137 | } |