Blame


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