inp.c

Go to the documentation of this file.
00001 /* $Header: /opt/proj/minix/cvsroot/src/commands/patch/inp.c,v 1.1.1.1 2005/04/21 14:55:10 beng Exp $
00002  *
00003  * $Log: inp.c,v $
00004  * Revision 1.1.1.1  2005/04/21 14:55:10  beng
00005  * Initial import of pre-3.0.1
00006  *
00007  * Revision 1.1.1.1  2005/04/20 13:33:18  beng
00008  * Initial import of minix 2.0.4
00009  *
00010  * Revision 2.0.1.1  88/06/03  15:06:13  lwall
00011  * patch10: made a little smarter about sccs files
00012  * 
00013  * Revision 2.0  86/09/17  15:37:02  lwall
00014  * Baseline for netwide release.
00015  * 
00016  */
00017 
00018 #include "EXTERN.h"
00019 #include "common.h"
00020 #include "util.h"
00021 #include "pch.h"
00022 #include "INTERN.h"
00023 #include "inp.h"
00024 
00025 /* Input-file-with-indexable-lines abstract type */
00026 
00027 static long i_size;                     /* size of the input file */
00028 static char *i_womp;                    /* plan a buffer for entire file */
00029 static char **i_ptr;                    /* pointers to lines in i_womp */
00030 
00031 static int tifd = -1;                   /* plan b virtual string array */
00032 static char *tibuf[2];                  /* plan b buffers */
00033 static LINENUM tiline[2] = {-1, -1};    /* 1st line in each buffer */
00034 static LINENUM lines_per_buf;           /* how many lines per buffer */
00035 static int tireclen;                    /* length of records in tmp file */
00036 
00037 /* New patch--prepare to edit another file. */
00038 
00039 void
00040 re_input()
00041 {
00042     if (using_plan_a) {
00043         i_size = 0;
00044 #ifndef lint
00045         if (i_ptr != Null(char**))
00046             free((char *)i_ptr);
00047 #endif
00048         if (i_womp != Nullch)
00049             free(i_womp);
00050         i_womp = Nullch;
00051         i_ptr = Null(char **);
00052     }
00053     else {
00054 #ifndef SMALL
00055         using_plan_a = TRUE;            /* maybe the next one is smaller */
00056 #endif
00057         Close(tifd);
00058         tifd = -1;
00059         free(tibuf[0]);
00060         free(tibuf[1]);
00061         tibuf[0] = tibuf[1] = Nullch;
00062         tiline[0] = tiline[1] = -1;
00063         tireclen = 0;
00064     }
00065 }
00066 
00067 /* Constuct the line index, somehow or other. */
00068 
00069 void
00070 scan_input(filename)
00071 char *filename;
00072 {
00073 #ifndef SMALL
00074     if (!plan_a(filename))
00075 #endif
00076         plan_b(filename);
00077     if (verbose) {
00078         say3("Patching file %s using Plan %s...\n", filename,
00079           (using_plan_a ? "A" : "B") );
00080     }
00081 }
00082 
00083 #ifndef SMALL
00084 /* Try keeping everything in memory. */
00085 
00086 bool
00087 plan_a(filename)
00088 char *filename;
00089 {
00090     int ifd;
00091     Reg1 char *s;
00092     Reg2 LINENUM iline;
00093 
00094     if (ok_to_create_file && stat(filename, &filestat) < 0) {
00095         if (verbose)
00096             say2("(Creating file %s...)\n",filename);
00097         makedirs(filename, TRUE);
00098         close(creat(filename, 0666));
00099     }
00100     if (stat(filename, &filestat) < 0) {
00101         Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
00102         if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
00103             Sprintf(buf, CHECKOUT, filename);
00104             if (verbose)
00105                 say2("Can't find %s--attempting to check it out from RCS.\n",
00106                     filename);
00107             if (system(buf) || stat(filename, &filestat))
00108                 fatal2("Can't check out %s.\n", filename);
00109         }
00110         else {
00111             Sprintf(buf+20, "SCCS/%s%s", SCCSPREFIX, filename);
00112             if (stat(s=buf+20, &filestat) >= 0 ||
00113               stat(s=buf+25, &filestat) >= 0) {
00114                 Sprintf(buf, GET, s);
00115                 if (verbose)
00116                     say2("Can't find %s--attempting to get it from SCCS.\n",
00117                         filename);
00118                 if (system(buf) || stat(filename, &filestat))
00119                     fatal2("Can't get %s.\n", filename);
00120             }
00121             else
00122                 fatal2("Can't find %s.\n", filename);
00123         }
00124     }
00125     filemode = filestat.st_mode;
00126     if ((filemode & S_IFMT) & ~S_IFREG)
00127         fatal2("%s is not a normal file--can't patch.\n", filename);
00128     i_size = filestat.st_size;
00129     if (out_of_mem) {
00130         set_hunkmax();          /* make sure dynamic arrays are allocated */
00131         out_of_mem = FALSE;
00132         return FALSE;                   /* force plan b because plan a bombed */
00133     }
00134 #ifdef lint
00135     i_womp = Nullch;
00136 #else
00137     i_womp = malloc((MEM)(i_size+2));   /* lint says this may alloc less than */
00138                                         /* i_size, but that's okay, I think. */
00139 #endif
00140     if (i_womp == Nullch)
00141         return FALSE;
00142     if ((ifd = open(filename, 0)) < 0)
00143         fatal2("Can't open file %s\n", filename);
00144 #ifndef lint
00145     if (read(ifd, i_womp, (int)i_size) != i_size) {
00146         Close(ifd);     /* probably means i_size > 15 or 16 bits worth */
00147         free(i_womp);   /* at this point it doesn't matter if i_womp was */
00148         return FALSE;   /*   undersized. */
00149     }
00150 #endif
00151     Close(ifd);
00152     if (i_size && i_womp[i_size-1] != '\n')
00153         i_womp[i_size++] = '\n';
00154     i_womp[i_size] = '\0';
00155 
00156     /* count the lines in the buffer so we know how many pointers we need */
00157 
00158     iline = 0;
00159     for (s=i_womp; *s; s++) {
00160         if (*s == '\n')
00161             iline++;
00162     }
00163 #ifdef lint
00164     i_ptr = Null(char**);
00165 #else
00166     i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
00167 #endif
00168     if (i_ptr == Null(char **)) {       /* shucks, it was a near thing */
00169         free((char *)i_womp);
00170         return FALSE;
00171     }
00172     
00173     /* now scan the buffer and build pointer array */
00174 
00175     iline = 1;
00176     i_ptr[iline] = i_womp;
00177     for (s=i_womp; *s; s++) {
00178         if (*s == '\n')
00179             i_ptr[++iline] = s+1;       /* these are NOT null terminated */
00180     }
00181     input_lines = iline - 1;
00182 
00183     /* now check for revision, if any */
00184 
00185     if (revision != Nullch) { 
00186         if (!rev_in_string(i_womp)) {
00187             if (force) {
00188                 if (verbose)
00189                     say2(
00190 "Warning: this file doesn't appear to be the %s version--patching anyway.\n",
00191                         revision);
00192             }
00193             else {
00194                 ask2(
00195 "This file doesn't appear to be the %s version--patch anyway? [n] ",
00196                     revision);
00197             if (*buf != 'y')
00198                 fatal1("Aborted.\n");
00199             }
00200         }
00201         else if (verbose)
00202             say2("Good.  This file appears to be the %s version.\n",
00203                 revision);
00204     }
00205     return TRUE;                        /* plan a will work */
00206 }
00207 #endif
00208 
00209 /* Keep (virtually) nothing in memory. */
00210 
00211 void
00212 plan_b(filename)
00213 char *filename;
00214 {
00215     Reg3 FILE *ifp;
00216     Reg1 int i = 0;
00217     Reg2 int maxlen = 1;
00218     Reg4 bool found_revision = (revision == Nullch);
00219 
00220     using_plan_a = FALSE;
00221     if ((ifp = fopen(filename, "r")) == Nullfp)
00222         fatal2("Can't open file %s\n", filename);
00223     if ((tifd = creat(TMPINNAME, 0666)) < 0)
00224         fatal2("Can't open file %s\n", TMPINNAME);
00225     while (fgets(buf, sizeof buf, ifp) != Nullch) {
00226         if (revision != Nullch && !found_revision && rev_in_string(buf))
00227             found_revision = TRUE;
00228         if ((i = strlen(buf)) > maxlen)
00229             maxlen = i;                 /* find longest line */
00230     }
00231     if (revision != Nullch) {
00232         if (!found_revision) {
00233             if (force) {
00234                 if (verbose)
00235                     say2(
00236 "Warning: this file doesn't appear to be the %s version--patching anyway.\n",
00237                         revision);
00238             }
00239             else {
00240                 ask2(
00241 "This file doesn't appear to be the %s version--patch anyway? [n] ",
00242                     revision);
00243                 if (*buf != 'y')
00244                     fatal1("Aborted.\n");
00245             }
00246         }
00247         else if (verbose)
00248             say2("Good.  This file appears to be the %s version.\n",
00249                 revision);
00250     }
00251     Fseek(ifp, 0L, 0);          /* rewind file */
00252     lines_per_buf = BUFFERSIZE / maxlen;
00253     tireclen = maxlen;
00254     tibuf[0] = (char *)malloc((MEM)(BUFFERSIZE + 1));
00255     tibuf[1] = (char *)malloc((MEM)(BUFFERSIZE + 1));
00256     if (tibuf[1] == Nullch)
00257         fatal1("Can't seem to get enough memory.\n");
00258     for (i=1; ; i++) {
00259         if (! (i % lines_per_buf))      /* new block */
00260             if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
00261                 fatal1("patch: can't write temp file.\n");
00262         if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
00263           == Nullch) {
00264             input_lines = i - 1;
00265             if (i % lines_per_buf)
00266                 if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
00267                     fatal1("patch: can't write temp file.\n");
00268             break;
00269         }
00270     }
00271     Fclose(ifp);
00272     Close(tifd);
00273     if ((tifd = open(TMPINNAME, 0)) < 0) {
00274         fatal2("Can't reopen file %s\n", TMPINNAME);
00275     }
00276 }
00277 
00278 /* Fetch a line from the input file, \n terminated, not necessarily \0. */
00279 
00280 char *
00281 ifetch(line,whichbuf)
00282 Reg1 LINENUM line;
00283 int whichbuf;                           /* ignored when file in memory */
00284 {
00285     if (line < 1 || line > input_lines)
00286         return "";
00287     if (using_plan_a)
00288         return i_ptr[line];
00289     else {
00290         LINENUM offline = line % lines_per_buf;
00291         LINENUM baseline = line - offline;
00292 
00293         if (tiline[0] == baseline)
00294             whichbuf = 0;
00295         else if (tiline[1] == baseline)
00296             whichbuf = 1;
00297         else {
00298             tiline[whichbuf] = baseline;
00299 #ifndef lint            /* complains of long accuracy */
00300             Lseek(tifd, (long)baseline / lines_per_buf * BUFFERSIZE, 0);
00301 #endif
00302             if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
00303                 fatal2("Error reading tmp file %s.\n", TMPINNAME);
00304         }
00305         return tibuf[whichbuf] + (tireclen*offline);
00306     }
00307 }
00308 
00309 /* True if the string argument contains the revision number we want. */
00310 
00311 bool
00312 rev_in_string(string)
00313 char *string;
00314 {
00315     Reg1 char *s;
00316     Reg2 int patlen;
00317 
00318     if (revision == Nullch)
00319         return TRUE;
00320     patlen = strlen(revision);
00321     if (strnEQ(string,revision,patlen) && isspace(s[patlen]))
00322         return TRUE;
00323     for (s = string; *s; s++) {
00324         if (isspace(*s) && strnEQ(s+1, revision, patlen) && 
00325                 isspace(s[patlen+1] )) {
00326             return TRUE;
00327         }
00328     }
00329     return FALSE;
00330 }
00331 

Generated on Fri Apr 14 22:57:01 2006 for minix by  doxygen 1.4.6