Annotation of src/usr.bin/less/ifile.c, Revision 1.7
1.1 etheisen 1: /*
1.7 ! shadchin 2: * Copyright (C) 1984-2012 Mark Nudelman
1.1 etheisen 3: *
1.4 millert 4: * You may distribute under the terms of either the GNU General Public
5: * License or the Less License, as specified in the README file.
1.1 etheisen 6: *
1.7 ! shadchin 7: * For more information, see the README file.
1.1 etheisen 8: */
9:
10:
11: /*
12: * An IFILE represents an input file.
13: *
14: * It is actually a pointer to an ifile structure,
15: * but is opaque outside this module.
16: * Ifile structures are kept in a linked list in the order they
17: * appear on the command line.
18: * Any new file which does not already appear in the list is
19: * inserted after the current file.
20: */
21:
22: #include "less.h"
23:
24: extern IFILE curr_ifile;
25:
26: struct ifile {
27: struct ifile *h_next; /* Links for command line list */
28: struct ifile *h_prev;
29: char *h_filename; /* Name of the file */
30: void *h_filestate; /* File state (used in ch.c) */
31: int h_index; /* Index within command line list */
1.4 millert 32: int h_hold; /* Hold count */
33: char h_opened; /* Has this ifile been opened? */
1.1 etheisen 34: struct scrpos h_scrpos; /* Saved position within the file */
35: };
36:
37: /*
38: * Convert an IFILE (external representation)
39: * to a struct file (internal representation), and vice versa.
40: */
41: #define int_ifile(h) ((struct ifile *)(h))
42: #define ext_ifile(h) ((IFILE)(h))
43:
44: /*
45: * Anchor for linked list.
46: */
1.4 millert 47: static struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0',
48: { NULL_POSITION, 0 } };
1.1 etheisen 49: static int ifiles = 0;
50:
51: static void
52: incr_index(p, incr)
1.4 millert 53: register struct ifile *p;
1.1 etheisen 54: int incr;
55: {
56: for (; p != &anchor; p = p->h_next)
57: p->h_index += incr;
58: }
59:
1.4 millert 60: /*
61: * Link an ifile into the ifile list.
62: */
1.1 etheisen 63: static void
64: link_ifile(p, prev)
65: struct ifile *p;
66: struct ifile *prev;
67: {
68: /*
69: * Link into list.
70: */
71: if (prev == NULL)
72: prev = &anchor;
73: p->h_next = prev->h_next;
74: p->h_prev = prev;
75: prev->h_next->h_prev = p;
76: prev->h_next = p;
77: /*
78: * Calculate index for the new one,
79: * and adjust the indexes for subsequent ifiles in the list.
80: */
81: p->h_index = prev->h_index + 1;
82: incr_index(p->h_next, 1);
83: ifiles++;
84: }
85:
1.4 millert 86: /*
87: * Unlink an ifile from the ifile list.
88: */
1.1 etheisen 89: static void
90: unlink_ifile(p)
91: struct ifile *p;
92: {
93: p->h_next->h_prev = p->h_prev;
94: p->h_prev->h_next = p->h_next;
95: incr_index(p->h_next, -1);
96: ifiles--;
97: }
98:
99: /*
100: * Allocate a new ifile structure and stick a filename in it.
101: * It should go after "prev" in the list
102: * (or at the beginning of the list if "prev" is NULL).
103: * Return a pointer to the new ifile structure.
104: */
105: static struct ifile *
106: new_ifile(filename, prev)
107: char *filename;
108: struct ifile *prev;
109: {
1.4 millert 110: register struct ifile *p;
1.1 etheisen 111:
112: /*
113: * Allocate and initialize structure.
114: */
115: p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
116: p->h_filename = save(filename);
117: p->h_scrpos.pos = NULL_POSITION;
118: p->h_opened = 0;
1.4 millert 119: p->h_hold = 0;
120: p->h_filestate = NULL;
1.1 etheisen 121: link_ifile(p, prev);
122: return (p);
123: }
124:
125: /*
126: * Delete an existing ifile structure.
127: */
128: public void
129: del_ifile(h)
130: IFILE h;
131: {
1.4 millert 132: register struct ifile *p;
1.1 etheisen 133:
134: if (h == NULL_IFILE)
135: return;
136: /*
137: * If the ifile we're deleting is the currently open ifile,
138: * move off it.
139: */
1.4 millert 140: unmark(h);
1.1 etheisen 141: if (h == curr_ifile)
142: curr_ifile = getoff_ifile(curr_ifile);
143: p = int_ifile(h);
144: unlink_ifile(p);
145: free(p->h_filename);
146: free(p);
147: }
148:
149: /*
150: * Get the ifile after a given one in the list.
151: */
152: public IFILE
153: next_ifile(h)
154: IFILE h;
155: {
1.4 millert 156: register struct ifile *p;
1.1 etheisen 157:
158: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
159: if (p->h_next == &anchor)
160: return (NULL_IFILE);
161: return (ext_ifile(p->h_next));
162: }
163:
164: /*
165: * Get the ifile before a given one in the list.
166: */
167: public IFILE
168: prev_ifile(h)
169: IFILE h;
170: {
1.4 millert 171: register struct ifile *p;
1.1 etheisen 172:
173: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
174: if (p->h_prev == &anchor)
175: return (NULL_IFILE);
176: return (ext_ifile(p->h_prev));
177: }
178:
179: /*
180: * Return a different ifile from the given one.
181: */
182: public IFILE
183: getoff_ifile(ifile)
184: IFILE ifile;
185: {
186: IFILE newifile;
187:
188: if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
189: return (newifile);
190: if ((newifile = next_ifile(ifile)) != NULL_IFILE)
191: return (newifile);
192: return (NULL_IFILE);
193: }
194:
195: /*
196: * Return the number of ifiles.
197: */
198: public int
199: nifile()
200: {
201: return (ifiles);
202: }
203:
204: /*
205: * Find an ifile structure, given a filename.
206: */
207: static struct ifile *
208: find_ifile(filename)
209: char *filename;
210: {
1.4 millert 211: register struct ifile *p;
1.1 etheisen 212:
213: for (p = anchor.h_next; p != &anchor; p = p->h_next)
214: if (strcmp(filename, p->h_filename) == 0)
215: return (p);
216: return (NULL);
217: }
218:
219: /*
220: * Get the ifile associated with a filename.
221: * If the filename has not been seen before,
222: * insert the new ifile after "prev" in the list.
223: */
224: public IFILE
225: get_ifile(filename, prev)
226: char *filename;
227: IFILE prev;
228: {
1.4 millert 229: register struct ifile *p;
1.1 etheisen 230:
231: if ((p = find_ifile(filename)) == NULL)
232: p = new_ifile(filename, int_ifile(prev));
233: return (ext_ifile(p));
234: }
235:
236: /*
237: * Get the filename associated with a ifile.
238: */
239: public char *
240: get_filename(ifile)
241: IFILE ifile;
242: {
243: if (ifile == NULL)
244: return (NULL);
245: return (int_ifile(ifile)->h_filename);
246: }
247:
248: /*
249: * Get the index of the file associated with a ifile.
250: */
251: public int
252: get_index(ifile)
253: IFILE ifile;
254: {
255: return (int_ifile(ifile)->h_index);
256: }
257:
258: /*
259: * Save the file position to be associated with a given file.
260: */
261: public void
262: store_pos(ifile, scrpos)
263: IFILE ifile;
264: struct scrpos *scrpos;
265: {
266: int_ifile(ifile)->h_scrpos = *scrpos;
267: }
268:
269: /*
270: * Recall the file position associated with a file.
271: * If no position has been associated with the file, return NULL_POSITION.
272: */
273: public void
274: get_pos(ifile, scrpos)
275: IFILE ifile;
276: struct scrpos *scrpos;
277: {
278: *scrpos = int_ifile(ifile)->h_scrpos;
279: }
280:
281: /*
282: * Mark the ifile as "opened".
283: */
284: public void
285: set_open(ifile)
286: IFILE ifile;
287: {
288: int_ifile(ifile)->h_opened = 1;
289: }
290:
291: /*
292: * Return whether the ifile has been opened previously.
293: */
294: public int
295: opened(ifile)
296: IFILE ifile;
297: {
298: return (int_ifile(ifile)->h_opened);
299: }
300:
1.4 millert 301: public void
302: hold_ifile(ifile, incr)
303: IFILE ifile;
304: int incr;
305: {
306: int_ifile(ifile)->h_hold += incr;
307: }
308:
1.6 shadchin 309: #if !SMALL
1.4 millert 310: public int
311: held_ifile(ifile)
312: IFILE ifile;
313: {
314: return (int_ifile(ifile)->h_hold);
315: }
1.6 shadchin 316: #endif /* !SMALL */
1.4 millert 317:
1.1 etheisen 318: public void *
319: get_filestate(ifile)
320: IFILE ifile;
321: {
322: return (int_ifile(ifile)->h_filestate);
323: }
324:
325: public void
326: set_filestate(ifile, filestate)
327: IFILE ifile;
328: void *filestate;
329: {
330: int_ifile(ifile)->h_filestate = filestate;
331: }
332:
333: #if 0
334: public void
335: if_dump()
336: {
1.4 millert 337: register struct ifile *p;
1.1 etheisen 338:
339: for (p = anchor.h_next; p != &anchor; p = p->h_next)
340: {
341: printf("%x: %d. <%s> pos %d,%x\n",
342: p, p->h_index, p->h_filename,
343: p->h_scrpos.ln, p->h_scrpos.pos);
344: ch_dump(p->h_filestate);
345: }
346: }
347: #endif