ifile.c revision 60786
1104476Ssam/* 2139825Simp * Copyright (C) 1984-2000 Mark Nudelman 3104476Ssam * 4247061Spjd * You may distribute under the terms of either the GNU General Public 5247061Spjd * License or the Less License, as specified in the README file. 6247061Spjd * 7104476Ssam * For more information about less, or for information on how to 8104476Ssam * contact the author, see the README file. 9104476Ssam */ 10104476Ssam 11104476Ssam 12104476Ssam/* 13104476Ssam * An IFILE represents an input file. 14104476Ssam * 15104476Ssam * It is actually a pointer to an ifile structure, 16104476Ssam * but is opaque outside this module. 17104476Ssam * Ifile structures are kept in a linked list in the order they 18104476Ssam * appear on the command line. 19247061Spjd * Any new file which does not already appear in the list is 20247061Spjd * inserted after the current file. 21104476Ssam */ 22104476Ssam 23104476Ssam#include "less.h" 24104476Ssam 25104476Ssamextern IFILE curr_ifile; 26247061Spjd 27275732Sjmgstruct ifile { 28275732Sjmg struct ifile *h_next; /* Links for command line list */ 29247061Spjd struct ifile *h_prev; 30275732Sjmg char *h_filename; /* Name of the file */ 31275732Sjmg void *h_filestate; /* File state (used in ch.c) */ 32275732Sjmg int h_index; /* Index within command line list */ 33275732Sjmg int h_hold; /* Hold count */ 34104476Ssam char h_opened; /* Has this ifile been opened? */ 35104476Ssam struct scrpos h_scrpos; /* Saved position within the file */ 36104476Ssam}; 37104476Ssam 38104476Ssam/* 39104476Ssam * Convert an IFILE (external representation) 40104476Ssam * to a struct file (internal representation), and vice versa. 41104476Ssam */ 42104476Ssam#define int_ifile(h) ((struct ifile *)(h)) 43104476Ssam#define ext_ifile(h) ((IFILE)(h)) 44104476Ssam 45104476Ssam/* 46104476Ssam * Anchor for linked list. 47104476Ssam */ 48104476Ssamstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', 49104476Ssam { NULL_POSITION, 0 } }; 50116191Sobrienstatic int ifiles = 0; 51116191Sobrien 52116191Sobrien static void 53143423Sumeincr_index(p, incr) 54292963Sallanjude register struct ifile *p; 55104476Ssam int incr; 56104476Ssam{ 57104476Ssam for (; p != &anchor; p = p->h_next) 58104476Ssam p->h_index += incr; 59104476Ssam} 60104476Ssam 61104476Ssam/* 62104476Ssam * Link an ifile into the ifile list. 63104476Ssam */ 64285336Sgnn static void 65285336Sgnnlink_ifile(p, prev) 66104476Ssam struct ifile *p; 67104476Ssam struct ifile *prev; 68104476Ssam{ 69104476Ssam /* 70275732Sjmg * Link into list. 71104476Ssam */ 72104476Ssam if (prev == NULL) 73104476Ssam prev = &anchor; 74104476Ssam p->h_next = prev->h_next; 75104476Ssam p->h_prev = prev; 76104476Ssam prev->h_next->h_prev = p; 77104476Ssam prev->h_next = p; 78104476Ssam /* 79104476Ssam * Calculate index for the new one, 80104476Ssam * and adjust the indexes for subsequent ifiles in the list. 81104476Ssam */ 82104476Ssam p->h_index = prev->h_index + 1; 83104476Ssam incr_index(p->h_next, 1); 84104476Ssam ifiles++; 85143408Sume} 86104476Ssam 87104476Ssam/* 88104476Ssam * Unlink an ifile from the ifile list. 89104476Ssam */ 90104476Ssam static void 91104476Ssamunlink_ifile(p) 92104476Ssam struct ifile *p; 93104476Ssam{ 94149143Spjd p->h_next->h_prev = p->h_prev; 95149143Spjd p->h_prev->h_next = p->h_next; 96292963Sallanjude incr_index(p->h_next, -1); 97104476Ssam ifiles--; 98104476Ssam} 99143408Sume 100143408Sume/* 101104476Ssam * Allocate a new ifile structure and stick a filename in it. 102104476Ssam * It should go after "prev" in the list 103104476Ssam * (or at the beginning of the list if "prev" is NULL). 104104476Ssam * Return a pointer to the new ifile structure. 105104476Ssam */ 106104476Ssam static struct ifile * 107104476Ssamnew_ifile(filename, prev) 108104476Ssam char *filename; 109104476Ssam struct ifile *prev; 110143408Sume{ 111292963Sallanjude register struct ifile *p; 112104476Ssam 113104476Ssam /* 114 * Allocate and initialize structure. 115 */ 116 p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); 117 p->h_filename = save(filename); 118 p->h_scrpos.pos = NULL_POSITION; 119 p->h_opened = 0; 120 p->h_hold = 0; 121 p->h_filestate = NULL; 122 link_ifile(p, prev); 123 return (p); 124} 125 126/* 127 * Delete an existing ifile structure. 128 */ 129 public void 130del_ifile(h) 131 IFILE h; 132{ 133 register struct ifile *p; 134 135 if (h == NULL_IFILE) 136 return; 137 /* 138 * If the ifile we're deleting is the currently open ifile, 139 * move off it. 140 */ 141 unmark(h); 142 if (h == curr_ifile) 143 curr_ifile = getoff_ifile(curr_ifile); 144 p = int_ifile(h); 145 unlink_ifile(p); 146 free(p->h_filename); 147 free(p); 148} 149 150/* 151 * Get the ifile after a given one in the list. 152 */ 153 public IFILE 154next_ifile(h) 155 IFILE h; 156{ 157 register struct ifile *p; 158 159 p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 160 if (p->h_next == &anchor) 161 return (NULL_IFILE); 162 return (ext_ifile(p->h_next)); 163} 164 165/* 166 * Get the ifile before a given one in the list. 167 */ 168 public IFILE 169prev_ifile(h) 170 IFILE h; 171{ 172 register struct ifile *p; 173 174 p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 175 if (p->h_prev == &anchor) 176 return (NULL_IFILE); 177 return (ext_ifile(p->h_prev)); 178} 179 180/* 181 * Return a different ifile from the given one. 182 */ 183 public IFILE 184getoff_ifile(ifile) 185 IFILE ifile; 186{ 187 IFILE newifile; 188 189 if ((newifile = prev_ifile(ifile)) != NULL_IFILE) 190 return (newifile); 191 if ((newifile = next_ifile(ifile)) != NULL_IFILE) 192 return (newifile); 193 return (NULL_IFILE); 194} 195 196/* 197 * Return the number of ifiles. 198 */ 199 public int 200nifile() 201{ 202 return (ifiles); 203} 204 205/* 206 * Find an ifile structure, given a filename. 207 */ 208 static struct ifile * 209find_ifile(filename) 210 char *filename; 211{ 212 register struct ifile *p; 213 214 for (p = anchor.h_next; p != &anchor; p = p->h_next) 215 if (strcmp(filename, p->h_filename) == 0) 216 return (p); 217 return (NULL); 218} 219 220/* 221 * Get the ifile associated with a filename. 222 * If the filename has not been seen before, 223 * insert the new ifile after "prev" in the list. 224 */ 225 public IFILE 226get_ifile(filename, prev) 227 char *filename; 228 IFILE prev; 229{ 230 register struct ifile *p; 231 232 if ((p = find_ifile(filename)) == NULL) 233 p = new_ifile(filename, int_ifile(prev)); 234 return (ext_ifile(p)); 235} 236 237/* 238 * Get the filename associated with a ifile. 239 */ 240 public char * 241get_filename(ifile) 242 IFILE ifile; 243{ 244 if (ifile == NULL) 245 return (NULL); 246 return (int_ifile(ifile)->h_filename); 247} 248 249/* 250 * Get the index of the file associated with a ifile. 251 */ 252 public int 253get_index(ifile) 254 IFILE ifile; 255{ 256 return (int_ifile(ifile)->h_index); 257} 258 259/* 260 * Save the file position to be associated with a given file. 261 */ 262 public void 263store_pos(ifile, scrpos) 264 IFILE ifile; 265 struct scrpos *scrpos; 266{ 267 int_ifile(ifile)->h_scrpos = *scrpos; 268} 269 270/* 271 * Recall the file position associated with a file. 272 * If no position has been associated with the file, return NULL_POSITION. 273 */ 274 public void 275get_pos(ifile, scrpos) 276 IFILE ifile; 277 struct scrpos *scrpos; 278{ 279 *scrpos = int_ifile(ifile)->h_scrpos; 280} 281 282/* 283 * Mark the ifile as "opened". 284 */ 285 public void 286set_open(ifile) 287 IFILE ifile; 288{ 289 int_ifile(ifile)->h_opened = 1; 290} 291 292/* 293 * Return whether the ifile has been opened previously. 294 */ 295 public int 296opened(ifile) 297 IFILE ifile; 298{ 299 return (int_ifile(ifile)->h_opened); 300} 301 302 public void 303hold_ifile(ifile, incr) 304 IFILE ifile; 305 int incr; 306{ 307 int_ifile(ifile)->h_hold += incr; 308} 309 310 public int 311held_ifile(ifile) 312 IFILE ifile; 313{ 314 return (int_ifile(ifile)->h_hold); 315} 316 317 public void * 318get_filestate(ifile) 319 IFILE ifile; 320{ 321 return (int_ifile(ifile)->h_filestate); 322} 323 324 public void 325set_filestate(ifile, filestate) 326 IFILE ifile; 327 void *filestate; 328{ 329 int_ifile(ifile)->h_filestate = filestate; 330} 331 332#if 0 333 public void 334if_dump() 335{ 336 register struct ifile *p; 337 338 for (p = anchor.h_next; p != &anchor; p = p->h_next) 339 { 340 printf("%x: %d. <%s> pos %d,%x\n", 341 p, p->h_index, p->h_filename, 342 p->h_scrpos.ln, p->h_scrpos.pos); 343 ch_dump(p->h_filestate); 344 } 345} 346#endif 347