split.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
split.c (3257B) | |
--- | |
1 #include <u.h> | |
2 #include <libc.h> | |
3 #include <bio.h> | |
4 #include <ctype.h> | |
5 #include <regexp.h> | |
6 | |
7 char digit[] = "0123456789"; | |
8 char *suffix = ""; | |
9 char *stem = "x"; | |
10 char suff[] = "aa"; | |
11 char name[200]; | |
12 Biobuf bout; | |
13 Biobuf *output = &bout; | |
14 | |
15 extern int nextfile(void); | |
16 extern int matchfile(Resub*); | |
17 extern void openf(void); | |
18 extern char *fold(char*,int); | |
19 extern void usage(void); | |
20 extern void badexp(void); | |
21 | |
22 void | |
23 main(int argc, char *argv[]) | |
24 { | |
25 Reprog *exp; | |
26 char *pattern = 0; | |
27 int n = 1000; | |
28 char *line; | |
29 int xflag = 0; | |
30 int iflag = 0; | |
31 Biobuf bin; | |
32 Biobuf *b = &bin; | |
33 char buf[256]; | |
34 | |
35 ARGBEGIN { | |
36 case 'l': | |
37 case 'n': | |
38 n=atoi(EARGF(usage())); | |
39 break; | |
40 case 'e': | |
41 pattern = strdup(EARGF(usage())); | |
42 break; | |
43 case 'f': | |
44 stem = strdup(EARGF(usage())); | |
45 break; | |
46 case 's': | |
47 suffix = strdup(EARGF(usage())); | |
48 break; | |
49 case 'x': | |
50 xflag++; | |
51 break; | |
52 case 'i': | |
53 iflag++; | |
54 break; | |
55 default: | |
56 usage(); | |
57 break; | |
58 | |
59 } ARGEND; | |
60 | |
61 if(argc < 0 || argc > 1) | |
62 usage(); | |
63 | |
64 if(argc != 0) { | |
65 b = Bopen(argv[0], OREAD); | |
66 if(b == nil) { | |
67 fprint(2, "split: can't open %s: %r\n", argv[0]); | |
68 exits("open"); | |
69 } | |
70 } else | |
71 Binit(b, 0, OREAD); | |
72 | |
73 if(pattern) { | |
74 if(!(exp = regcomp(iflag? fold(pattern,strlen(pattern)):… | |
75 badexp(); | |
76 while((line=Brdline(b,'\n')) != 0) { | |
77 Resub match[2]; | |
78 memset(match, 0, sizeof match); | |
79 line[Blinelen(b)-1] = 0; | |
80 if(regexec(exp,iflag?fold(line,Blinelen(b)-1):li… | |
81 if(matchfile(match) && xflag) | |
82 continue; | |
83 } else if(output == 0) | |
84 nextfile(); /* at most once */ | |
85 Bwrite(output, line, Blinelen(b)-1); | |
86 Bputc(output, '\n'); | |
87 } | |
88 } else { | |
89 int linecnt = n; | |
90 | |
91 while((line=Brdline(b,'\n')) != 0) { | |
92 if(++linecnt > n) { | |
93 nextfile(); | |
94 linecnt = 1; | |
95 } | |
96 Bwrite(output, line, Blinelen(b)); | |
97 } | |
98 | |
99 /* | |
100 * in case we didn't end with a newline, tack whatever's | |
101 * left onto the last file | |
102 */ | |
103 while((n = Bread(b, buf, sizeof(buf))) > 0) | |
104 Bwrite(output, buf, n); | |
105 } | |
106 if(b != nil) | |
107 Bterm(b); | |
108 exits(0); | |
109 } | |
110 | |
111 int | |
112 nextfile(void) | |
113 { | |
114 static int canopen = 1; | |
115 if(suff[0] > 'z') { | |
116 if(canopen) | |
117 fprint(2, "split: file %szz not split\n",stem); | |
118 canopen = 0; | |
119 } else { | |
120 strcpy(name, stem); | |
121 strcat(name, suff); | |
122 if(++suff[1] > 'z') | |
123 suff[1] = 'a', ++suff[0]; | |
124 openf(); | |
125 } | |
126 return canopen; | |
127 } | |
128 | |
129 int | |
130 matchfile(Resub *match) | |
131 { | |
132 if(match[1].s.sp) { | |
133 int len = match[1].e.ep - match[1].s.sp; | |
134 strncpy(name, match[1].s.sp, len); | |
135 strcpy(name+len, suffix); | |
136 openf(); | |
137 return 1; | |
138 } | |
139 return nextfile(); | |
140 } | |
141 | |
142 void | |
143 openf(void) | |
144 { | |
145 static int fd = 0; | |
146 Bflush(output); | |
147 Bterm(output); | |
148 if(fd > 0) | |
149 close(fd); | |
150 fd = create(name,OWRITE,0666); | |
151 if(fd < 0) { | |
152 fprint(2, "grep: can't create %s: %r\n", name); | |
153 exits("create"); | |
154 } | |
155 Binit(output, fd, OWRITE); | |
156 } | |
157 | |
158 char * | |
159 fold(char *s, int n) | |
160 { | |
161 static char *fline; | |
162 static int linesize = 0; | |
163 char *t; | |
164 | |
165 if(linesize < n+1){ | |
166 fline = realloc(fline,n+1); | |
167 linesize = n+1; | |
168 } | |
169 for(t=fline; *t++ = tolower((uchar)*s++); ) | |
170 continue; | |
171 /* we assume the 'A'-'Z' only appear as themselves | |
172 * in a utf encoding. | |
173 */ | |
174 return fline; | |
175 } | |
176 | |
177 void | |
178 usage(void) | |
179 { | |
180 fprint(2, "usage: split [-n num] [-e exp] [-f stem] [-s suff] [-… | |
181 exits("usage"); | |
182 } | |
183 | |
184 void | |
185 badexp(void) | |
186 { | |
187 fprint(2, "split: bad regular expression\n"); | |
188 exits("bad regular expression"); | |
189 } |