]>
diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/miscellany/patch-2.0.12u8/inp.c
1 /* $Header: inp.c,v 2.0.1.1 88/06/03 15:06:13 lwall Locked $
4 * Revision 2.0.1.1 88/06/03 15:06:13 lwall
5 * patch10: made a little smarter about sccs files
7 * Revision 2.0 86/09/17 15:37:02 lwall
8 * Baseline for netwide release.
19 /* Input-file-with-indexable-lines abstract type */
21 static long i_size
; /* size of the input file */
22 static char *i_womp
; /* plan a buffer for entire file */
23 static char **i_ptr
; /* pointers to lines in i_womp */
25 static int tifd
= -1; /* plan b virtual string array */
26 static char *tibuf
[2]; /* plan b buffers */
27 static LINENUM tiline
[2] = {-1, -1}; /* 1st line in each buffer */
28 static LINENUM lines_per_buf
; /* how many lines per buffer */
29 static int tireclen
; /* length of records in tmp file */
31 /* New patch--prepare to edit another file. */
39 if (i_ptr
!= Null(char**))
45 i_ptr
= Null(char **);
48 using_plan_a
= TRUE
; /* maybe the next one is smaller */
53 tibuf
[0] = tibuf
[1] = Nullch
;
54 tiline
[0] = tiline
[1] = -1;
59 /* Constuct the line index, somehow or other. */
65 if (!plan_a(filename
))
68 say3("Patching file %s using Plan %s...\n", filename
,
69 (using_plan_a
? "A" : "B") );
73 /* Try keeping everything in memory. */
82 char lbuf
[MAXLINELEN
];
84 statfailed
= stat(filename
, &filestat
);
85 if (statfailed
&& ok_to_create_file
) {
87 say2("(Creating file %s...)\n",filename
);
88 makedirs(filename
, TRUE
);
89 close(creat(filename
, 0666));
90 statfailed
= stat(filename
, &filestat
);
92 /* For nonexistent or read-only files, look for RCS or SCCS versions. */
94 /* No one can write to it. */
95 || (filestat
.st_mode
& 0222) == 0
96 /* I can't write to it. */
97 || ((filestat
.st_mode
& 0022) == 0 && filestat
.st_uid
!= myuid
)) {
103 filebase
= basename(filename
);
104 pathlen
= filebase
- filename
;
106 /* Put any leading path into `s'.
107 Leave room in lbuf for the diff command. */
109 strncpy(s
, filename
, pathlen
);
111 #define try(f, a1, a2) (Sprintf(s + pathlen, f, a1, a2), stat(s, &cstat) == 0)
112 if ( try("RCS/%s%s", filebase
, RCSSUFFIX
)
113 || try("RCS/%s" , filebase
, 0)
114 || try( "%s%s", filebase
, RCSSUFFIX
)) {
115 Sprintf(buf
, CHECKOUT
, filename
);
116 Sprintf(lbuf
, RCSDIFF
, filename
);
118 } else if ( try("SCCS/%s%s", SCCSPREFIX
, filebase
)
119 || try( "%s%s", SCCSPREFIX
, filebase
)) {
120 Sprintf(buf
, GET
, s
);
121 Sprintf(lbuf
, SCCSDIFF
, s
, filename
);
123 } else if (statfailed
)
124 fatal2("can't find %s\n", filename
);
125 /* else we can't write to it but it's not under a version
126 control system, so just proceed. */
129 if ((filestat
.st_mode
& 0222) != 0)
130 /* The owner can write to it. */
131 fatal3("file %s seems to be locked by somebody else under %s\n",
133 /* It might be checked out unlocked. See if it's safe to
134 check out the default version locked. */
136 say3("Comparing file %s to default %s version...\n",
139 fatal3("can't check out file %s: differs from default %s version\n",
143 say3("Checking out file %s from %s...\n", filename
, cs
);
144 if (system(buf
) || stat(filename
, &filestat
))
145 fatal3("can't check out file %s from %s\n", filename
, cs
);
148 filemode
= filestat
.st_mode
;
149 if (!S_ISREG(filemode
))
150 fatal2("%s is not a normal file--can't patch\n", filename
);
151 i_size
= filestat
.st_size
;
153 set_hunkmax(); /* make sure dynamic arrays are allocated */
155 return FALSE
; /* force plan b because plan a bombed */
160 i_womp
= malloc((MEM
)(i_size
+2)); /* lint says this may alloc less than */
161 /* i_size, but that's okay, I think. */
163 if (i_womp
== Nullch
)
165 if ((ifd
= open(filename
, 0)) < 0)
166 pfatal2("can't open file %s", filename
);
168 if (read(ifd
, i_womp
, (int)i_size
) != i_size
) {
169 Close(ifd
); /* probably means i_size > 15 or 16 bits worth */
170 free(i_womp
); /* at this point it doesn't matter if i_womp was */
171 return FALSE
; /* undersized. */
175 if (i_size
&& i_womp
[i_size
-1] != '\n')
176 i_womp
[i_size
++] = '\n';
177 i_womp
[i_size
] = '\0';
179 /* count the lines in the buffer so we know how many pointers we need */
182 for (s
=i_womp
; *s
; s
++) {
187 i_ptr
= Null(char**);
189 i_ptr
= (char **)malloc((MEM
)((iline
+ 2) * sizeof(char *)));
191 if (i_ptr
== Null(char **)) { /* shucks, it was a near thing */
192 free((char *)i_womp
);
196 /* now scan the buffer and build pointer array */
199 i_ptr
[iline
] = i_womp
;
200 for (s
=i_womp
; *s
; s
++) {
202 i_ptr
[++iline
] = s
+1; /* these are NOT null terminated */
204 input_lines
= iline
- 1;
206 /* now check for revision, if any */
208 if (revision
!= Nullch
) {
209 if (!rev_in_string(i_womp
)) {
213 "Warning: this file doesn't appear to be the %s version--patching anyway.\n",
218 "this file doesn't appear to be the %s version--aborting.\n", revision
);
222 "This file doesn't appear to be the %s version--patch anyway? [n] ",
229 say2("Good. This file appears to be the %s version.\n",
232 return TRUE
; /* plan a will work */
235 /* Keep (virtually) nothing in memory. */
244 Reg4
bool found_revision
= (revision
== Nullch
);
246 using_plan_a
= FALSE
;
247 if ((ifp
= fopen(filename
, "r")) == Nullfp
)
248 pfatal2("can't open file %s", filename
);
249 if ((tifd
= creat(TMPINNAME
, 0666)) < 0)
250 pfatal2("can't open file %s", TMPINNAME
);
251 while (fgets(buf
, sizeof buf
, ifp
) != Nullch
) {
252 if (revision
!= Nullch
&& !found_revision
&& rev_in_string(buf
))
253 found_revision
= TRUE
;
254 if ((i
= strlen(buf
)) > maxlen
)
255 maxlen
= i
; /* find longest line */
257 if (revision
!= Nullch
) {
258 if (!found_revision
) {
262 "Warning: this file doesn't appear to be the %s version--patching anyway.\n",
267 "this file doesn't appear to be the %s version--aborting.\n", revision
);
271 "This file doesn't appear to be the %s version--patch anyway? [n] ",
278 say2("Good. This file appears to be the %s version.\n",
281 Fseek(ifp
, 0L, 0); /* rewind file */
282 lines_per_buf
= BUFFERSIZE
/ maxlen
;
284 tibuf
[0] = malloc((MEM
)(BUFFERSIZE
+ 1));
285 tibuf
[1] = malloc((MEM
)(BUFFERSIZE
+ 1));
286 if (tibuf
[1] == Nullch
)
287 fatal1("out of memory\n");
289 if (! (i
% lines_per_buf
)) /* new block */
290 if (write(tifd
, tibuf
[0], BUFFERSIZE
) < BUFFERSIZE
)
291 pfatal1("can't write temp file");
292 if (fgets(tibuf
[0] + maxlen
* (i%lines_per_buf
), maxlen
+ 1, ifp
)
295 if (i
% lines_per_buf
)
296 if (write(tifd
, tibuf
[0], BUFFERSIZE
) < BUFFERSIZE
)
297 pfatal1("can't write temp file");
303 if ((tifd
= open(TMPINNAME
, 0)) < 0) {
304 pfatal2("can't reopen file %s", TMPINNAME
);
308 /* Fetch a line from the input file, \n terminated, not necessarily \0. */
311 ifetch(line
,whichbuf
)
313 int whichbuf
; /* ignored when file in memory */
315 if (line
< 1 || line
> input_lines
)
320 LINENUM offline
= line
% lines_per_buf
;
321 LINENUM baseline
= line
- offline
;
323 if (tiline
[0] == baseline
)
325 else if (tiline
[1] == baseline
)
328 tiline
[whichbuf
] = baseline
;
329 #ifndef lint /* complains of long accuracy */
330 Lseek(tifd
, (long)baseline
/ lines_per_buf
* BUFFERSIZE
, 0);
332 if (read(tifd
, tibuf
[whichbuf
], BUFFERSIZE
) < 0)
333 pfatal2("error reading tmp file %s", TMPINNAME
);
335 return tibuf
[whichbuf
] + (tireclen
*offline
);
339 /* True if the string argument contains the revision number we want. */
342 rev_in_string(string
)
348 if (revision
== Nullch
)
350 patlen
= strlen(revision
);
351 if (strnEQ(string
,revision
,patlen
) && isspace(string
[patlen
]))
353 for (s
= string
; *s
; s
++) {
354 if (isspace(*s
) && strnEQ(s
+1, revision
, patlen
) &&
355 isspace(s
[patlen
+1] )) {