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