Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ctype.h>
5 #include <regexp.h>
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;
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);
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];
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;
59 } ARGEND;
61 if(argc < 0 || argc > 1)
62 usage();
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);
73 if(pattern) {
74 if(!(exp = regcomp(iflag? fold(pattern,strlen(pattern)): 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):line,match,2)) {
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;
91 while((line=Brdline(b,'\n')) != 0) {
92 if(++linecnt > n) {
93 nextfile();
94 linecnt = 1;
95 }
96 Bwrite(output, line, Blinelen(b));
97 }
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);
106 if(b != nil)
107 Bterm(b);
108 exits(0);
111 int
112 nextfile(void)
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();
126 return canopen;
129 int
130 matchfile(Resub *match)
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;
139 return nextfile();
142 void
143 openf(void)
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");
155 Binit(output, fd, OWRITE);
158 char *
159 fold(char *s, int n)
161 static char *fline;
162 static int linesize = 0;
163 char *t;
165 if(linesize < n+1){
166 fline = realloc(fline,n+1);
167 linesize = n+1;
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;
177 void
178 usage(void)
180 fprint(2, "usage: split [-n num] [-e exp] [-f stem] [-s suff] [-x] [-i] [file]\n");
181 exits("usage");
184 void
185 badexp(void)
187 fprint(2, "split: bad regular expression\n");
188 exits("bad regular expression");