ifile.c revision 191930
1219974Smav/* 2219974Smav * Copyright (C) 1984-2008 Mark Nudelman 3219974Smav * 4219974Smav * You may distribute under the terms of either the GNU General Public 5219974Smav * License or the Less License, as specified in the README file. 6219974Smav * 7219974Smav * For more information about less, or for information on how to 8219974Smav * contact the author, see the README file. 9219974Smav */ 10219974Smav 11219974Smav 12219974Smav/* 13219974Smav * An IFILE represents an input file. 14219974Smav * 15219974Smav * It is actually a pointer to an ifile structure, 16219974Smav * but is opaque outside this module. 17219974Smav * Ifile structures are kept in a linked list in the order they 18219974Smav * appear on the command line. 19219974Smav * Any new file which does not already appear in the list is 20219974Smav * inserted after the current file. 21219974Smav */ 22219974Smav 23219974Smav#include "less.h" 24219974Smav 25219974Smavextern IFILE curr_ifile; 26219974Smav 27219974Smavstruct ifile { 28219974Smav struct ifile *h_next; /* Links for command line list */ 29219974Smav struct ifile *h_prev; 30219974Smav char *h_filename; /* Name of the file */ 31219974Smav void *h_filestate; /* File state (used in ch.c) */ 32219974Smav int h_index; /* Index within command line list */ 33219974Smav int h_hold; /* Hold count */ 34219974Smav char h_opened; /* Has this ifile been opened? */ 35219974Smav struct scrpos h_scrpos; /* Saved position within the file */ 36219974Smav}; 37219974Smav 38223921Sae/* 39219974Smav * Convert an IFILE (external representation) 40219974Smav * to a struct file (internal representation), and vice versa. 41219974Smav */ 42219974Smav#define int_ifile(h) ((struct ifile *)(h)) 43219974Smav#define ext_ifile(h) ((IFILE)(h)) 44219974Smav 45219974Smav/* 46219974Smav * Anchor for linked list. 47219974Smav */ 48219974Smavstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', 49219974Smav { NULL_POSITION, 0 } }; 50219974Smavstatic int ifiles = 0; 51219974Smav 52219974Smav static void 53219974Smavincr_index(p, incr) 54219974Smav register struct ifile *p; 55219974Smav int incr; 56219974Smav{ 57219974Smav for (; p != &anchor; p = p->h_next) 58219974Smav p->h_index += incr; 59220790Smav} 60219974Smav 61219974Smav/* 62219974Smav * Link an ifile into the ifile list. 63219974Smav */ 64219974Smav static void 65219974Smavlink_ifile(p, prev) 66219974Smav struct ifile *p; 67219974Smav struct ifile *prev; 68219974Smav{ 69219974Smav /* 70219974Smav * Link into list. 71219974Smav */ 72219974Smav if (prev == NULL) 73219974Smav prev = &anchor; 74219974Smav p->h_next = prev->h_next; 75219974Smav p->h_prev = prev; 76219974Smav prev->h_next->h_prev = p; 77219974Smav prev->h_next = p; 78219974Smav /* 79219974Smav * Calculate index for the new one, 80219974Smav * and adjust the indexes for subsequent ifiles in the list. 81219974Smav */ 82219974Smav p->h_index = prev->h_index + 1; 83219974Smav incr_index(p->h_next, 1); 84219974Smav ifiles++; 85219974Smav} 86219974Smav 87219974Smav/* 88219974Smav * Unlink an ifile from the ifile list. 89219974Smav */ 90219974Smav static void 91219974Smavunlink_ifile(p) 92219974Smav struct ifile *p; 93219974Smav{ 94219974Smav p->h_next->h_prev = p->h_prev; 95219974Smav p->h_prev->h_next = p->h_next; 96219974Smav incr_index(p->h_next, -1); 97219974Smav ifiles--; 98219974Smav} 99219974Smav 100219974Smav/* 101219974Smav * Allocate a new ifile structure and stick a filename in it. 102219974Smav * It should go after "prev" in the list 103219974Smav * (or at the beginning of the list if "prev" is NULL). 104219974Smav * Return a pointer to the new ifile structure. 105219974Smav */ 106219974Smav static struct ifile * 107219974Smavnew_ifile(filename, prev) 108219974Smav char *filename; 109219974Smav struct ifile *prev; 110219974Smav{ 111219974Smav register struct ifile *p; 112219974Smav 113219974Smav /* 114219974Smav * Allocate and initialize structure. 115219974Smav */ 116219974Smav p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); 117219974Smav p->h_filename = save(filename); 118219974Smav p->h_scrpos.pos = NULL_POSITION; 119219974Smav p->h_opened = 0; 120219974Smav p->h_hold = 0; 121219974Smav p->h_filestate = NULL; 122219974Smav link_ifile(p, prev); 123219974Smav return (p); 124219974Smav} 125219974Smav 126219974Smav/* 127219974Smav * Delete an existing ifile structure. 128219974Smav */ 129219974Smav public void 130219974Smavdel_ifile(h) 131219974Smav IFILE h; 132219974Smav{ 133219974Smav register struct ifile *p; 134219974Smav 135219974Smav if (h == NULL_IFILE) 136219974Smav return; 137219974Smav /* 138219974Smav * If the ifile we're deleting is the currently open ifile, 139219974Smav * move off it. 140219974Smav */ 141219974Smav unmark(h); 142219974Smav if (h == curr_ifile) 143219974Smav curr_ifile = getoff_ifile(curr_ifile); 144219974Smav p = int_ifile(h); 145219974Smav unlink_ifile(p); 146219974Smav free(p->h_filename); 147219974Smav free(p); 148219974Smav} 149219974Smav 150219974Smav/* 151219974Smav * Get the ifile after a given one in the list. 152219974Smav */ 153219974Smav public IFILE 154219974Smavnext_ifile(h) 155219974Smav IFILE h; 156219974Smav{ 157219974Smav register struct ifile *p; 158219974Smav 159219974Smav p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 160219974Smav if (p->h_next == &anchor) 161219974Smav return (NULL_IFILE); 162219974Smav return (ext_ifile(p->h_next)); 163219974Smav} 164219974Smav 165219974Smav/* 166219974Smav * Get the ifile before a given one in the list. 167219974Smav */ 168219974Smav public IFILE 169219974Smavprev_ifile(h) 170219974Smav IFILE h; 171219974Smav{ 172219974Smav register struct ifile *p; 173219974Smav 174219974Smav p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 175219974Smav if (p->h_prev == &anchor) 176219974Smav return (NULL_IFILE); 177219974Smav return (ext_ifile(p->h_prev)); 178219974Smav} 179219974Smav 180219974Smav/* 181219974Smav * Return a different ifile from the given one. 182219974Smav */ 183219974Smav public IFILE 184219974Smavgetoff_ifile(ifile) 185219974Smav IFILE ifile; 186219974Smav{ 187219974Smav IFILE newifile; 188219974Smav 189219974Smav if ((newifile = prev_ifile(ifile)) != NULL_IFILE) 190219974Smav return (newifile); 191219974Smav if ((newifile = next_ifile(ifile)) != NULL_IFILE) 192219974Smav return (newifile); 193219974Smav return (NULL_IFILE); 194219974Smav} 195219974Smav 196219974Smav/* 197219974Smav * Return the number of ifiles. 198219974Smav */ 199219974Smav public int 200219974Smavnifile() 201219974Smav{ 202219974Smav return (ifiles); 203219974Smav} 204219974Smav 205219974Smav/* 206219974Smav * Find an ifile structure, given a filename. 207219974Smav */ 208219974Smav static struct ifile * 209219974Smavfind_ifile(filename) 210219974Smav char *filename; 211219974Smav{ 212219974Smav register struct ifile *p; 213219974Smav 214219974Smav for (p = anchor.h_next; p != &anchor; p = p->h_next) 215219974Smav if (strcmp(filename, p->h_filename) == 0) 216219974Smav return (p); 217219974Smav return (NULL); 218219974Smav} 219219974Smav 220219974Smav/* 221239175Smav * Get the ifile associated with a filename. 222239175Smav * If the filename has not been seen before, 223219974Smav * insert the new ifile after "prev" in the list. 224219974Smav */ 225219974Smav public IFILE 226219974Smavget_ifile(filename, prev) 227219974Smav char *filename; 228219974Smav IFILE prev; 229219974Smav{ 230219974Smav register struct ifile *p; 231219974Smav 232219974Smav if ((p = find_ifile(filename)) == NULL) 233219974Smav p = new_ifile(filename, int_ifile(prev)); 234219974Smav return (ext_ifile(p)); 235219974Smav} 236219974Smav 237219974Smav/* 238219974Smav * Get the filename associated with a ifile. 239219974Smav */ 240219974Smav public char * 241219974Smavget_filename(ifile) 242219974Smav IFILE ifile; 243219974Smav{ 244219974Smav if (ifile == NULL) 245219974Smav return (NULL); 246219974Smav return (int_ifile(ifile)->h_filename); 247219974Smav} 248219974Smav 249219974Smav/* 250219974Smav * Get the index of the file associated with a ifile. 251219974Smav */ 252219974Smav public int 253219974Smavget_index(ifile) 254219974Smav IFILE ifile; 255219974Smav{ 256219974Smav return (int_ifile(ifile)->h_index); 257219974Smav} 258219974Smav 259219974Smav/* 260219974Smav * Save the file position to be associated with a given file. 261219974Smav */ 262219974Smav public void 263219974Smavstore_pos(ifile, scrpos) 264219974Smav IFILE ifile; 265219974Smav struct scrpos *scrpos; 266219974Smav{ 267219974Smav int_ifile(ifile)->h_scrpos = *scrpos; 268219974Smav} 269219974Smav 270219974Smav/* 271219974Smav * Recall the file position associated with a file. 272219974Smav * If no position has been associated with the file, return NULL_POSITION. 273219974Smav */ 274219974Smav public void 275219974Smavget_pos(ifile, scrpos) 276219974Smav IFILE ifile; 277219974Smav struct scrpos *scrpos; 278219974Smav{ 279219974Smav *scrpos = int_ifile(ifile)->h_scrpos; 280219974Smav} 281219974Smav 282234603Smav/* 283234603Smav * Mark the ifile as "opened". 284234603Smav */ 285234603Smav public void 286219974Smavset_open(ifile) 287219974Smav IFILE ifile; 288234603Smav{ 289234610Smav int_ifile(ifile)->h_opened = 1; 290234603Smav} 291234610Smav 292219974Smav/* 293219974Smav * Return whether the ifile has been opened previously. 294234458Smav */ 295234603Smav public int 296234458Smavopened(ifile) 297234603Smav IFILE ifile; 298234458Smav{ 299234603Smav return (int_ifile(ifile)->h_opened); 300234458Smav} 301234603Smav 302219974Smav public void 303219974Smavhold_ifile(ifile, incr) 304234603Smav IFILE ifile; 305234603Smav int incr; 306234603Smav{ 307234603Smav int_ifile(ifile)->h_hold += incr; 308234603Smav} 309234603Smav 310234603Smav public int 311234603Smavheld_ifile(ifile) 312219974Smav IFILE ifile; 313234603Smav{ 314234603Smav return (int_ifile(ifile)->h_hold); 315234603Smav} 316234603Smav 317234603Smav public void * 318234603Smavget_filestate(ifile) 319234603Smav IFILE ifile; 320234603Smav{ 321234603Smav return (int_ifile(ifile)->h_filestate); 322234603Smav} 323219974Smav 324234603Smav public void 325234603Smavset_filestate(ifile, filestate) 326234603Smav IFILE ifile; 327234603Smav void *filestate; 328219974Smav{ 329219974Smav int_ifile(ifile)->h_filestate = filestate; 330219974Smav} 331219974Smav 332219974Smav#if 0 333219974Smav public void 334234603Smavif_dump() 335234603Smav{ 336234603Smav register struct ifile *p; 337234603Smav 338234603Smav for (p = anchor.h_next; p != &anchor; p = p->h_next) 339234603Smav { 340234603Smav printf("%x: %d. <%s> pos %d,%x\n", 341234603Smav p, p->h_index, p->h_filename, 342219974Smav p->h_scrpos.ln, p->h_scrpos.pos); 343219974Smav ch_dump(p->h_filestate); 344234603Smav } 345234603Smav} 346234603Smav#endif 347234603Smav