1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier #include <regexp.h> 5bd389b36SDavid du Colombier 6bd389b36SDavid du Colombier char digit[] = "0123456789"; 7bd389b36SDavid du Colombier char *suffix = ""; 8bd389b36SDavid du Colombier char *stem = "x"; 9bd389b36SDavid du Colombier char suff[] = "aa"; 10bd389b36SDavid du Colombier char name[200]; 11bd389b36SDavid du Colombier Biobuf bout; 12bd389b36SDavid du Colombier Biobuf *output = &bout; 13bd389b36SDavid du Colombier 14bd389b36SDavid du Colombier extern int nextfile(void); 15bd389b36SDavid du Colombier extern int matchfile(Resub*); 16bd389b36SDavid du Colombier extern void openf(void); 17bd389b36SDavid du Colombier extern char *fold(char*,int); 18bd389b36SDavid du Colombier extern void usage(void); 19bd389b36SDavid du Colombier extern void badexp(void); 20bd389b36SDavid du Colombier 21bd389b36SDavid du Colombier void 22bd389b36SDavid du Colombier main(int argc, char *argv[]) 23bd389b36SDavid du Colombier { 24bd389b36SDavid du Colombier Reprog *exp; 25bd389b36SDavid du Colombier char *pattern = 0; 267dd7cddfSDavid du Colombier int n = 1000; 27bd389b36SDavid du Colombier char *line; 28bd389b36SDavid du Colombier int xflag = 0; 29bd389b36SDavid du Colombier int iflag = 0; 30bd389b36SDavid du Colombier Biobuf bin; 31bd389b36SDavid du Colombier Biobuf *b = &bin; 32219b2ee8SDavid du Colombier char buf[256]; 33bd389b36SDavid du Colombier 34bd389b36SDavid du Colombier ARGBEGIN { 35d9306527SDavid du Colombier case 'l': 36bd389b36SDavid du Colombier case 'n': 3759cc4ca5SDavid du Colombier n=atoi(EARGF(usage())); 38bd389b36SDavid du Colombier break; 39bd389b36SDavid du Colombier case 'e': 4059cc4ca5SDavid du Colombier pattern = strdup(EARGF(usage())); 41bd389b36SDavid du Colombier break; 42bd389b36SDavid du Colombier case 'f': 4359cc4ca5SDavid du Colombier stem = strdup(EARGF(usage())); 44bd389b36SDavid du Colombier break; 45bd389b36SDavid du Colombier case 's': 4659cc4ca5SDavid du Colombier suffix = strdup(EARGF(usage())); 47bd389b36SDavid du Colombier break; 48bd389b36SDavid du Colombier case 'x': 49bd389b36SDavid du Colombier xflag++; 50bd389b36SDavid du Colombier break; 51bd389b36SDavid du Colombier case 'i': 52bd389b36SDavid du Colombier iflag++; 53bd389b36SDavid du Colombier break; 54bd389b36SDavid du Colombier default: 557dd7cddfSDavid du Colombier usage(); 567dd7cddfSDavid du Colombier break; 57bd389b36SDavid du Colombier 587dd7cddfSDavid du Colombier } ARGEND; 597dd7cddfSDavid du Colombier 607dd7cddfSDavid du Colombier if(argc < 0 || argc > 1) 617dd7cddfSDavid du Colombier usage(); 627dd7cddfSDavid du Colombier 637dd7cddfSDavid du Colombier if(argc != 0) { 64bd389b36SDavid du Colombier b = Bopen(argv[0], OREAD); 657dd7cddfSDavid du Colombier if(b == nil) { 66bd389b36SDavid du Colombier fprint(2, "split: can't open %s: %r\n", argv[0]); 677dd7cddfSDavid du Colombier exits("open"); 68bd389b36SDavid du Colombier } 697dd7cddfSDavid du Colombier } else 707dd7cddfSDavid du Colombier Binit(b, 0, OREAD); 717dd7cddfSDavid du Colombier 72bd389b36SDavid du Colombier if(pattern) { 73bd389b36SDavid du Colombier if(!(exp = regcomp(iflag? fold(pattern,strlen(pattern)): pattern))) 74bd389b36SDavid du Colombier badexp(); 75bd389b36SDavid du Colombier while((line=Brdline(b,'\n')) != 0) { 76bd389b36SDavid du Colombier Resub match[2]; 7780ee5cbfSDavid du Colombier memset(match, 0, sizeof match); 787dd7cddfSDavid du Colombier line[Blinelen(b)-1] = 0; 797dd7cddfSDavid du Colombier if(regexec(exp,iflag?fold(line,Blinelen(b)-1):line,match,2)) { 80bd389b36SDavid du Colombier if(matchfile(match) && xflag) 81bd389b36SDavid du Colombier continue; 82bd389b36SDavid du Colombier } else if(output == 0) 83bd389b36SDavid du Colombier nextfile(); /* at most once */ 847dd7cddfSDavid du Colombier Bwrite(output, line, Blinelen(b)-1); 85bd389b36SDavid du Colombier Bputc(output, '\n'); 86bd389b36SDavid du Colombier } 87bd389b36SDavid du Colombier } else { 887dd7cddfSDavid du Colombier int linecnt = n; 897dd7cddfSDavid du Colombier 90bd389b36SDavid du Colombier while((line=Brdline(b,'\n')) != 0) { 91bd389b36SDavid du Colombier if(++linecnt > n) { 92bd389b36SDavid du Colombier nextfile(); 93bd389b36SDavid du Colombier linecnt = 1; 94bd389b36SDavid du Colombier } 957dd7cddfSDavid du Colombier Bwrite(output, line, Blinelen(b)); 96bd389b36SDavid du Colombier } 97219b2ee8SDavid du Colombier 98219b2ee8SDavid du Colombier /* 99219b2ee8SDavid du Colombier * in case we didn't end with a newline, tack whatever's 100219b2ee8SDavid du Colombier * left onto the last file 101219b2ee8SDavid du Colombier */ 102219b2ee8SDavid du Colombier while((n = Bread(b, buf, sizeof(buf))) > 0) 103219b2ee8SDavid du Colombier Bwrite(output, buf, n); 104bd389b36SDavid du Colombier } 1057dd7cddfSDavid du Colombier if(b != nil) 106219b2ee8SDavid du Colombier Bterm(b); 107bd389b36SDavid du Colombier exits(0); 108bd389b36SDavid du Colombier } 109bd389b36SDavid du Colombier 110bd389b36SDavid du Colombier int 111bd389b36SDavid du Colombier nextfile(void) 112bd389b36SDavid du Colombier { 113bd389b36SDavid du Colombier static canopen = 1; 114bd389b36SDavid du Colombier if(suff[0] > 'z') { 115bd389b36SDavid du Colombier if(canopen) 116bd389b36SDavid du Colombier fprint(2, "split: file %szz not split\n",stem); 117bd389b36SDavid du Colombier canopen = 0; 118bd389b36SDavid du Colombier } else { 119*4d44ba9bSDavid du Colombier snprint(name, sizeof name, "%s%s", stem, suff); 120bd389b36SDavid du Colombier if(++suff[1] > 'z') 121bd389b36SDavid du Colombier suff[1] = 'a', ++suff[0]; 122bd389b36SDavid du Colombier openf(); 123bd389b36SDavid du Colombier } 124bd389b36SDavid du Colombier return canopen; 125bd389b36SDavid du Colombier } 126bd389b36SDavid du Colombier 127bd389b36SDavid du Colombier int 128bd389b36SDavid du Colombier matchfile(Resub *match) 129bd389b36SDavid du Colombier { 130bd389b36SDavid du Colombier if(match[1].sp) { 131bd389b36SDavid du Colombier int len = match[1].ep - match[1].sp; 132bd389b36SDavid du Colombier strncpy(name, match[1].sp, len); 133bd389b36SDavid du Colombier strcpy(name+len, suffix); 134bd389b36SDavid du Colombier openf(); 135bd389b36SDavid du Colombier return 1; 136bd389b36SDavid du Colombier } 137bd389b36SDavid du Colombier return nextfile(); 138bd389b36SDavid du Colombier } 139bd389b36SDavid du Colombier 140bd389b36SDavid du Colombier void 141bd389b36SDavid du Colombier openf(void) 142bd389b36SDavid du Colombier { 14380ee5cbfSDavid du Colombier static int fd = 0; 144bd389b36SDavid du Colombier Bflush(output); 145219b2ee8SDavid du Colombier Bterm(output); 14680ee5cbfSDavid du Colombier if(fd > 0) 14780ee5cbfSDavid du Colombier close(fd); 1487dd7cddfSDavid du Colombier fd = create(name,OWRITE,0666); 1497dd7cddfSDavid du Colombier if(fd < 0) { 1507dd7cddfSDavid du Colombier fprint(2, "grep: can't create %s: %r\n", name); 1517dd7cddfSDavid du Colombier exits("create"); 152bd389b36SDavid du Colombier } 153bd389b36SDavid du Colombier Binit(output, fd, OWRITE); 154bd389b36SDavid du Colombier } 155bd389b36SDavid du Colombier 156bd389b36SDavid du Colombier char * 157bd389b36SDavid du Colombier fold(char *s, int n) 158bd389b36SDavid du Colombier { 159bd389b36SDavid du Colombier static char *fline; 160bd389b36SDavid du Colombier static int linesize = 0; 161bd389b36SDavid du Colombier char *t; 1627dd7cddfSDavid du Colombier 163bd389b36SDavid du Colombier if(linesize < n+1){ 164bd389b36SDavid du Colombier fline = realloc(fline,n+1); 165bd389b36SDavid du Colombier linesize = n+1; 166bd389b36SDavid du Colombier } 167bd389b36SDavid du Colombier for(t=fline; *t++ = tolower(*s++); ) 168bd389b36SDavid du Colombier continue; 169bd389b36SDavid du Colombier /* we assume the 'A'-'Z' only appear as themselves 170bd389b36SDavid du Colombier * in a utf encoding. 171bd389b36SDavid du Colombier */ 172bd389b36SDavid du Colombier return fline; 173bd389b36SDavid du Colombier } 174bd389b36SDavid du Colombier 175bd389b36SDavid du Colombier void 176bd389b36SDavid du Colombier usage(void) 177bd389b36SDavid du Colombier { 178bd389b36SDavid du Colombier fprint(2, "usage: split [-n num] [-e exp] [-f stem] [-s suff] [-x] [-i] [file]\n"); 1797dd7cddfSDavid du Colombier exits("usage"); 180bd389b36SDavid du Colombier } 181bd389b36SDavid du Colombier 182bd389b36SDavid du Colombier void 183bd389b36SDavid du Colombier badexp(void) 184bd389b36SDavid du Colombier { 185bd389b36SDavid du Colombier fprint(2, "split: bad regular expression\n"); 186bd389b36SDavid du Colombier exits("bad regular expression"); 187bd389b36SDavid du Colombier } 188