| 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 } |