Annotation of src/usr.bin/less/ifile.c, Revision 1.3
1.3 ! mpech 1: /* $OpenBSD: ifile.c,v 1.2 2001/01/29 01:58:02 niklas Exp $ */
1.2 niklas 2:
1.1 etheisen 3: /*
4: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice in the documentation and/or other materials provided with
14: * the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
17: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29:
30: /*
31: * An IFILE represents an input file.
32: *
33: * It is actually a pointer to an ifile structure,
34: * but is opaque outside this module.
35: * Ifile structures are kept in a linked list in the order they
36: * appear on the command line.
37: * Any new file which does not already appear in the list is
38: * inserted after the current file.
39: */
40:
41: #include "less.h"
42:
43: extern IFILE curr_ifile;
44:
45: struct ifile {
46: struct ifile *h_next; /* Links for command line list */
47: struct ifile *h_prev;
48: char *h_filename; /* Name of the file */
49: void *h_filestate; /* File state (used in ch.c) */
50: int h_index; /* Index within command line list */
51: int h_opened; /* Only need one bit */
52: struct scrpos h_scrpos; /* Saved position within the file */
53: };
54:
55: /*
56: * Convert an IFILE (external representation)
57: * to a struct file (internal representation), and vice versa.
58: */
59: #define int_ifile(h) ((struct ifile *)(h))
60: #define ext_ifile(h) ((IFILE)(h))
61:
62: /*
63: * Anchor for linked list.
64: */
65: static struct ifile anchor = { &anchor, &anchor, 0 };
66: static int ifiles = 0;
67:
68: static void
69: incr_index(p, incr)
1.3 ! mpech 70: struct ifile *p;
1.1 etheisen 71: int incr;
72: {
73: for (; p != &anchor; p = p->h_next)
74: p->h_index += incr;
75: }
76:
77: static void
78: link_ifile(p, prev)
79: struct ifile *p;
80: struct ifile *prev;
81: {
82: /*
83: * Link into list.
84: */
85: if (prev == NULL)
86: prev = &anchor;
87: p->h_next = prev->h_next;
88: p->h_prev = prev;
89: prev->h_next->h_prev = p;
90: prev->h_next = p;
91: /*
92: * Calculate index for the new one,
93: * and adjust the indexes for subsequent ifiles in the list.
94: */
95: p->h_index = prev->h_index + 1;
96: incr_index(p->h_next, 1);
97: ifiles++;
98: }
99:
100: static void
101: unlink_ifile(p)
102: struct ifile *p;
103: {
104: p->h_next->h_prev = p->h_prev;
105: p->h_prev->h_next = p->h_next;
106: incr_index(p->h_next, -1);
107: ifiles--;
108: }
109:
110: /*
111: * Allocate a new ifile structure and stick a filename in it.
112: * It should go after "prev" in the list
113: * (or at the beginning of the list if "prev" is NULL).
114: * Return a pointer to the new ifile structure.
115: */
116: static struct ifile *
117: new_ifile(filename, prev)
118: char *filename;
119: struct ifile *prev;
120: {
1.3 ! mpech 121: struct ifile *p;
1.1 etheisen 122:
123: /*
124: * Allocate and initialize structure.
125: */
126: p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
127: p->h_filename = save(filename);
128: p->h_scrpos.pos = NULL_POSITION;
129: p->h_opened = 0;
130: link_ifile(p, prev);
131: return (p);
132: }
133:
134: /*
135: * Delete an existing ifile structure.
136: */
137: public void
138: del_ifile(h)
139: IFILE h;
140: {
1.3 ! mpech 141: struct ifile *p;
1.1 etheisen 142:
143: if (h == NULL_IFILE)
144: return;
145: /*
146: * If the ifile we're deleting is the currently open ifile,
147: * move off it.
148: */
149: if (h == curr_ifile)
150: curr_ifile = getoff_ifile(curr_ifile);
151: p = int_ifile(h);
152: unlink_ifile(p);
153: free(p->h_filename);
154: free(p);
155: }
156:
157: /*
158: * Get the ifile after a given one in the list.
159: */
160: public IFILE
161: next_ifile(h)
162: IFILE h;
163: {
1.3 ! mpech 164: struct ifile *p;
1.1 etheisen 165:
166: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
167: if (p->h_next == &anchor)
168: return (NULL_IFILE);
169: return (ext_ifile(p->h_next));
170: }
171:
172: /*
173: * Get the ifile before a given one in the list.
174: */
175: public IFILE
176: prev_ifile(h)
177: IFILE h;
178: {
1.3 ! mpech 179: struct ifile *p;
1.1 etheisen 180:
181: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
182: if (p->h_prev == &anchor)
183: return (NULL_IFILE);
184: return (ext_ifile(p->h_prev));
185: }
186:
187: /*
188: * Return a different ifile from the given one.
189: */
190: public IFILE
191: getoff_ifile(ifile)
192: IFILE ifile;
193: {
194: IFILE newifile;
195:
196: if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
197: return (newifile);
198: if ((newifile = next_ifile(ifile)) != NULL_IFILE)
199: return (newifile);
200: return (NULL_IFILE);
201: }
202:
203: /*
204: * Return the number of ifiles.
205: */
206: public int
207: nifile()
208: {
209: return (ifiles);
210: }
211:
212: /*
213: * Find an ifile structure, given a filename.
214: */
215: static struct ifile *
216: find_ifile(filename)
217: char *filename;
218: {
1.3 ! mpech 219: struct ifile *p;
1.1 etheisen 220:
221: for (p = anchor.h_next; p != &anchor; p = p->h_next)
222: if (strcmp(filename, p->h_filename) == 0)
223: return (p);
224: return (NULL);
225: }
226:
227: /*
228: * Get the ifile associated with a filename.
229: * If the filename has not been seen before,
230: * insert the new ifile after "prev" in the list.
231: */
232: public IFILE
233: get_ifile(filename, prev)
234: char *filename;
235: IFILE prev;
236: {
1.3 ! mpech 237: struct ifile *p;
1.1 etheisen 238:
239: if ((p = find_ifile(filename)) == NULL)
240: p = new_ifile(filename, int_ifile(prev));
241: return (ext_ifile(p));
242: }
243:
244: /*
245: * Get the filename associated with a ifile.
246: */
247: public char *
248: get_filename(ifile)
249: IFILE ifile;
250: {
251: if (ifile == NULL)
252: return (NULL);
253: return (int_ifile(ifile)->h_filename);
254: }
255:
256: /*
257: * Get the index of the file associated with a ifile.
258: */
259: public int
260: get_index(ifile)
261: IFILE ifile;
262: {
263: return (int_ifile(ifile)->h_index);
264: }
265:
266: /*
267: * Save the file position to be associated with a given file.
268: */
269: public void
270: store_pos(ifile, scrpos)
271: IFILE ifile;
272: struct scrpos *scrpos;
273: {
274: int_ifile(ifile)->h_scrpos = *scrpos;
275: }
276:
277: /*
278: * Recall the file position associated with a file.
279: * If no position has been associated with the file, return NULL_POSITION.
280: */
281: public void
282: get_pos(ifile, scrpos)
283: IFILE ifile;
284: struct scrpos *scrpos;
285: {
286: *scrpos = int_ifile(ifile)->h_scrpos;
287: }
288:
289: /*
290: * Mark the ifile as "opened".
291: */
292: public void
293: set_open(ifile)
294: IFILE ifile;
295: {
296: int_ifile(ifile)->h_opened = 1;
297: }
298:
299: /*
300: * Return whether the ifile has been opened previously.
301: */
302: public int
303: opened(ifile)
304: IFILE ifile;
305: {
306: return (int_ifile(ifile)->h_opened);
307: }
308:
309: public void *
310: get_filestate(ifile)
311: IFILE ifile;
312: {
313: return (int_ifile(ifile)->h_filestate);
314: }
315:
316: public void
317: set_filestate(ifile, filestate)
318: IFILE ifile;
319: void *filestate;
320: {
321: int_ifile(ifile)->h_filestate = filestate;
322: }
323:
324: #if 0
325: public void
326: if_dump()
327: {
1.3 ! mpech 328: struct ifile *p;
1.1 etheisen 329:
330: for (p = anchor.h_next; p != &anchor; p = p->h_next)
331: {
332: printf("%x: %d. <%s> pos %d,%x\n",
333: p, p->h_index, p->h_filename,
334: p->h_scrpos.ln, p->h_scrpos.pos);
335: ch_dump(p->h_filestate);
336: }
337: }
338: #endif