13297ae0bSbostic /* $Header: inp.c,v 2.0 86/09/17 15:37:02 lwall Exp $
23297ae0bSbostic *
33297ae0bSbostic * $Log: inp.c,v $
43297ae0bSbostic * Revision 2.0 86/09/17 15:37:02 lwall
53297ae0bSbostic * Baseline for netwide release.
63297ae0bSbostic *
73297ae0bSbostic */
83297ae0bSbostic
93297ae0bSbostic #include "EXTERN.h"
103297ae0bSbostic #include "common.h"
113297ae0bSbostic #include "util.h"
123297ae0bSbostic #include "pch.h"
133297ae0bSbostic #include "INTERN.h"
143297ae0bSbostic #include "inp.h"
153297ae0bSbostic
163297ae0bSbostic /* Input-file-with-indexable-lines abstract type */
173297ae0bSbostic
183297ae0bSbostic static long i_size; /* size of the input file */
193297ae0bSbostic static char *i_womp; /* plan a buffer for entire file */
203297ae0bSbostic static char **i_ptr; /* pointers to lines in i_womp */
213297ae0bSbostic
223297ae0bSbostic static int tifd = -1; /* plan b virtual string array */
233297ae0bSbostic static char *tibuf[2]; /* plan b buffers */
243297ae0bSbostic static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
253297ae0bSbostic static LINENUM lines_per_buf; /* how many lines per buffer */
263297ae0bSbostic static int tireclen; /* length of records in tmp file */
273297ae0bSbostic
283297ae0bSbostic /* New patch--prepare to edit another file. */
293297ae0bSbostic
303297ae0bSbostic void
re_input()313297ae0bSbostic re_input()
323297ae0bSbostic {
333297ae0bSbostic if (using_plan_a) {
343297ae0bSbostic i_size = 0;
353297ae0bSbostic #ifndef lint
363297ae0bSbostic if (i_ptr != Null(char**))
373297ae0bSbostic free((char *)i_ptr);
383297ae0bSbostic #endif
393297ae0bSbostic if (i_womp != Nullch)
403297ae0bSbostic free(i_womp);
413297ae0bSbostic i_womp = Nullch;
423297ae0bSbostic i_ptr = Null(char **);
433297ae0bSbostic }
443297ae0bSbostic else {
453297ae0bSbostic using_plan_a = TRUE; /* maybe the next one is smaller */
463297ae0bSbostic Close(tifd);
473297ae0bSbostic tifd = -1;
483297ae0bSbostic free(tibuf[0]);
493297ae0bSbostic free(tibuf[1]);
503297ae0bSbostic tibuf[0] = tibuf[1] = Nullch;
513297ae0bSbostic tiline[0] = tiline[1] = -1;
523297ae0bSbostic tireclen = 0;
533297ae0bSbostic }
543297ae0bSbostic }
553297ae0bSbostic
563297ae0bSbostic /* Constuct the line index, somehow or other. */
573297ae0bSbostic
583297ae0bSbostic void
scan_input(filename)593297ae0bSbostic scan_input(filename)
603297ae0bSbostic char *filename;
613297ae0bSbostic {
623297ae0bSbostic if (!plan_a(filename))
633297ae0bSbostic plan_b(filename);
643297ae0bSbostic if (verbose) {
653297ae0bSbostic say3("Patching file %s using Plan %s...\n", filename,
663297ae0bSbostic (using_plan_a ? "A" : "B") );
673297ae0bSbostic }
683297ae0bSbostic }
693297ae0bSbostic
703297ae0bSbostic /* Try keeping everything in memory. */
713297ae0bSbostic
723297ae0bSbostic bool
plan_a(filename)733297ae0bSbostic plan_a(filename)
743297ae0bSbostic char *filename;
753297ae0bSbostic {
763297ae0bSbostic int ifd;
773297ae0bSbostic Reg1 char *s;
783297ae0bSbostic Reg2 LINENUM iline;
793297ae0bSbostic
803297ae0bSbostic if (ok_to_create_file && stat(filename, &filestat) < 0) {
813297ae0bSbostic if (verbose)
823297ae0bSbostic say2("(Creating file %s...)\n",filename);
833297ae0bSbostic makedirs(filename, TRUE);
843297ae0bSbostic close(creat(filename, 0666));
853297ae0bSbostic }
863297ae0bSbostic if (stat(filename, &filestat) < 0) {
873297ae0bSbostic Sprintf(buf, "RCS/%s%s", filename, RCSSUFFIX);
883297ae0bSbostic if (stat(buf, &filestat) >= 0 || stat(buf+4, &filestat) >= 0) {
893297ae0bSbostic Sprintf(buf, CHECKOUT, filename);
903297ae0bSbostic if (verbose)
913297ae0bSbostic say2("Can't find %s--attempting to check it out from RCS.\n",
923297ae0bSbostic filename);
933297ae0bSbostic if (system(buf) || stat(filename, &filestat))
943297ae0bSbostic fatal2("Can't check out %s.\n", filename);
953297ae0bSbostic }
963297ae0bSbostic else {
973297ae0bSbostic Sprintf(buf, "SCCS/%s%s", SCCSPREFIX, filename);
983297ae0bSbostic if (stat(buf, &filestat) >= 0 || stat(buf+5, &filestat) >= 0) {
993297ae0bSbostic Sprintf(buf, GET, filename);
1003297ae0bSbostic if (verbose)
1013297ae0bSbostic say2("Can't find %s--attempting to get it from SCCS.\n",
1023297ae0bSbostic filename);
1033297ae0bSbostic if (system(buf) || stat(filename, &filestat))
1043297ae0bSbostic fatal2("Can't get %s.\n", filename);
1053297ae0bSbostic }
1063297ae0bSbostic else
1073297ae0bSbostic fatal2("Can't find %s.\n", filename);
1083297ae0bSbostic }
1093297ae0bSbostic }
1103297ae0bSbostic filemode = filestat.st_mode;
1113297ae0bSbostic if ((filemode & S_IFMT) & ~S_IFREG)
1123297ae0bSbostic fatal2("%s is not a normal file--can't patch.\n", filename);
1133297ae0bSbostic i_size = filestat.st_size;
1143297ae0bSbostic if (out_of_mem) {
1153297ae0bSbostic set_hunkmax(); /* make sure dynamic arrays are allocated */
1163297ae0bSbostic out_of_mem = FALSE;
1173297ae0bSbostic return FALSE; /* force plan b because plan a bombed */
1183297ae0bSbostic }
1193297ae0bSbostic #ifdef lint
1203297ae0bSbostic i_womp = Nullch;
1213297ae0bSbostic #else
1223297ae0bSbostic i_womp = malloc((MEM)(i_size+2)); /* lint says this may alloc less than */
1233297ae0bSbostic /* i_size, but that's okay, I think. */
1243297ae0bSbostic #endif
1253297ae0bSbostic if (i_womp == Nullch)
1263297ae0bSbostic return FALSE;
1273297ae0bSbostic if ((ifd = open(filename, 0)) < 0)
1283297ae0bSbostic fatal2("Can't open file %s\n", filename);
1293297ae0bSbostic #ifndef lint
1303297ae0bSbostic if (read(ifd, i_womp, (int)i_size) != i_size) {
1313297ae0bSbostic Close(ifd); /* probably means i_size > 15 or 16 bits worth */
1323297ae0bSbostic free(i_womp); /* at this point it doesn't matter if i_womp was */
1333297ae0bSbostic return FALSE; /* undersized. */
1343297ae0bSbostic }
1353297ae0bSbostic #endif
1363297ae0bSbostic Close(ifd);
1373297ae0bSbostic if (i_size && i_womp[i_size-1] != '\n')
1383297ae0bSbostic i_womp[i_size++] = '\n';
1393297ae0bSbostic i_womp[i_size] = '\0';
1403297ae0bSbostic
1413297ae0bSbostic /* count the lines in the buffer so we know how many pointers we need */
1423297ae0bSbostic
1433297ae0bSbostic iline = 0;
1443297ae0bSbostic for (s=i_womp; *s; s++) {
1453297ae0bSbostic if (*s == '\n')
1463297ae0bSbostic iline++;
1473297ae0bSbostic }
1483297ae0bSbostic #ifdef lint
1493297ae0bSbostic i_ptr = Null(char**);
1503297ae0bSbostic #else
1513297ae0bSbostic i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
1523297ae0bSbostic #endif
1533297ae0bSbostic if (i_ptr == Null(char **)) { /* shucks, it was a near thing */
1543297ae0bSbostic free((char *)i_womp);
1553297ae0bSbostic return FALSE;
1563297ae0bSbostic }
1573297ae0bSbostic
1583297ae0bSbostic /* now scan the buffer and build pointer array */
1593297ae0bSbostic
1603297ae0bSbostic iline = 1;
1613297ae0bSbostic i_ptr[iline] = i_womp;
1623297ae0bSbostic for (s=i_womp; *s; s++) {
1633297ae0bSbostic if (*s == '\n')
1643297ae0bSbostic i_ptr[++iline] = s+1; /* these are NOT null terminated */
1653297ae0bSbostic }
1663297ae0bSbostic input_lines = iline - 1;
1673297ae0bSbostic
1683297ae0bSbostic /* now check for revision, if any */
1693297ae0bSbostic
1703297ae0bSbostic if (revision != Nullch) {
1713297ae0bSbostic if (!rev_in_string(i_womp)) {
1723297ae0bSbostic if (force) {
1733297ae0bSbostic if (verbose)
1743297ae0bSbostic say2("\
1753297ae0bSbostic Warning: this file doesn't appear to be the %s version--patching anyway.\n",
1763297ae0bSbostic revision);
1773297ae0bSbostic }
1783297ae0bSbostic else {
1793297ae0bSbostic ask2("\
1803297ae0bSbostic This file doesn't appear to be the %s version--patch anyway? [n] ",
1813297ae0bSbostic revision);
1823297ae0bSbostic if (*buf != 'y')
1833297ae0bSbostic fatal1("Aborted.\n");
1843297ae0bSbostic }
1853297ae0bSbostic }
1863297ae0bSbostic else if (verbose)
1873297ae0bSbostic say2("Good. This file appears to be the %s version.\n",
1883297ae0bSbostic revision);
1893297ae0bSbostic }
1903297ae0bSbostic return TRUE; /* plan a will work */
1913297ae0bSbostic }
1923297ae0bSbostic
1933297ae0bSbostic /* Keep (virtually) nothing in memory. */
1943297ae0bSbostic
1953297ae0bSbostic void
plan_b(filename)1963297ae0bSbostic plan_b(filename)
1973297ae0bSbostic char *filename;
1983297ae0bSbostic {
1993297ae0bSbostic Reg3 FILE *ifp;
2003297ae0bSbostic Reg1 int i = 0;
2013297ae0bSbostic Reg2 int maxlen = 1;
2023297ae0bSbostic Reg4 bool found_revision = (revision == Nullch);
2033297ae0bSbostic
2043297ae0bSbostic using_plan_a = FALSE;
2053297ae0bSbostic if ((ifp = fopen(filename, "r")) == Nullfp)
2063297ae0bSbostic fatal2("Can't open file %s\n", filename);
2073297ae0bSbostic if ((tifd = creat(TMPINNAME, 0666)) < 0)
2083297ae0bSbostic fatal2("Can't open file %s\n", TMPINNAME);
2093297ae0bSbostic while (fgets(buf, sizeof buf, ifp) != Nullch) {
2103297ae0bSbostic if (revision != Nullch && !found_revision && rev_in_string(buf))
2113297ae0bSbostic found_revision = TRUE;
2123297ae0bSbostic if ((i = strlen(buf)) > maxlen)
2133297ae0bSbostic maxlen = i; /* find longest line */
2143297ae0bSbostic }
2153297ae0bSbostic if (revision != Nullch) {
2163297ae0bSbostic if (!found_revision) {
2173297ae0bSbostic if (force) {
2183297ae0bSbostic if (verbose)
2193297ae0bSbostic say2("\
2203297ae0bSbostic Warning: this file doesn't appear to be the %s version--patching anyway.\n",
2213297ae0bSbostic revision);
2223297ae0bSbostic }
2233297ae0bSbostic else {
2243297ae0bSbostic ask2("\
2253297ae0bSbostic This file doesn't appear to be the %s version--patch anyway? [n] ",
2263297ae0bSbostic revision);
2273297ae0bSbostic if (*buf != 'y')
2283297ae0bSbostic fatal1("Aborted.\n");
2293297ae0bSbostic }
2303297ae0bSbostic }
2313297ae0bSbostic else if (verbose)
2323297ae0bSbostic say2("Good. This file appears to be the %s version.\n",
2333297ae0bSbostic revision);
2343297ae0bSbostic }
2353297ae0bSbostic Fseek(ifp, 0L, 0); /* rewind file */
2363297ae0bSbostic lines_per_buf = BUFFERSIZE / maxlen;
2373297ae0bSbostic tireclen = maxlen;
2383297ae0bSbostic tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
2393297ae0bSbostic tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
2403297ae0bSbostic if (tibuf[1] == Nullch)
2413297ae0bSbostic fatal1("Can't seem to get enough memory.\n");
2423297ae0bSbostic for (i=1; ; i++) {
2433297ae0bSbostic if (! (i % lines_per_buf)) /* new block */
2443297ae0bSbostic if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
2453297ae0bSbostic fatal1("patch: can't write temp file.\n");
2463297ae0bSbostic if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
2473297ae0bSbostic == Nullch) {
2483297ae0bSbostic input_lines = i - 1;
2493297ae0bSbostic if (i % lines_per_buf)
2503297ae0bSbostic if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
2513297ae0bSbostic fatal1("patch: can't write temp file.\n");
2523297ae0bSbostic break;
2533297ae0bSbostic }
2543297ae0bSbostic }
2553297ae0bSbostic Fclose(ifp);
2563297ae0bSbostic Close(tifd);
2573297ae0bSbostic if ((tifd = open(TMPINNAME, 0)) < 0) {
2583297ae0bSbostic fatal2("Can't reopen file %s\n", TMPINNAME);
2593297ae0bSbostic }
2603297ae0bSbostic }
2613297ae0bSbostic
2623297ae0bSbostic /* Fetch a line from the input file, \n terminated, not necessarily \0. */
2633297ae0bSbostic
2643297ae0bSbostic char *
ifetch(line,whichbuf)2653297ae0bSbostic ifetch(line,whichbuf)
2663297ae0bSbostic Reg1 LINENUM line;
2673297ae0bSbostic int whichbuf; /* ignored when file in memory */
2683297ae0bSbostic {
2693297ae0bSbostic if (line < 1 || line > input_lines)
2703297ae0bSbostic return "";
2713297ae0bSbostic if (using_plan_a)
2723297ae0bSbostic return i_ptr[line];
2733297ae0bSbostic else {
2743297ae0bSbostic LINENUM offline = line % lines_per_buf;
2753297ae0bSbostic LINENUM baseline = line - offline;
2763297ae0bSbostic
2773297ae0bSbostic if (tiline[0] == baseline)
2783297ae0bSbostic whichbuf = 0;
2793297ae0bSbostic else if (tiline[1] == baseline)
2803297ae0bSbostic whichbuf = 1;
2813297ae0bSbostic else {
2823297ae0bSbostic tiline[whichbuf] = baseline;
2833297ae0bSbostic #ifndef lint /* complains of long accuracy */
284*5d045ae7Sbostic Lseek(tifd, (off_t)baseline / lines_per_buf * BUFFERSIZE, 0);
2853297ae0bSbostic #endif
2863297ae0bSbostic if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
2873297ae0bSbostic fatal2("Error reading tmp file %s.\n", TMPINNAME);
2883297ae0bSbostic }
2893297ae0bSbostic return tibuf[whichbuf] + (tireclen*offline);
2903297ae0bSbostic }
2913297ae0bSbostic }
2923297ae0bSbostic
2933297ae0bSbostic /* True if the string argument contains the revision number we want. */
2943297ae0bSbostic
2953297ae0bSbostic bool
rev_in_string(string)2963297ae0bSbostic rev_in_string(string)
2973297ae0bSbostic char *string;
2983297ae0bSbostic {
2993297ae0bSbostic Reg1 char *s;
3003297ae0bSbostic Reg2 int patlen;
3013297ae0bSbostic
3023297ae0bSbostic if (revision == Nullch)
3033297ae0bSbostic return TRUE;
3043297ae0bSbostic patlen = strlen(revision);
3053297ae0bSbostic for (s = string; *s; s++) {
3063297ae0bSbostic if (isspace(*s) && strnEQ(s+1, revision, patlen) &&
3073297ae0bSbostic isspace(s[patlen+1] )) {
3083297ae0bSbostic return TRUE;
3093297ae0bSbostic }
3103297ae0bSbostic }
3113297ae0bSbostic return FALSE;
3123297ae0bSbostic }
3133297ae0bSbostic
314