1: /* $Header: inp.c,v 2.0.1.2 96/12/7 22:15:00 sms $
   2:  *
   3:  * $Log:	inp.c,v $
   4:  * Revision 2.0.1.2  96/12/7  22:15:00 sms
   5:  * Files right up against 64kb in size caused patch to core dump because
   6:  * a large (negative) value was passed to malloc().  Therefore force
   7:  * plan B for files over 48kb in size if on a pdp-11.
   8:  *
   9:  * Revision 2.0.1.1  88/06/03  15:06:13  lwall
  10:  * patch10: made a little smarter about sccs files
  11:  *
  12:  * Revision 2.0  86/09/17  15:37:02  lwall
  13:  * Baseline for netwide release.
  14:  *
  15:  */
  16: 
  17: #include "EXTERN.h"
  18: #include "common.h"
  19: #include "util.h"
  20: #include "pch.h"
  21: #include "INTERN.h"
  22: #include "inp.h"
  23: 
  24: /* Input-file-with-indexable-lines abstract type */
  25: 
  26: static long i_size;         /* size of the input file */
  27: static char *i_womp;            /* plan a buffer for entire file */
  28: static char **i_ptr;            /* pointers to lines in i_womp */
  29: 
  30: static int tifd = -1;           /* plan b virtual string array */
  31: static char *tibuf[2];          /* plan b buffers */
  32: static LINENUM tiline[2] = {-1, -1};    /* 1st line in each buffer */
  33: static LINENUM lines_per_buf;       /* how many lines per buffer */
  34: static int tireclen;            /* length of records in tmp file */
  35: 
  36: /* New patch--prepare to edit another file. */
  37: 
  38: void
  39: re_input()
  40: {
  41:     if (using_plan_a) {
  42:     i_size = 0;
  43: #ifndef lint
  44:     if (i_ptr != Null(char**))
  45:         free((char *)i_ptr);
  46: #endif
  47:     if (i_womp != Nullch)
  48:         free(i_womp);
  49:     i_womp = Nullch;
  50:     i_ptr = Null(char **);
  51:     }
  52:     else {
  53:     using_plan_a = TRUE;        /* maybe the next one is smaller */
  54:     Close(tifd);
  55:     tifd = -1;
  56:     free(tibuf[0]);
  57:     free(tibuf[1]);
  58:     tibuf[0] = tibuf[1] = Nullch;
  59:     tiline[0] = tiline[1] = -1;
  60:     tireclen = 0;
  61:     }
  62: }
  63: 
  64: /* Constuct the line index, somehow or other. */
  65: 
  66: void
  67: scan_input(filename)
  68: char *filename;
  69: {
  70:     if (!plan_a(filename))
  71:     plan_b(filename);
  72:     if (verbose) {
  73:     say3("Patching file %s using Plan %s...\n", filename,
  74:       (using_plan_a ? "A" : "B") );
  75:     }
  76: }
  77: 
  78: /* Try keeping everything in memory. */
  79: 
  80: bool
  81: plan_a(filename)
  82: char *filename;
  83: {
  84:     int ifd;
  85:     Reg1 char *s;
  86:     Reg2 LINENUM iline;
  87: 
  88:     if (ok_to_create_file && stat(filename, &filestat) < 0) {
  89:     if (verbose)
  90:         say2("(Creating file %s...)\n",filename);
  91:     makedirs(filename, TRUE);
  92:     close(creat(filename, 0666));
  93:     }
  94:     if (stat(filename, &filestat) < 0) {
  95:     Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
  96:     if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
  97:         Sprintf(buf, CHECKOUT, filename);
  98:         if (verbose)
  99:         say2("Can't find %s--attempting to check it out from RCS.\n",
 100:             filename);
 101:         if (system(buf) || stat(filename, &filestat))
 102:         fatal2("Can't check out %s.\n", filename);
 103:     }
 104:     else {
 105:         Sprintf(buf+20, "SCCS/%s%s", SCCSPREFIX, filename);
 106:         if (stat(s=buf+20, &filestat) >= 0 ||
 107:           stat(s=buf+25, &filestat) >= 0) {
 108:         Sprintf(buf, GET, s);
 109:         if (verbose)
 110:             say2("Can't find %s--attempting to get it from SCCS.\n",
 111:             filename);
 112:         if (system(buf) || stat(filename, &filestat))
 113:             fatal2("Can't get %s.\n", filename);
 114:         }
 115:         else
 116:         fatal2("Can't find %s.\n", filename);
 117:     }
 118:     }
 119:     filemode = filestat.st_mode;
 120:     if ((filemode & S_IFMT) & ~S_IFREG)
 121:     fatal2("%s is not a normal file--can't patch.\n", filename);
 122:     i_size = filestat.st_size;
 123: #ifdef  pdp11
 124: /*
 125:  * csh.1 was 65392 bytes long and caused patch to core dump because
 126:  * malloc() couldn't cope.
 127: */
 128:     if (i_size > 49152L)
 129:     return FALSE;
 130: #endif
 131:     if (out_of_mem) {
 132:     set_hunkmax();      /* make sure dynamic arrays are allocated */
 133:     out_of_mem = FALSE;
 134:     return FALSE;           /* force plan b because plan a bombed */
 135:     }
 136: #ifdef lint
 137:     i_womp = Nullch;
 138: #else
 139:     i_womp = malloc((MEM)(i_size+2));   /* lint says this may alloc less than */
 140:                     /* i_size, but that's okay, I think. */
 141: #endif
 142:     if (i_womp == Nullch)
 143:     return FALSE;
 144:     if ((ifd = open(filename, 0)) < 0)
 145:     fatal2("Can't open file %s\n", filename);
 146: #ifndef lint
 147:     if (read(ifd, i_womp, (int)i_size) != i_size) {
 148:     Close(ifd); /* probably means i_size > 15 or 16 bits worth */
 149:     free(i_womp);   /* at this point it doesn't matter if i_womp was */
 150:     return FALSE;   /*   undersized. */
 151:     }
 152: #endif
 153:     Close(ifd);
 154:     if (i_size && i_womp[i_size-1] != '\n')
 155:     i_womp[i_size++] = '\n';
 156:     i_womp[i_size] = '\0';
 157: 
 158:     /* count the lines in the buffer so we know how many pointers we need */
 159: 
 160:     iline = 0;
 161:     for (s=i_womp; *s; s++) {
 162:     if (*s == '\n')
 163:         iline++;
 164:     }
 165: #ifdef lint
 166:     i_ptr = Null(char**);
 167: #else
 168:     i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
 169: #endif
 170:     if (i_ptr == Null(char **)) {   /* shucks, it was a near thing */
 171:     free((char *)i_womp);
 172:     return FALSE;
 173:     }
 174: 
 175:     /* now scan the buffer and build pointer array */
 176: 
 177:     iline = 1;
 178:     i_ptr[iline] = i_womp;
 179:     for (s=i_womp; *s; s++) {
 180:     if (*s == '\n')
 181:         i_ptr[++iline] = s+1;   /* these are NOT null terminated */
 182:     }
 183:     input_lines = iline - 1;
 184: 
 185:     /* now check for revision, if any */
 186: 
 187:     if (revision != Nullch) {
 188:     if (!rev_in_string(i_womp)) {
 189:         if (force) {
 190:         if (verbose)
 191:             say2(
 192: "Warning: this file doesn't appear to be the %s version--patching anyway.\n",
 193:             revision);
 194:         }
 195:         else {
 196:         ask2(
 197: "This file doesn't appear to be the %s version--patch anyway? [n] ",
 198:             revision);
 199:         if (*buf != 'y')
 200:         fatal1("Aborted.\n");
 201:         }
 202:     }
 203:     else if (verbose)
 204:         say2("Good.  This file appears to be the %s version.\n",
 205:         revision);
 206:     }
 207:     return TRUE;            /* plan a will work */
 208: }
 209: 
 210: /* Keep (virtually) nothing in memory. */
 211: 
 212: void
 213: plan_b(filename)
 214: char *filename;
 215: {
 216:     Reg3 FILE *ifp;
 217:     Reg1 int i = 0;
 218:     Reg2 int maxlen = 1;
 219:     Reg4 bool found_revision = (revision == Nullch);
 220: 
 221:     using_plan_a = FALSE;
 222:     if ((ifp = fopen(filename, "r")) == Nullfp)
 223:     fatal2("Can't open file %s\n", filename);
 224:     if ((tifd = creat(TMPINNAME, 0666)) < 0)
 225:     fatal2("Can't open file %s\n", TMPINNAME);
 226:     while (fgets(buf, sizeof buf, ifp) != Nullch) {
 227:     if (revision != Nullch && !found_revision && rev_in_string(buf))
 228:         found_revision = TRUE;
 229:     if ((i = strlen(buf)) > maxlen)
 230:         maxlen = i;         /* find longest line */
 231:     }
 232:     if (revision != Nullch) {
 233:     if (!found_revision) {
 234:         if (force) {
 235:         if (verbose)
 236:             say2(
 237: "Warning: this file doesn't appear to be the %s version--patching anyway.\n",
 238:             revision);
 239:         }
 240:         else {
 241:         ask2(
 242: "This file doesn't appear to be the %s version--patch anyway? [n] ",
 243:             revision);
 244:         if (*buf != 'y')
 245:             fatal1("Aborted.\n");
 246:         }
 247:     }
 248:     else if (verbose)
 249:         say2("Good.  This file appears to be the %s version.\n",
 250:         revision);
 251:     }
 252:     Fseek(ifp, 0L, 0);      /* rewind file */
 253:     lines_per_buf = BUFFERSIZE / maxlen;
 254:     tireclen = maxlen;
 255:     tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
 256:     tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
 257:     if (tibuf[1] == Nullch)
 258:     fatal1("Can't seem to get enough memory.\n");
 259:     for (i=1; ; i++) {
 260:     if (! (i % lines_per_buf))  /* new block */
 261:         if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
 262:         fatal1("patch: can't write temp file.\n");
 263:     if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
 264:       == Nullch) {
 265:         input_lines = i - 1;
 266:         if (i % lines_per_buf)
 267:         if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
 268:             fatal1("patch: can't write temp file.\n");
 269:         break;
 270:     }
 271:     }
 272:     Fclose(ifp);
 273:     Close(tifd);
 274:     if ((tifd = open(TMPINNAME, 0)) < 0) {
 275:     fatal2("Can't reopen file %s\n", TMPINNAME);
 276:     }
 277: }
 278: 
 279: /* Fetch a line from the input file, \n terminated, not necessarily \0. */
 280: 
 281: char *
 282: ifetch(line,whichbuf)
 283: Reg1 LINENUM line;
 284: int whichbuf;               /* ignored when file in memory */
 285: {
 286:     if (line < 1 || line > input_lines)
 287:     return "";
 288:     if (using_plan_a)
 289:     return i_ptr[line];
 290:     else {
 291:     LINENUM offline = line % lines_per_buf;
 292:     LINENUM baseline = line - offline;
 293: 
 294:     if (tiline[0] == baseline)
 295:         whichbuf = 0;
 296:     else if (tiline[1] == baseline)
 297:         whichbuf = 1;
 298:     else {
 299:         tiline[whichbuf] = baseline;
 300: #ifndef lint        /* complains of long accuracy */
 301:         Lseek(tifd, (long)baseline / lines_per_buf * BUFFERSIZE, 0);
 302: #endif
 303:         if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
 304:         fatal2("Error reading tmp file %s.\n", TMPINNAME);
 305:     }
 306:     return tibuf[whichbuf] + (tireclen*offline);
 307:     }
 308: }
 309: 
 310: /* True if the string argument contains the revision number we want. */
 311: 
 312: bool
 313: rev_in_string(string)
 314: char *string;
 315: {
 316:     Reg1 char *s;
 317:     Reg2 int patlen;
 318: 
 319:     if (revision == Nullch)
 320:     return TRUE;
 321:     patlen = strlen(revision);
 322:     if (strnEQ(string,revision,patlen) && isspace(s[patlen]))
 323:     return TRUE;
 324:     for (s = string; *s; s++) {
 325:     if (isspace(*s) && strnEQ(s+1, revision, patlen) &&
 326:         isspace(s[patlen+1] )) {
 327:         return TRUE;
 328:     }
 329:     }
 330:     return FALSE;
 331: }

Defined functions

ifetch defined in line 281; used 4 times
plan_a defined in line 80; used 2 times
plan_b defined in line 212; used 2 times
re_input defined in line 38; used 2 times
rev_in_string defined in line 312; used 3 times
scan_input defined in line 66; used 2 times

Defined variables

i_ptr defined in line 28; used 9 times
i_size defined in line 26; used 10 times
i_womp defined in line 27; used 16 times
lines_per_buf defined in line 33; used 6 times
tibuf defined in line 31; used 12 times
tifd defined in line 30; used 9 times
tiline defined in line 32; used 5 times
tireclen defined in line 34; used 3 times
Last modified: 1996-12-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4146
Valid CSS Valid XHTML 1.0 Strict