Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / miscellany / less-177 / ifile.c
1 /*
2  * An IFILE represents an input file.
3  *
4  * It is actually a pointer to an ifile structure,
5  * but is opaque outside this module.
6  * Ifile structures are kept in a linked list in the order they 
7  * appear on the command line.
8  * Any new file which does not already appear in the list is
9  * inserted after the current file.
10  */
11
12 #include "less.h"
13
14 struct ifile {
15         struct ifile *h_next;           /* Links for command line list */
16         struct ifile *h_prev;
17         int h_index;                    /* Index within command line list */
18         char *h_filename;               /* Name of the file */
19         struct scrpos h_scrpos;         /* Saved position within the file */
20 };
21
22 /*
23  * Convert an IFILE (external representation)
24  * to a struct file (internal representation), and vice versa.
25  */
26 #define int_ifile(h)    ((struct ifile *)(h))
27 #define ext_ifile(h)    ((IFILE)(h))
28
29 /*
30  * Anchor for linked list.
31  */
32 static struct ifile anchor = { &anchor, &anchor, 0 };
33 static int ifiles = 0;
34
35 /*
36  * Allocate a new ifile structure and stick a filename in it.
37  * It should go after "prev" in the list
38  * (or at the beginning of the list if "prev" is NULL).
39  * Return a pointer to the new ifile structure.
40  */
41         static struct ifile *
42 new_ifile(filename, prev)
43         char *filename;
44         struct ifile *prev;
45 {
46         register struct ifile *p;
47         register struct ifile *np;
48
49         /*
50          * Allocate and initialize structure.
51          */
52         p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
53         p->h_filename = filename;
54         p->h_scrpos.pos = NULL_POSITION;
55
56         /*
57          * Link into list.
58          */
59         if (prev == NULL)
60                 prev = &anchor;
61         p->h_next = prev->h_next;
62         p->h_prev = prev;
63         prev->h_next->h_prev = p;
64         prev->h_next = p;
65
66         /*
67          * Calculate index for the new one,
68          * and adjust the indexes for subsequent ifiles in the list.
69          */
70         p->h_index = prev->h_index + 1;
71         for (np = p->h_next;  np != &anchor;  np = np->h_next)
72                 np->h_index++;
73
74         ifiles++;
75         return (p);
76 }
77
78 /*
79  * Get the ifile after a given one in the list.
80  */
81         public IFILE
82 next_ifile(h)
83         IFILE h;
84 {
85         register struct ifile *p;
86
87         p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
88         if (p->h_next == &anchor)
89                 return (NULL_IFILE);
90         return (ext_ifile(p->h_next));
91 }
92
93 /*
94  * Get the ifile before a given one in the list.
95  */
96         public IFILE
97 prev_ifile(h)
98         IFILE h;
99 {
100         register struct ifile *p;
101
102         p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
103         if (p->h_prev == &anchor)
104                 return (NULL_IFILE);
105         return (ext_ifile(p->h_prev));
106 }
107
108 /*
109  * Return the number of ifiles.
110  */
111         public int
112 nifile()
113 {
114         return (ifiles);
115 }
116
117 /*
118  * Find an ifile structure, given a filename.
119  */
120         static struct ifile *
121 find_ifile(filename)
122         char *filename;
123 {
124         register struct ifile *p;
125
126         for (p = anchor.h_next;  p != &anchor;  p = p->h_next)
127                 if (strcmp(filename, p->h_filename) == 0)
128                         return (p);
129         return (NULL);
130 }
131
132 /*
133  * Get the ifile associated with a filename.
134  * If the filename has not been seen before,
135  * insert the new ifile after "prev" in the list.
136  */
137         public IFILE
138 get_ifile(filename, prev)
139         char *filename;
140         IFILE prev;
141 {
142         register struct ifile *p;
143
144         if ((p = find_ifile(filename)) == NULL)
145                 p = new_ifile(save(filename), int_ifile(prev));
146         return (ext_ifile(p));
147 }
148
149 /*
150  * Get the filename associated with a ifile.
151  */
152         public char *
153 get_filename(ifile)
154         IFILE ifile;
155 {
156         if (ifile == NULL)
157                 return (NULL);
158         return (int_ifile(ifile)->h_filename);
159 }
160
161 /*
162  * Get the index of the file associated with a ifile.
163  */
164         public int
165 get_index(ifile)
166         IFILE ifile;
167 {
168         return (int_ifile(ifile)->h_index); 
169 }
170
171 /*
172  * Save the file position to be associated with a given file.
173  */
174         public void
175 store_pos(ifile, scrpos)
176         IFILE ifile;
177         struct scrpos *scrpos;
178 {
179         int_ifile(ifile)->h_scrpos = *scrpos;
180 }
181
182 /*
183  * Recall the file position associated with a file.
184  * If no position has been associated with the file, return NULL_POSITION.
185  */
186         public void
187 get_pos(ifile, scrpos)
188         IFILE ifile;
189         struct scrpos *scrpos;
190 {
191         *scrpos = int_ifile(ifile)->h_scrpos;
192 }