# 2.11BSD#431 - /usr/src/usr.bin/patch/inp.c

##### Functions

    ifetch            X
    plan_a            X
    plan_b            X
    re_input          X
    rev_in_string     X
    scan_input        X

       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

- in /usr/src/usr.bin/patch/inp.h line 17
- in /usr/src/usr.bin/patch/patch.c line 751, 768-773(2)

plan_a defined in line 80; used 2 times

- in line 70
- in /usr/src/usr.bin/patch/inp.h line 15

plan_b defined in line 212; used 2 times

- in line 71
- in /usr/src/usr.bin/patch/inp.h line 16

re_input defined in line 38; used 2 times

- in /usr/src/usr.bin/patch/patch.c line 112, 329

rev_in_string defined in line 312; used 3 times

- in line 188, 227
- in /usr/src/usr.bin/patch/inp.h line 13

scan_input defined in line 66; used 2 times

- in /usr/src/usr.bin/patch/inp.h line 14
- in /usr/src/usr.bin/patch/patch.c line 170

#### Defined variables

i_ptr defined in line 28; used 9 times

- in line 44-50(3), 166-170(3), 178-181(2), 289

i_size defined in line 26; used 10 times

- in line 42, 122, 128, 139, 147(2), 154-156(4)

i_womp defined in line 27; used 16 times

- in line 47-49(3), 137-161(9), 171, 178-179(2), 188

lines_per_buf defined in line 33; used 6 times

- in line 253, 260-266(3), 291, 301

tibuf defined in line 31; used 12 times

- in line 56-58(4), 255-267(6), 303-306(2)

tifd defined in line 30; used 9 times

- in line 54-55(2), 224, 261, 267, 273-274(2), 301-303(2)

tiline defined in line 32; used 5 times

- in line 59(2), 294-299(3)

tireclen defined in line 34; used 3 times

- in line 60, 254, 306

Last modified: 1996-12-08 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1781 |