Changeset 4121 for zzuf/trunk/test/zzcat.c
- Timestamp:
- 12/14/09 03:55:31 (3 years ago)
- File:
-
- 1 edited
-
zzuf/trunk/test/zzcat.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
zzuf/trunk/test/zzcat.c
r4030 r4121 13 13 */ 14 14 15 /* 16 * TODO: fsetpos64, fgetln 17 */ 18 15 19 #include "config.h" 16 20 … … 19 23 /* Needed for O_RDONLY on HP-UX */ 20 24 #define _INCLUDE_POSIX_SOURCE 25 /* Needed for fgets_unlocked() */ 26 #define _GNU_SOURCE 21 27 22 28 #if defined HAVE_STDINT_H … … 37 43 #include <stdio.h> 38 44 #include <string.h> 39 40 static int zzcat_read(char const *, unsigned char *, int64_t, int64_t);41 static int zzcat_fread(char const *, unsigned char *, int64_t, int64_t);42 static int zzcat_fread_fseek(char const *, unsigned char *, int64_t, int64_t);43 static int zzcat_fseek_fread(char const *, unsigned char *, int64_t, int64_t);44 #if defined HAVE_GETLINE45 static int zzcat_getline_getc(char const *, unsigned char *, int64_t, int);46 #endif47 static int zzcat_fseek_getc(char const *, unsigned char *,48 int64_t, int64_t, int);49 static int zzcat_fread_getc(char const *, unsigned char *, int64_t,50 int64_t, int);51 static int zzcat_random_socket(char const *, unsigned char *, int64_t);52 static int zzcat_random_stream(char const *, unsigned char *, int64_t);53 #if defined HAVE_MMAP54 static int zzcat_random_mmap(char const *, unsigned char *, int64_t);55 #endif56 45 57 46 static inline unsigned int myrand(void) … … 65 54 } 66 55 67 static inline int mygetc(FILE *stream, int getc_method) 68 { 69 switch (getc_method) 70 { 56 #define FOPEN(cmd) \ 57 do { \ 58 cmd; \ 59 if (!f) \ 60 { \ 61 fprintf(stderr, "E: zzcat: cannot open `%s'\n", file); \ 62 return EXIT_FAILURE; \ 63 } \ 64 retoff = 0; \ 65 p = strchr(p, ')') + 1; \ 66 } while(0) 67 68 #define FCLOSE(cmd) \ 69 do { \ 70 cmd; \ 71 f = NULL; \ 72 p = strchr(p, ')') + 1; \ 73 } while(0) 74 75 #define MERGE(address, cnt, off) \ 76 do { \ 77 size_t _cnt = cnt, _off = off; \ 78 if (_cnt && retoff + _cnt > retlen) \ 79 { \ 80 retlen = retoff + _cnt; \ 81 retbuf = realloc(retbuf, retlen); \ 82 } \ 83 if (_cnt > 0) \ 84 memcpy(retbuf + retoff, address, _cnt); \ 85 retoff += _off; \ 86 } while(0) 87 88 #define FREAD(cmd, buf, cnt) FCALL(cmd, buf, cnt, cnt) 89 #define FSEEK(cmd, off) FCALL(cmd, /* unused */ "", 0, off) 90 91 #define FCALL(cmd, buf, cnt, off) \ 92 do { \ 93 if (!f) \ 94 { \ 95 f = fopen(file, "r"); \ 96 if (!f) \ 97 { \ 98 fprintf(stderr, "E: zzcat: cannot open `%s'\n", file); \ 99 return EXIT_FAILURE; \ 100 } \ 101 } \ 102 cmd; \ 103 MERGE(buf, cnt, off); \ 104 p = strchr(p, ')') + 1; \ 105 } while(0) 106 107 /* 108 * Command parser. We rewrite fmt by replacing the last character with 109 * '%c' and check that the sscanf() call returns the expected number of 110 * matches plus one (for the last character). We use this macro trick to 111 * avoid using vsscanf() which does not exist on all platforms. 112 */ 113 114 struct parser 115 { 116 char tmpfmt[1024], ch, lastch; 117 }; 118 119 static int make_fmt(struct parser *p, char const *fmt) 120 { 121 char const *tmp; 122 size_t len; 123 int ret = 0; 124 125 len = strlen(fmt); 126 p->lastch = fmt[len - 1]; 127 128 memcpy(p->tmpfmt, fmt, len - 1); 129 p->tmpfmt[len - 1] = '%'; 130 p->tmpfmt[len] = 'c'; 131 p->tmpfmt[len + 1] = '\0'; 132 133 for (tmp = p->tmpfmt; *tmp; tmp++) 134 if (*tmp == '%') 135 tmp++, ret++; 136 137 return ret; 138 } 139 140 #define PARSECMD(fmt, arg...) \ 141 make_fmt(&parser, fmt) == sscanf(p, parser.tmpfmt, ##arg, &parser.ch) \ 142 && parser.ch == parser.lastch 143 144 /* 145 * File reader. We parse a command line and perform all the operations it 146 * contains on the specified file. 147 */ 148 149 static int cat_file(char const *p, char const *file) 150 { 151 struct { char const *p; int count; } loops[128]; 152 char *retbuf = NULL, *tmp; 153 FILE *f = NULL; 154 size_t retlen = 0, retoff = 0; 155 int nloops = 0, fd = -1; 156 157 /* Allocate 32MB for our temporary buffer. Any larger value will crash. */ 158 tmp = malloc(32 * 1024 * 1024); 159 160 while (*p) 161 { 162 struct parser parser; 163 long int l1, l2; 164 char *s, *lineptr = NULL; 165 size_t k; 166 ssize_t l; 167 int n; 168 char ch; 169 170 /* Ignore punctuation */ 171 if (strchr(" \t,;\r\n", *p)) 172 p++; 173 174 /* Loop handling */ 175 else if (PARSECMD("repeat ( %li ,", &l1)) 176 { 177 p = strchr(p, ',') + 1; 178 loops[nloops].p = p; 179 loops[nloops].count = l1; 180 nloops++; 181 } 182 else if (PARSECMD(")")) 183 { 184 if (nloops == 0) 185 { 186 fprintf(stderr, "E: zzcat: ')' outside a loop\n"); 187 return EXIT_FAILURE; 188 } 189 loops[nloops - 1].count--; 190 if (loops[nloops - 1].count <= 0) 191 { 192 nloops--; 193 p = strchr(p, ')') + 1; 194 } 195 else 196 { 197 p = loops[nloops - 1].p; 198 } 199 } 200 201 /* FILE * opening functions */ 202 else if (PARSECMD("fopen ( )")) 203 FOPEN(f = fopen(file, "r")); 204 #if defined HAVE_FOPEN64 205 else if (PARSECMD("fopen64 ( )")) 206 FOPEN(f = fopen64(file, "r")); 207 #endif 208 #if defined HAVE___FOPEN64 209 else if (PARSECMD("__fopen64 ( )")) 210 FOPEN(f = __fopen64(file, "r")); 211 #endif 212 else if (PARSECMD("freopen ( )")) 213 FOPEN(f = freopen(file, "r", f)); 214 #if defined HAVE_FREOPEN64 215 else if (PARSECMD("freopen64 ( )")) 216 FOPEN(f = freopen64(file, "r", f)); 217 #endif 218 #if defined HAVE___FREOPEN64 219 else if (PARSECMD("__freopen64 ( )")) 220 FOPEN(f = __freopen64(file, "r", f)); 221 #endif 222 223 /* FILE * closing functions */ 224 else if (PARSECMD("fclose ( )")) 225 FCLOSE(fclose(f)); 226 227 /* FILE * reading functions */ 228 else if (PARSECMD("fread ( %li , %li )", &l1, &l2)) 229 FREAD(l = fread(tmp, l1, l2, f), tmp, l > 0 ? l * l1 : 0); 230 else if (PARSECMD("getc ( )")) 231 FREAD(ch = (n = getc(f)), &ch, (n != EOF)); 232 else if (PARSECMD("fgetc ( )")) 233 FREAD(ch = (n = fgetc(f)), &ch, (n != EOF)); 234 else if (PARSECMD("fgets ( %li )", &l1)) 235 FREAD(s = fgets(tmp, l1, f), tmp, s ? strlen(tmp) : 0); 236 #if defined HAVE__IO_GETC 237 else if (PARSECMD("_IO_getc ( )")) 238 FREAD(ch = (n = _IO_getc(f)), &ch, (n != EOF)); 239 #endif 240 #if defined HAVE_FREAD_UNLOCKED 241 else if (PARSECMD("fread_unlocked ( %li , %li )", &l1, &l2)) 242 FREAD(l = fread_unlocked(tmp, l1, l2, f), tmp, l > 0 ? l * l1 : 0); 243 #endif 244 #if defined HAVE_FGETS_UNLOCKED 245 else if (PARSECMD("fgets_unlocked ( %li )", &l1)) 246 FREAD(s = fgets_unlocked(tmp, l1, f), tmp, s ? strlen(tmp) : 0); 247 #endif 71 248 #if defined HAVE_GETC_UNLOCKED 72 case 3: return fgetc_unlocked(stream); 73 case 2: return getc_unlocked(stream); 74 #endif 75 case 1: return fgetc(stream); 76 default: return getc(stream); 77 } 78 } 249 else if (PARSECMD("getc_unlocked ( )")) 250 FREAD(ch = (n = getc_unlocked(f)), &ch, (n != EOF)); 251 #endif 252 #if defined HAVE_FGETC_UNLOCKED 253 else if (PARSECMD("fgetc_unlocked ( )")) 254 FREAD(ch = (n = fgetc_unlocked(f)), &ch, (n != EOF)); 255 #endif 256 257 /* FILE * getdelim functions */ 258 #if defined HAVE_GETLINE 259 else if (PARSECMD("getline ( )")) 260 FREAD(l = getline(&lineptr, &k, f), lineptr, l >= 0 ? l : 0); 261 #endif 262 #if defined HAVE_GETDELIM 263 else if (PARSECMD("getdelim ( '%c' )", &ch)) 264 FREAD(l = getdelim(&lineptr, &k, ch, f), lineptr, l >= 0 ? l : 0); 265 else if (PARSECMD("getdelim ( %i )", &n)) 266 FREAD(l = getdelim(&lineptr, &k, n, f), lineptr, l >= 0 ? l : 0); 267 #endif 268 #if defined HAVE___GETDELIM 269 else if (PARSECMD("__getdelim ( '%c' )", &ch)) 270 FREAD(l = __getdelim(&lineptr, &k, ch, f), lineptr, l >= 0 ? l : 0); 271 else if (PARSECMD("__getdelim ( %i )", &n)) 272 FREAD(l = __getdelim(&lineptr, &k, n, f), lineptr, l >= 0 ? l : 0); 273 #endif 274 275 /* FILE * seeking functions */ 276 else if (PARSECMD("fseek ( %li , SEEK_CUR )", &l1)) 277 FSEEK(l = fseek(f, l1, SEEK_CUR), 278 ftell(f) >= 0 ? ftell(f) - retoff : 0); 279 else if (PARSECMD("fseek ( %li , SEEK_SET )", &l1)) 280 FSEEK(l = fseek(f, l1, SEEK_SET), 281 ftell(f) >= 0 ? ftell(f) - retoff : 0); 282 else if (PARSECMD("fseek ( %li , SEEK_END )", &l1)) 283 FSEEK(l = fseek(f, l1, SEEK_END), 284 ftell(f) >= 0 ? ftell(f) - retoff : 0); 285 #if defined HAVE_FSEEKO 286 else if (PARSECMD("fseeko ( %li , SEEK_CUR )", &l1)) 287 FSEEK(l = fseeko(f, l1, SEEK_CUR), 288 ftell(f) >= 0 ? ftell(f) - retoff : 0); 289 else if (PARSECMD("fseeko ( %li , SEEK_SET )", &l1)) 290 FSEEK(l = fseeko(f, l1, SEEK_SET), 291 ftell(f) >= 0 ? ftell(f) - retoff : 0); 292 else if (PARSECMD("fseeko ( %li , SEEK_END )", &l1)) 293 FSEEK(l = fseeko(f, l1, SEEK_END), 294 ftell(f) >= 0 ? ftell(f) - retoff : 0); 295 #endif 296 #if defined HAVE_FSEEKO64 297 else if (PARSECMD("fseeko64 ( %li , SEEK_CUR )", &l1)) 298 FSEEK(l = fseeko64(f, l1, SEEK_CUR), 299 ftell(f) >= 0 ? ftell(f) - retoff : 0); 300 else if (PARSECMD("fseeko64 ( %li , SEEK_SET )", &l1)) 301 FSEEK(l = fseeko64(f, l1, SEEK_SET), 302 ftell(f) >= 0 ? ftell(f) - retoff : 0); 303 else if (PARSECMD("fseeko64 ( %li , SEEK_END )", &l1)) 304 FSEEK(l = fseeko64(f, l1, SEEK_END), 305 ftell(f) >= 0 ? ftell(f) - retoff : 0); 306 #endif 307 #if defined HAVE___FSEEKO64 308 else if (PARSECMD("__fseeko64 ( %li , SEEK_CUR )", &l1)) 309 FSEEK(l = __fseeko64(f, l1, SEEK_CUR), 310 ftell(f) >= 0 ? ftell(f) - retoff : 0); 311 else if (PARSECMD("__fseeko64 ( %li , SEEK_SET )", &l1)) 312 FSEEK(l = __fseeko64(f, l1, SEEK_SET), 313 ftell(f) >= 0 ? ftell(f) - retoff : 0); 314 else if (PARSECMD("__fseeko64 ( %li , SEEK_END )", &l1)) 315 FSEEK(l = __fseeko64(f, l1, SEEK_END), 316 ftell(f) >= 0 ? ftell(f) - retoff : 0); 317 #endif 318 else if (PARSECMD("rewind ( )")) 319 FSEEK(rewind(f), -retlen); 320 else if (PARSECMD("ungetc ( )")) 321 FSEEK(if(retoff) ungetc((unsigned char)retbuf[retoff - 1], f), 322 retoff ? -1 : 0); 323 324 /* Unrecognised sequence */ 325 else 326 { 327 char buf[16]; 328 snprintf(buf, 16, strlen(p) < 16 ? "%s" : "%.12s...", p); 329 fprintf(stderr, "E: zzcat: syntax error near `%s'\n", buf); 330 return EXIT_FAILURE; 331 } 332 333 /* Clean up our mess */ 334 if (lineptr) 335 free(lineptr); 336 } 337 338 if (f) 339 fclose(f); 340 341 if (fd >= 0) 342 close(fd); 343 344 fwrite(retbuf, retlen, 1, stdout); 345 346 free(retbuf); 347 free(tmp); 348 349 return EXIT_SUCCESS; 350 } 351 352 /* 353 * Main program. 354 */ 79 355 80 356 int main(int argc, char *argv[]) 81 357 { 82 int64_t len; 83 unsigned char *data; 84 char const *name; 85 int ret, cmd, fd; 86 87 if(argc != 3) 358 int i; 359 360 if (argc < 2) 361 { 362 fprintf(stderr, "E: zzcat: too few arguments\n"); 88 363 return EXIT_FAILURE; 89 90 name = argv[2]; 91 92 /* Read the whole file */ 93 fd = open(name, O_RDONLY); 94 if(fd < 0) 95 return EXIT_FAILURE; 96 len = lseek(fd, 0, SEEK_END); 97 if(len < 0) 98 return EXIT_FAILURE; 99 data = malloc(len + 16); /* 16 safety bytes */ 100 lseek(fd, 0, SEEK_SET); 101 read(fd, data, len); 102 close(fd); 103 104 /* Read shit here and there, using different methods */ 105 switch((cmd = atoi(argv[1]))) 106 { 107 /* Simple socket calls */ 108 case 100: ret = zzcat_read(name, data, len, 1); break; 109 case 101: ret = zzcat_read(name, data, len, 3); break; 110 case 102: ret = zzcat_read(name, data, len, len); break; 111 /* Simple stream calls */ 112 case 200: ret = zzcat_fread(name, data, len, 1); break; 113 case 201: ret = zzcat_fread(name, data, len, 2); break; 114 case 202: ret = zzcat_fread(name, data, len, len); break; 115 case 203: ret = zzcat_fseek_getc(name, data, len, 0, 0); break; 116 case 204: ret = zzcat_fseek_getc(name, data, len, 0, 1); break; 117 case 205: ret = zzcat_fseek_getc(name, data, len, 2, 0); break; 118 case 206: ret = zzcat_fseek_getc(name, data, len, 2, 1); break; 119 case 207: ret = zzcat_fseek_getc(name, data, len, len / 2, 0); break; 120 case 208: ret = zzcat_fseek_getc(name, data, len, len / 2, 1); break; 121 case 209: ret = zzcat_fread_getc(name, data, len, 2, 0); break; 122 case 210: ret = zzcat_fread_getc(name, data, len, 2, 1); break; 123 case 211: ret = zzcat_fread_getc(name, data, len, len / 2, 0); break; 124 case 212: ret = zzcat_fread_getc(name, data, len, len / 2, 1); break; 125 #if defined HAVE_GETLINE 126 case 213: ret = zzcat_getline_getc(name, data, len, 0); break; 127 case 214: ret = zzcat_getline_getc(name, data, len, 1); break; 128 #endif 129 /* Simple unlocked stream calls */ 130 #if defined HAVE_GETC_UNLOCKED 131 case 300: ret = zzcat_fseek_getc(name, data, len, 0, 2); break; 132 case 301: ret = zzcat_fseek_getc(name, data, len, 0, 3); break; 133 case 302: ret = zzcat_fseek_getc(name, data, len, 2, 2); break; 134 case 303: ret = zzcat_fseek_getc(name, data, len, 2, 3); break; 135 case 304: ret = zzcat_fseek_getc(name, data, len, len / 2, 2); break; 136 case 305: ret = zzcat_fseek_getc(name, data, len, len / 2, 3); break; 137 case 306: ret = zzcat_fread_getc(name, data, len, 2, 2); break; 138 case 307: ret = zzcat_fread_getc(name, data, len, 2, 3); break; 139 case 308: ret = zzcat_fread_getc(name, data, len, len / 2, 2); break; 140 case 309: ret = zzcat_fread_getc(name, data, len, len / 2, 3); break; 141 # if defined HAVE_GETLINE 142 case 310: ret = zzcat_getline_getc(name, data, len, 2); break; 143 case 311: ret = zzcat_getline_getc(name, data, len, 3); break; 144 # endif 145 #endif 146 /* Incomplete calls (but still OK since data is pre-filled) */ 147 case 400: ret = zzcat_fread_fseek(name, data, len, 1); break; 148 case 401: ret = zzcat_fread_fseek(name, data, len, 2); break; 149 case 402: ret = zzcat_fread_fseek(name, data, len, 4000); break; 150 case 403: ret = zzcat_fseek_fread(name, data, len, 1); break; 151 case 404: ret = zzcat_fseek_fread(name, data, len, 2); break; 152 case 405: ret = zzcat_fseek_fread(name, data, len, 4000); break; 153 case 406: ret = zzcat_random_socket(name, data, len); break; 154 case 407: ret = zzcat_random_stream(name, data, len); break; 155 /* Misc */ 156 #if defined HAVE_MMAP 157 case 500: ret = zzcat_random_mmap(name, data, len); break; 158 #endif 159 default: ret = EXIT_SUCCESS; 160 } 161 162 /* Write what we have read */ 163 fwrite(data, len, 1, stdout); 164 free(data); 165 166 return ret; 167 } 168 364 } 365 366 if (argc == 2) 367 return cat_file("fread(1,33554432)", argv[1]); 368 369 for (i = 2; i < argc; i++) 370 { 371 int ret = cat_file(argv[1], argv[i]); 372 if (ret) 373 return ret; 374 } 375 376 return EXIT_SUCCESS; 377 } 378 379 #if 0 169 380 /* Only read() calls */ 170 381 static int zzcat_read(char const *name, unsigned char *data, int64_t len, … … 177 388 read(fd, data + i, chunk); 178 389 close(fd); 179 return EXIT_SUCCESS;180 }181 182 /* Only fread() calls */183 static int zzcat_fread(char const *name, unsigned char *data, int64_t len,184 int64_t chunk)185 {186 FILE *stream = fopen(name, "r");187 int i;188 if(!stream)189 return EXIT_FAILURE;190 for(i = 0; i < len; i += chunk)191 fread(data + i, chunk, 1, stream);192 fclose(stream);193 return EXIT_SUCCESS;194 }195 196 /* Only fread() and fseek() calls */197 static int zzcat_fread_fseek(char const *name, unsigned char *data,198 int64_t len, int64_t chunk)199 {200 FILE *stream = fopen(name, "r");201 int i;202 if(!stream)203 return EXIT_FAILURE;204 for(i = 0; i < len; )205 {206 fread(data + i, chunk, 1, stream);207 i += chunk;208 if (i >= len)209 break;210 fseek(stream, chunk, SEEK_CUR);211 i += chunk;212 }213 fclose(stream);214 return EXIT_SUCCESS;215 }216 217 /* Only fseek() and fread() calls */218 static int zzcat_fseek_fread(char const *name, unsigned char *data,219 int64_t len, int64_t chunk)220 {221 FILE *stream = fopen(name, "r");222 int i;223 if(!stream)224 return EXIT_FAILURE;225 for(i = 0; i < len; )226 {227 fseek(stream, chunk, SEEK_CUR);228 i += chunk;229 if (i >= len)230 break;231 fread(data + i, chunk, 1, stream);232 i += chunk;233 }234 fclose(stream);235 return EXIT_SUCCESS;236 }237 238 #if defined HAVE_GETLINE239 /* getdelim() and getc() calls */240 static int zzcat_getline_getc(char const *name, unsigned char *data,241 int64_t len, int getc_method)242 {243 FILE *stream = fopen(name, "r");244 int i = 0, j;245 char c;246 if(!stream)247 return EXIT_FAILURE;248 (void)len;249 while ((c = mygetc(stream, getc_method)) != EOF)250 {251 char *line;252 ssize_t ret;253 size_t n;254 255 ungetc(c, stream);256 line = NULL;257 ret = getline(&line, &n, stream);258 for (j = 0; j < ret; i++, j++)259 data[i] = line[j];260 }261 fclose(stream);262 return EXIT_SUCCESS;263 }264 #endif265 266 /* One fseek(), then only getc() or fgetc() calls */267 static int zzcat_fseek_getc(char const *name, unsigned char *data,268 int64_t len, int64_t chunk, int getc_method)269 {270 FILE *stream = fopen(name, "r");271 int i;272 if(!stream)273 return EXIT_FAILURE;274 if (chunk)275 fseek(stream, chunk, SEEK_CUR);276 for(i = chunk; i < len; i++)277 data[i] = mygetc(stream, getc_method);278 fclose(stream);279 return EXIT_SUCCESS;280 }281 282 /* One fread(), then only getc() or fgetc() calls */283 static int zzcat_fread_getc(char const *name, unsigned char *data,284 int64_t len, int64_t chunk, int getc_method)285 {286 FILE *stream = fopen(name, "r");287 int i;288 if(!stream)289 return EXIT_FAILURE;290 if (chunk)291 fread(data, 1, chunk, stream);292 for(i = chunk; i < len; i++)293 data[i] = mygetc(stream, getc_method);294 fclose(stream);295 390 return EXIT_SUCCESS; 296 391 } … … 376 471 } 377 472 #endif 378 473 #endif 474
Note: See TracChangeset
for help on using the changeset viewer.
