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; 26bd389b36SDavid du Colombier register 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; 32*219b2ee8SDavid du Colombier char buf[256]; 33bd389b36SDavid du Colombier 34bd389b36SDavid du Colombier ARGBEGIN{ 35bd389b36SDavid du Colombier case 'n': 36bd389b36SDavid du Colombier n=atoi(ARGF()); 37bd389b36SDavid du Colombier break; 38bd389b36SDavid du Colombier case 'e': 39bd389b36SDavid du Colombier pattern = strdup(ARGF()); 40bd389b36SDavid du Colombier break; 41bd389b36SDavid du Colombier case 'f': 42bd389b36SDavid du Colombier stem = strdup(ARGF()); 43bd389b36SDavid du Colombier break; 44bd389b36SDavid du Colombier case 's': 45bd389b36SDavid du Colombier suffix = strdup(ARGF()); 46bd389b36SDavid du Colombier break; 47bd389b36SDavid du Colombier case 'x': 48bd389b36SDavid du Colombier xflag++; 49bd389b36SDavid du Colombier break; 50bd389b36SDavid du Colombier case 'i': 51bd389b36SDavid du Colombier iflag++; 52bd389b36SDavid du Colombier break; 53bd389b36SDavid du Colombier default: 54bd389b36SDavid du Colombier goto Usage; 55bd389b36SDavid du Colombier }ARGEND; 56bd389b36SDavid du Colombier if(argc < 0 || argc > 1) 57bd389b36SDavid du Colombier Usage: usage(); 58bd389b36SDavid du Colombier 59bd389b36SDavid du Colombier if(argc == 0){ 60bd389b36SDavid du Colombier Binit(b, 0, OREAD); 61bd389b36SDavid du Colombier }else{ 62bd389b36SDavid du Colombier b = Bopen(argv[0], OREAD); 63bd389b36SDavid du Colombier if(b == 0) 64bd389b36SDavid du Colombier fprint(2, "split: can't open %s: %r\n", argv[0]); 65bd389b36SDavid du Colombier } 66bd389b36SDavid du Colombier if(pattern) { 67bd389b36SDavid du Colombier if(!(exp = regcomp(iflag? fold(pattern,strlen(pattern)): pattern))) 68bd389b36SDavid du Colombier badexp(); 69bd389b36SDavid du Colombier while((line=Brdline(b,'\n')) != 0) { 70bd389b36SDavid du Colombier Resub match[2]; 71bd389b36SDavid du Colombier line[BLINELEN(b)-1] = 0; 72bd389b36SDavid du Colombier if(regexec(exp,iflag?fold(line,BLINELEN(b)-1):line,match,2)) { 73bd389b36SDavid du Colombier if(matchfile(match) && xflag) 74bd389b36SDavid du Colombier continue; 75bd389b36SDavid du Colombier } else if(output == 0) 76bd389b36SDavid du Colombier nextfile(); /* at most once */ 77bd389b36SDavid du Colombier Bwrite(output, line, BLINELEN(b)-1); 78bd389b36SDavid du Colombier Bputc(output, '\n'); 79bd389b36SDavid du Colombier } 80bd389b36SDavid du Colombier } else { 81bd389b36SDavid du Colombier register linecnt = n; 82bd389b36SDavid du Colombier while((line=Brdline(b,'\n')) != 0) { 83bd389b36SDavid du Colombier if(++linecnt > n) { 84bd389b36SDavid du Colombier nextfile(); 85bd389b36SDavid du Colombier linecnt = 1; 86bd389b36SDavid du Colombier } 87bd389b36SDavid du Colombier Bwrite(output, line, BLINELEN(b)); 88bd389b36SDavid du Colombier } 89*219b2ee8SDavid du Colombier 90*219b2ee8SDavid du Colombier /* 91*219b2ee8SDavid du Colombier * in case we didn't end with a newline, tack whatever's 92*219b2ee8SDavid du Colombier * left onto the last file 93*219b2ee8SDavid du Colombier */ 94*219b2ee8SDavid du Colombier while((n = Bread(b, buf, sizeof(buf))) > 0) 95*219b2ee8SDavid du Colombier Bwrite(output, buf, n); 96bd389b36SDavid du Colombier } 97bd389b36SDavid du Colombier if(b != 0) 98*219b2ee8SDavid du Colombier Bterm(b); 99bd389b36SDavid du Colombier exits(0); 100bd389b36SDavid du Colombier } 101bd389b36SDavid du Colombier 102bd389b36SDavid du Colombier int 103bd389b36SDavid du Colombier nextfile(void) 104bd389b36SDavid du Colombier { 105bd389b36SDavid du Colombier static canopen = 1; 106bd389b36SDavid du Colombier if(suff[0] > 'z') { 107bd389b36SDavid du Colombier if(canopen) 108bd389b36SDavid du Colombier fprint(2, "split: file %szz not split\n",stem); 109bd389b36SDavid du Colombier canopen = 0; 110bd389b36SDavid du Colombier } else { 111bd389b36SDavid du Colombier strcpy(name, stem); 112bd389b36SDavid du Colombier strcat(name, suff); 113bd389b36SDavid du Colombier if(++suff[1] > 'z') 114bd389b36SDavid du Colombier suff[1] = 'a', ++suff[0]; 115bd389b36SDavid du Colombier openf(); 116bd389b36SDavid du Colombier } 117bd389b36SDavid du Colombier return canopen; 118bd389b36SDavid du Colombier } 119bd389b36SDavid du Colombier 120bd389b36SDavid du Colombier int 121bd389b36SDavid du Colombier matchfile(Resub *match) 122bd389b36SDavid du Colombier { 123bd389b36SDavid du Colombier if(match[1].sp) { 124bd389b36SDavid du Colombier int len = match[1].ep - match[1].sp; 125bd389b36SDavid du Colombier strncpy(name, match[1].sp, len); 126bd389b36SDavid du Colombier strcpy(name+len, suffix); 127bd389b36SDavid du Colombier openf(); 128bd389b36SDavid du Colombier return 1; 129bd389b36SDavid du Colombier } 130bd389b36SDavid du Colombier return nextfile(); 131bd389b36SDavid du Colombier } 132bd389b36SDavid du Colombier 133bd389b36SDavid du Colombier void 134bd389b36SDavid du Colombier openf(void) 135bd389b36SDavid du Colombier { 136bd389b36SDavid du Colombier int fd; 137bd389b36SDavid du Colombier Bflush(output); 138*219b2ee8SDavid du Colombier Bterm(output); 139bd389b36SDavid du Colombier if((fd=create(name,OWRITE,0666)) == -1) { 140bd389b36SDavid du Colombier fprint(2, "grep: can't open %s: %r\n", name); 141bd389b36SDavid du Colombier exits("open failed"); 142bd389b36SDavid du Colombier } 143bd389b36SDavid du Colombier Binit(output,fd,OWRITE); 144bd389b36SDavid du Colombier } 145bd389b36SDavid du Colombier 146bd389b36SDavid du Colombier char * 147bd389b36SDavid du Colombier fold(char *s, int n) 148bd389b36SDavid du Colombier { 149bd389b36SDavid du Colombier static char *fline; 150bd389b36SDavid du Colombier static int linesize = 0; 151bd389b36SDavid du Colombier char *t; 152bd389b36SDavid du Colombier if(linesize < n+1){ 153bd389b36SDavid du Colombier fline = realloc(fline,n+1); 154bd389b36SDavid du Colombier linesize = n+1; 155bd389b36SDavid du Colombier } 156bd389b36SDavid du Colombier for(t=fline; *t++=tolower(*s++); ) 157bd389b36SDavid du Colombier continue; 158bd389b36SDavid du Colombier /* we assume the 'A'-'Z' only appear as themselves 159bd389b36SDavid du Colombier * in a utf encoding. 160bd389b36SDavid du Colombier */ 161bd389b36SDavid du Colombier return fline; 162bd389b36SDavid du Colombier } 163bd389b36SDavid du Colombier 164bd389b36SDavid du Colombier void 165bd389b36SDavid du Colombier usage(void) 166bd389b36SDavid du Colombier { 167bd389b36SDavid du Colombier fprint(2, "usage: split [-n num] [-e exp] [-f stem] [-s suff] [-x] [-i] [file]\n"); 168bd389b36SDavid du Colombier exits("split usage"); 169bd389b36SDavid du Colombier } 170bd389b36SDavid du Colombier 171bd389b36SDavid du Colombier void 172bd389b36SDavid du Colombier badexp(void) 173bd389b36SDavid du Colombier { 174bd389b36SDavid du Colombier fprint(2, "split: bad regular expression\n"); 175bd389b36SDavid du Colombier exits("bad regular expression"); 176bd389b36SDavid du Colombier } 177