/* reader.c - a program for reading very large files By Jeff Winston http://www.kwcpa.com/tools Rev. 1.2, 2/18/04 Copyright (C) 2002, 2003, 2004 type reader -h for more information --------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. or check out http://www.gnu.org/copyleft/gpl.html --------------------------------------------------------------------- Rev 1.2 - added left border to display To compile: gcc reader.c -o reader */ #include /* string library */ #include /* io library */ #include /* math library */ #define MAXLINES 100000000 /* largest file that can be read */ #define MAXFAIL 5000 /* largest number of fail string pointers in linked list */ char tempstr[1023], /* temporary string */ failstring[1023], /* definition of fail */ infile[80], /* input file name */ cur_line[1023], /* current line of input file (for when file is read in) */ instr[1023], /* input command from the keyboard */ cmd[10], /* parsed command from input command */ seastr[255], /* parsed search string from the input command */ tokens[32][32]; extern char * malloc(); /* declare MALLOC */ void type_range(); int find_string(char *field, char *source); long get_tokens(char *str); char *lineptr[MAXLINES]; /* pointer array */ char *p; /* pointer */ /* variables for reading the file in */ long limit, /* max number of lines to read in */ begin, /* first line to read in */ len, /* length of input line */ line, /* total lines read in */ crlf, /* flag indicating a crlf needs to be added because line was shortened before storing */ /* variables for moving around the file */ rtop, /* top of current range */ width, /* length of current range (in lines) */ /* variables for special features */ found, /* flag used to indicate search success */ mark, /* marked line (for Mark function) */ fail, /* number of lines with fail string in them */ failline[MAXFAIL], /* location of lines with Fail in them */ curfail, /* pointer into Failline */ space_mode, /* extra space between long lines */ gl,m,a,ntk,i,x,z; /* temps */ FILE *infile_ptr, *outfile_ptr; /* file pointers */ main(argc,argv) int argc; /* Parse input and output file from command line */ char *argv[]; { printf("\nReader Rev 1.1 by J. Winston\n"); ++argv; if ((argc ==2) && (strcmp(*argv,"-h")==0)) { printf("\nUse: reader [] []\n"); printf("Where arg1 and arg2 are not given, the entire file is read.\n"); printf("If just arg1 is given, the first *1000 lines of the file are read.\n"); printf("If both arg1 and arg2 are given, the program reads *1000 lines\n"); printf("beginning at line *1000. \n\n"); printf("The user then navigates the file within the program.\n\n"); printf("One string can be coded into the program for special attention.\n"); printf("The program creates a linked list of instances of this string\n"); printf("which the user can quickly page through. The default is \"fail\"\n"); printf("(non-case sensitive). \n\n"); printf("Type ? after loading a file for navigation commands\n\n"); exit(0); } else if ((argc <2) || (argc>4)) { printf("Error: Incorrect number of parameters on command line\n"); printf("Type reader -h for help\n"); exit(0); } strcpy(infile,*argv); if ((infile_ptr=fopen(*argv, "r")) ==NULL) { printf("Error: Error opening input file /%s/\n\n",infile); exit(1); } limit=MAXLINES; begin=0; /* initialize file read parameters, get args */ if ((argc==3) || (argc==4)) { ++argv; strcpy(tempstr,*argv); sscanf(tempstr,"%d",&z); if ((z*1000) < limit) limit=z*1000; } if (argc==4) { ++argv; strcpy(tempstr,*argv); sscanf(tempstr,"%d",&begin); begin = begin*1000; } m=0;gl=0; fail=0; /* initialize variables */ curfail=0; failline[0]=0; space_mode=0; line=0; rtop=0; width=22; strcpy(seastr,"#*$#$"); strcpy(failstring,"fail"); /* default fail string - case-sensitive*/ printf("Reading input file...line 1"); /* read input file */ fflush(stdout); if (begin >0) { z=begin; printf("...Advancing"); while ((fgets(cur_line,1023,infile_ptr) != NULL) && (begin > 0)) { begin--; if ( (begin/50000)*50000 == begin) { printf("."); fflush (stdout); } } printf("\n"); fflush(stdout); if (begin > 0) {printf("\nexiting at line #%d\n",z-begin);exit(0);} } x=0; while ((fgets(cur_line,511,infile_ptr) != NULL) && (line < limit)) { len=strlen(cur_line); crlf=0; if (len > 1023) /* trim strings to 1023 chars */ { len=1023; crlf=1; } p=malloc(len+1+crlf); /* <<<<<====== MALLOC */ strncpy(p,cur_line,len+1+crlf); if (crlf ==1) strcat(p,"\n"); lineptr[line] = p; line++; if (fail < MAXFAIL) { if (find_string(cur_line,failstring)>0) /* record FAILs in Fail array */ { failline[fail]=line; fail++; if (fail == MAXFAIL) printf("\nLinked list of FAILs full (%d entries)\n",fail); } } if ( (line/50000)*50000 == line) /* flag every 50K lines */ { printf(", %dK",line/1000); fflush(stdout); x++; } if ( x==10) { printf("\n"); x=0; } } if (fail > 0) { /* printf("\nDone! (%d lines, %d of which contain \\%s\\). Enter ? for help\n\n",line,fail,failstring);*/ printf("\nDone! (%d lines). Enter ? for help\n\n",line); } else if (line >= limit) { printf("\nDone. Max size exceeded (%d lines). Enter ? for help\n\n",line); } else printf("\nDone! (%d lines). Enter ? for help\n\n",line); mark = 1; while (fgets(instr,255,stdin) != NULL) /* let user view file however he wants */ { len = strlen(instr); if (len <2) type_range(); else { x = len - 1; if (instr[x] == '\n') instr[x] = '\0'; sscanf(instr,"%s",cmd); if (strcmp(cmd,"?")==0) { printf(" Repeat last command\n"); printf("r Refresh screen\n"); printf("t/b Goto Top/Bottom of document\n"); printf("a/p Move ahead/back one window\n"); printf("h/H Move ahead/back 1/2 window\n"); printf("n/l Move ahead/back one line\n"); printf("w <#> Adjust window size (# of lines displayed) to <#>\n"); printf("m/M Mark top line / goto mark \n"); printf("W Write file with lines from file, starting at\n"); printf(" marked line and ending at current bottom line\n"); printf("g <#> Goto line <#>\n"); printf("gf/gb <#> Go forward/back <#> lines\n"); printf("f/F Find string searching forward/backward. If \n"); printf(" is omitted, searches for next instance of last \n"); /* printf("ff/FF Goto next/last line with string \\%s\\ in linked list\n",failstring); */ printf("other: x/q = Quit s = toggle space_mode\n"); } else if (strcmp(cmd,"x")==0) exit(0); /* quit */ else if (strcmp(cmd,"q")==0) exit(0); else if (strcmp(cmd,"r")==0) type_range(); else if (strcmp(cmd,"m")==0) /* mark location */ { mark=rtop; printf("Marked line %d. ",rtop); type_range(); } else if (strcmp(cmd,"M")==0) /* mark location */ { rtop = mark; type_range(); } else if (strcmp(cmd,"t")==0) /* Top of Document */ { rtop=0; curfail=0; type_range(); } else if (strcmp(cmd,"b")==0) /* Bottom of Document */ { curfail=fail; rtop=(line)-width; type_range(); } else if (strcmp(cmd,"a")==0) /* Advance Range */ { rtop=rtop+width-1; if (rtop > (line)-width) rtop = (line)-width; type_range(); } else if (strcmp(cmd,"n")==0) /* next line */ { rtop++; if (rtop > (line)-width) rtop = (line)-width; type_range(); } else if (strcmp(cmd,"p")==0) /* Prior range*/ { rtop=rtop-width+1; if (rtop <0) rtop =0; type_range(); } else if (strcmp(cmd,"h")==0) /* next 1/2 range */ { rtop=rtop+width/2-1; if (rtop > (line)-width) rtop = (line)-width; type_range(); } else if (strcmp(cmd,"H")==0) /* Prior 1/2 range*/ { rtop=rtop-width/2+1; if (rtop <0) rtop =0; type_range(); } else if (strcmp(cmd,"s")==0) /* space mode */ { if (space_mode == 0) space_mode=1; else space_mode = 0; type_range(); } else if (strcmp(cmd,"W")==0) /* write section to file */ { sscanf(instr,"%s %s",cmd,tempstr); if ((outfile_ptr=fopen(tempstr, "w")) ==NULL) { printf("Error: Error opening %s as output\n",tempstr); } else { for (i=mark; i < rtop+width; i++) fprintf(outfile_ptr,"%s",lineptr[i]); fclose(outfile_ptr); printf("Lines %d to %d Written to %s\n",mark,rtop+width,tempstr); type_range(); } } else if (strcmp(cmd,"l")==0) /* Last Line */ { rtop--; if (rtop <0) rtop =0; type_range(); } else if (strcmp(cmd,"w")==0) /* Width */ { sscanf(instr,"%s %d",cmd,&width); if (width < 1) width = 20; if (width > line) width = line; type_range(); } /* select line */ else if (strcmp(cmd,"g")==0) { sscanf(instr,"%s %d",cmd,&rtop); if (rtop < (width/2)) rtop = 0; else if (rtop > line-width) rtop = line-width; else rtop = rtop - (width/2); gl=1; type_range(); gl=0; } else if (strcmp(cmd,"gf")==0) { sscanf(instr,"%s %d",cmd,&x); if (x < 0) x = 0; rtop = rtop + x; if (rtop > (line-width)) rtop = line-width; type_range(); } else if (strcmp(cmd,"gb")==0) { sscanf(instr,"%s %d",cmd,&x); if (x < 0) x = 0; rtop= rtop - x; if (rtop <0) rtop = 0; type_range(); } else if (strcmp(cmd,"ff")==0) /* find fail forward */ { if (fail > 0) { rtop = failline[curfail] - width/2; if (curfail < fail) curfail++; type_range(); } else { printf("No Failures.\n "); } } else if (strcmp(cmd,"FF")==0) /* find fail backward */ { if (fail > 0) { if (curfail >0) curfail--; rtop = failline[curfail] - width/2; type_range(); } else { printf("No Failures.\n "); } } /* find string forward */ else if (strcmp(cmd,"f")==0) { if (strlen(instr) !=1) ntk = get_tokens(instr); i=rtop+width/2; z=i;found=0; printf("Finding /%s/...",seastr); fflush(stdout); while ((i (line-width)) rtop=line-width; else rtop=i-width/2; } printf("\n"); type_range(); } else if (strcmp(cmd,"F")==0) /* find string backward */ { if (strlen(instr) !=1) ntk = get_tokens(instr); i=rtop+width/2; found=0; z=i; printf("Finding \\%s\\...",seastr); fflush(stdout); while ((i>0) && (found==0)) { found=1; for (a=1;a0) rtop=rtop-2; } else printf("Unrecognized command %s (enter ? for help)\n",cmd); } } } void type_range() /* type current range to screen */ { int q; printf("[%d/%d]:\n",rtop,rtop+width-1); for (i=rtop; i<(rtop+width); i++) { if (((m==1) && (found==1)) && ((i-rtop) == (width/2-1))) printf(">>"); else if ((gl==1) && ((i-rtop) == (width/2))) printf(">>"); else { q = i-((i/10) * 10); if ((i != rtop) && (space_mode == 1)) printf("\n"); printf("%1d|",q); } printf("%s",lineptr[i]); /* if (strlen(lineptr[i]) > 80) printf(" %s",&lineptr[i][79]);*/ } m=0; } int find_string(char *field, char *source) /* returns LOC of substring in string */ { int flen; int slen; char *sPtr; int loc; flen = strlen(field); slen = strlen(source); if (slen > flen) return (0); /* error */ else { for (loc=0, sPtr = field; loc <= flen-slen; loc++, sPtr++) { if (strncmp(source,sPtr, slen) ==0) return(loc+1); } } return (0); } long get_tokens(char *str) /* get tokens on line. Put in global tokens[32][32], return count */ { long len, loc, cnt, sp, start,x; len = strlen(str); sp=1; cnt=0; for (loc=0; loc <= len; loc++) { if ( (loc < len) && (str[loc] != ' ') && (str[loc] !=',')) { if (sp==1) { cnt++; sp=0; start=loc; } } else { if (sp==0) { sp=1; strncpy(tokens[cnt-1],&str[start],loc-start); strncpy(&tokens[cnt-1][loc-start],"\0",1); } } } strncpy(seastr,&instr[2],strlen(instr)-2); strncpy(&seastr[strlen(instr)-2],"\0",1); return(cnt); }