ifile.c revision 294286
1254721Semaste/* 2254721Semaste * Copyright (C) 1984-2015 Mark Nudelman 3353358Sdim * 4353358Sdim * You may distribute under the terms of either the GNU General Public 5353358Sdim * License or the Less License, as specified in the README file. 6254721Semaste * 7254721Semaste * For more information, see the README file. 8254721Semaste */ 9254721Semaste 10254721Semaste 11254721Semaste/* 12254721Semaste * An IFILE represents an input file. 13254721Semaste * 14254721Semaste * It is actually a pointer to an ifile structure, 15254721Semaste * but is opaque outside this module. 16254721Semaste * Ifile structures are kept in a linked list in the order they 17314564Sdim * appear on the command line. 18254721Semaste * Any new file which does not already appear in the list is 19314564Sdim * inserted after the current file. 20254721Semaste */ 21314564Sdim 22314564Sdim#include "less.h" 23314564Sdim 24314564Sdimextern IFILE curr_ifile; 25314564Sdim 26314564Sdimstruct ifile { 27314564Sdim struct ifile *h_next; /* Links for command line list */ 28314564Sdim struct ifile *h_prev; 29254721Semaste char *h_filename; /* Name of the file */ 30254721Semaste void *h_filestate; /* File state (used in ch.c) */ 31314564Sdim int h_index; /* Index within command line list */ 32314564Sdim int h_hold; /* Hold count */ 33254721Semaste char h_opened; /* Has this ifile been opened? */ 34314564Sdim struct scrpos h_scrpos; /* Saved position within the file */ 35314564Sdim}; 36254721Semaste 37314564Sdim/* 38254721Semaste * Convert an IFILE (external representation) 39314564Sdim * to a struct file (internal representation), and vice versa. 40314564Sdim */ 41254721Semaste#define int_ifile(h) ((struct ifile *)(h)) 42314564Sdim#define ext_ifile(h) ((IFILE)(h)) 43314564Sdim 44314564Sdim/* 45344779Sdim * Anchor for linked list. 46254721Semaste */ 47314564Sdimstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', 48254721Semaste { NULL_POSITION, 0 } }; 49314564Sdimstatic int ifiles = 0; 50314564Sdim 51314564Sdim static void 52314564Sdimincr_index(p, incr) 53314564Sdim register struct ifile *p; 54314564Sdim int incr; 55314564Sdim{ 56314564Sdim for (; p != &anchor; p = p->h_next) 57254721Semaste p->h_index += incr; 58254721Semaste} 59254721Semaste 60254721Semaste/* 61296417Sdim * Link an ifile into the ifile list. 62 */ 63 static void 64link_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 86/* 87 * Unlink an ifile from the ifile list. 88 */ 89 static void 90unlink_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 * 106new_ifile(filename, prev) 107 char *filename; 108 struct ifile *prev; 109{ 110 register struct ifile *p; 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; 119 p->h_hold = 0; 120 p->h_filestate = NULL; 121 link_ifile(p, prev); 122 return (p); 123} 124 125/* 126 * Delete an existing ifile structure. 127 */ 128 public void 129del_ifile(h) 130 IFILE h; 131{ 132 register struct ifile *p; 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 */ 140 unmark(h); 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 153next_ifile(h) 154 IFILE h; 155{ 156 register struct ifile *p; 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 168prev_ifile(h) 169 IFILE h; 170{ 171 register struct ifile *p; 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 183getoff_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 199nifile() 200{ 201 return (ifiles); 202} 203 204/* 205 * Find an ifile structure, given a filename. 206 */ 207 static struct ifile * 208find_ifile(filename) 209 char *filename; 210{ 211 register struct ifile *p; 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 225get_ifile(filename, prev) 226 char *filename; 227 IFILE prev; 228{ 229 register struct ifile *p; 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 * 240get_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 252get_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 262store_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 274get_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 285set_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 295opened(ifile) 296 IFILE ifile; 297{ 298 return (int_ifile(ifile)->h_opened); 299} 300 301 public void 302hold_ifile(ifile, incr) 303 IFILE ifile; 304 int incr; 305{ 306 int_ifile(ifile)->h_hold += incr; 307} 308 309 public int 310held_ifile(ifile) 311 IFILE ifile; 312{ 313 return (int_ifile(ifile)->h_hold); 314} 315 316 public void * 317get_filestate(ifile) 318 IFILE ifile; 319{ 320 return (int_ifile(ifile)->h_filestate); 321} 322 323 public void 324set_filestate(ifile, filestate) 325 IFILE ifile; 326 void *filestate; 327{ 328 int_ifile(ifile)->h_filestate = filestate; 329} 330 331#if 0 332 public void 333if_dump() 334{ 335 register struct ifile *p; 336 337 for (p = anchor.h_next; p != &anchor; p = p->h_next) 338 { 339 printf("%x: %d. <%s> pos %d,%x\n", 340 p, p->h_index, p->h_filename, 341 p->h_scrpos.ln, p->h_scrpos.pos); 342 ch_dump(p->h_filestate); 343 } 344} 345#endif 346