1238730Sdelphij/* 2330571Sdelphij * Copyright (C) 1984-2017 Mark Nudelman 3238730Sdelphij * 4238730Sdelphij * You may distribute under the terms of either the GNU General Public 5238730Sdelphij * License or the Less License, as specified in the README file. 6238730Sdelphij * 7238730Sdelphij * For more information, see the README file. 8238730Sdelphij */ 960786Sps 1060786Sps 1160786Sps/* 1260786Sps * An IFILE represents an input file. 1360786Sps * 1460786Sps * It is actually a pointer to an ifile structure, 1560786Sps * but is opaque outside this module. 1660786Sps * Ifile structures are kept in a linked list in the order they 1760786Sps * appear on the command line. 1860786Sps * Any new file which does not already appear in the list is 1960786Sps * inserted after the current file. 2060786Sps */ 2160786Sps 2260786Sps#include "less.h" 2360786Sps 2460786Spsextern IFILE curr_ifile; 2560786Sps 2660786Spsstruct ifile { 27330571Sdelphij struct ifile *h_next; /* Links for command line list */ 2860786Sps struct ifile *h_prev; 29330571Sdelphij char *h_filename; /* Name of the file */ 30330571Sdelphij void *h_filestate; /* File state (used in ch.c) */ 31330571Sdelphij int h_index; /* Index within command line list */ 32330571Sdelphij int h_hold; /* Hold count */ 33330571Sdelphij char h_opened; /* Has this ifile been opened? */ 34330571Sdelphij struct scrpos h_scrpos; /* Saved position within the file */ 35330571Sdelphij void *h_altpipe; /* Alt pipe */ 36330571Sdelphij char *h_altfilename; /* Alt filename */ 3760786Sps}; 3860786Sps 3960786Sps/* 4060786Sps * Convert an IFILE (external representation) 4160786Sps * to a struct file (internal representation), and vice versa. 4260786Sps */ 4360786Sps#define int_ifile(h) ((struct ifile *)(h)) 4460786Sps#define ext_ifile(h) ((IFILE)(h)) 4560786Sps 4660786Sps/* 4760786Sps * Anchor for linked list. 4860786Sps */ 4960786Spsstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', 5060786Sps { NULL_POSITION, 0 } }; 5160786Spsstatic int ifiles = 0; 5260786Sps 5360786Sps static void 5460786Spsincr_index(p, incr) 55330571Sdelphij struct ifile *p; 5660786Sps int incr; 5760786Sps{ 5860786Sps for (; p != &anchor; p = p->h_next) 5960786Sps p->h_index += incr; 6060786Sps} 6160786Sps 6260786Sps/* 6360786Sps * Link an ifile into the ifile list. 6460786Sps */ 6560786Sps static void 6660786Spslink_ifile(p, prev) 6760786Sps struct ifile *p; 6860786Sps struct ifile *prev; 6960786Sps{ 7060786Sps /* 7160786Sps * Link into list. 7260786Sps */ 7360786Sps if (prev == NULL) 7460786Sps prev = &anchor; 7560786Sps p->h_next = prev->h_next; 7660786Sps p->h_prev = prev; 7760786Sps prev->h_next->h_prev = p; 7860786Sps prev->h_next = p; 7960786Sps /* 8060786Sps * Calculate index for the new one, 8160786Sps * and adjust the indexes for subsequent ifiles in the list. 8260786Sps */ 8360786Sps p->h_index = prev->h_index + 1; 8460786Sps incr_index(p->h_next, 1); 8560786Sps ifiles++; 8660786Sps} 8760786Sps 8860786Sps/* 8960786Sps * Unlink an ifile from the ifile list. 9060786Sps */ 9160786Sps static void 9260786Spsunlink_ifile(p) 9360786Sps struct ifile *p; 9460786Sps{ 9560786Sps p->h_next->h_prev = p->h_prev; 9660786Sps p->h_prev->h_next = p->h_next; 9760786Sps incr_index(p->h_next, -1); 9860786Sps ifiles--; 9960786Sps} 10060786Sps 10160786Sps/* 10260786Sps * Allocate a new ifile structure and stick a filename in it. 10360786Sps * It should go after "prev" in the list 10460786Sps * (or at the beginning of the list if "prev" is NULL). 10560786Sps * Return a pointer to the new ifile structure. 10660786Sps */ 10760786Sps static struct ifile * 10860786Spsnew_ifile(filename, prev) 10960786Sps char *filename; 11060786Sps struct ifile *prev; 11160786Sps{ 112330571Sdelphij struct ifile *p; 11360786Sps 11460786Sps /* 11560786Sps * Allocate and initialize structure. 11660786Sps */ 11760786Sps p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); 11860786Sps p->h_filename = save(filename); 11960786Sps p->h_scrpos.pos = NULL_POSITION; 12060786Sps p->h_opened = 0; 12160786Sps p->h_hold = 0; 12260786Sps p->h_filestate = NULL; 12360786Sps link_ifile(p, prev); 12460786Sps return (p); 12560786Sps} 12660786Sps 12760786Sps/* 12860786Sps * Delete an existing ifile structure. 12960786Sps */ 13060786Sps public void 13160786Spsdel_ifile(h) 13260786Sps IFILE h; 13360786Sps{ 134330571Sdelphij struct ifile *p; 13560786Sps 13660786Sps if (h == NULL_IFILE) 13760786Sps return; 13860786Sps /* 13960786Sps * If the ifile we're deleting is the currently open ifile, 14060786Sps * move off it. 14160786Sps */ 14260786Sps unmark(h); 14360786Sps if (h == curr_ifile) 14460786Sps curr_ifile = getoff_ifile(curr_ifile); 14560786Sps p = int_ifile(h); 14660786Sps unlink_ifile(p); 14760786Sps free(p->h_filename); 14860786Sps free(p); 14960786Sps} 15060786Sps 15160786Sps/* 15260786Sps * Get the ifile after a given one in the list. 15360786Sps */ 15460786Sps public IFILE 15560786Spsnext_ifile(h) 15660786Sps IFILE h; 15760786Sps{ 158330571Sdelphij struct ifile *p; 15960786Sps 16060786Sps p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 16160786Sps if (p->h_next == &anchor) 16260786Sps return (NULL_IFILE); 16360786Sps return (ext_ifile(p->h_next)); 16460786Sps} 16560786Sps 16660786Sps/* 16760786Sps * Get the ifile before a given one in the list. 16860786Sps */ 16960786Sps public IFILE 17060786Spsprev_ifile(h) 17160786Sps IFILE h; 17260786Sps{ 173330571Sdelphij struct ifile *p; 17460786Sps 17560786Sps p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 17660786Sps if (p->h_prev == &anchor) 17760786Sps return (NULL_IFILE); 17860786Sps return (ext_ifile(p->h_prev)); 17960786Sps} 18060786Sps 18160786Sps/* 18260786Sps * Return a different ifile from the given one. 18360786Sps */ 18460786Sps public IFILE 18560786Spsgetoff_ifile(ifile) 18660786Sps IFILE ifile; 18760786Sps{ 18860786Sps IFILE newifile; 18960786Sps 19060786Sps if ((newifile = prev_ifile(ifile)) != NULL_IFILE) 19160786Sps return (newifile); 19260786Sps if ((newifile = next_ifile(ifile)) != NULL_IFILE) 19360786Sps return (newifile); 19460786Sps return (NULL_IFILE); 19560786Sps} 19660786Sps 19760786Sps/* 19860786Sps * Return the number of ifiles. 19960786Sps */ 20060786Sps public int 20160786Spsnifile() 20260786Sps{ 20360786Sps return (ifiles); 20460786Sps} 20560786Sps 20660786Sps/* 20760786Sps * Find an ifile structure, given a filename. 20860786Sps */ 20960786Sps static struct ifile * 21060786Spsfind_ifile(filename) 21160786Sps char *filename; 21260786Sps{ 213330571Sdelphij struct ifile *p; 21460786Sps 21560786Sps for (p = anchor.h_next; p != &anchor; p = p->h_next) 21660786Sps if (strcmp(filename, p->h_filename) == 0) 21760786Sps return (p); 21860786Sps return (NULL); 21960786Sps} 22060786Sps 22160786Sps/* 22260786Sps * Get the ifile associated with a filename. 22360786Sps * If the filename has not been seen before, 22460786Sps * insert the new ifile after "prev" in the list. 22560786Sps */ 22660786Sps public IFILE 22760786Spsget_ifile(filename, prev) 22860786Sps char *filename; 22960786Sps IFILE prev; 23060786Sps{ 231330571Sdelphij struct ifile *p; 23260786Sps 23360786Sps if ((p = find_ifile(filename)) == NULL) 23460786Sps p = new_ifile(filename, int_ifile(prev)); 23560786Sps return (ext_ifile(p)); 23660786Sps} 23760786Sps 23860786Sps/* 23960786Sps * Get the filename associated with a ifile. 24060786Sps */ 24160786Sps public char * 24260786Spsget_filename(ifile) 24360786Sps IFILE ifile; 24460786Sps{ 24560786Sps if (ifile == NULL) 24660786Sps return (NULL); 24760786Sps return (int_ifile(ifile)->h_filename); 24860786Sps} 24960786Sps 25060786Sps/* 25160786Sps * Get the index of the file associated with a ifile. 25260786Sps */ 25360786Sps public int 25460786Spsget_index(ifile) 25560786Sps IFILE ifile; 25660786Sps{ 25760786Sps return (int_ifile(ifile)->h_index); 25860786Sps} 25960786Sps 26060786Sps/* 26160786Sps * Save the file position to be associated with a given file. 26260786Sps */ 26360786Sps public void 26460786Spsstore_pos(ifile, scrpos) 26560786Sps IFILE ifile; 26660786Sps struct scrpos *scrpos; 26760786Sps{ 26860786Sps int_ifile(ifile)->h_scrpos = *scrpos; 26960786Sps} 27060786Sps 27160786Sps/* 27260786Sps * Recall the file position associated with a file. 27360786Sps * If no position has been associated with the file, return NULL_POSITION. 27460786Sps */ 27560786Sps public void 27660786Spsget_pos(ifile, scrpos) 27760786Sps IFILE ifile; 27860786Sps struct scrpos *scrpos; 27960786Sps{ 28060786Sps *scrpos = int_ifile(ifile)->h_scrpos; 28160786Sps} 28260786Sps 28360786Sps/* 28460786Sps * Mark the ifile as "opened". 28560786Sps */ 28660786Sps public void 28760786Spsset_open(ifile) 28860786Sps IFILE ifile; 28960786Sps{ 29060786Sps int_ifile(ifile)->h_opened = 1; 29160786Sps} 29260786Sps 29360786Sps/* 29460786Sps * Return whether the ifile has been opened previously. 29560786Sps */ 29660786Sps public int 29760786Spsopened(ifile) 29860786Sps IFILE ifile; 29960786Sps{ 30060786Sps return (int_ifile(ifile)->h_opened); 30160786Sps} 30260786Sps 30360786Sps public void 30460786Spshold_ifile(ifile, incr) 30560786Sps IFILE ifile; 30660786Sps int incr; 30760786Sps{ 30860786Sps int_ifile(ifile)->h_hold += incr; 30960786Sps} 31060786Sps 31160786Sps public int 31260786Spsheld_ifile(ifile) 31360786Sps IFILE ifile; 31460786Sps{ 31560786Sps return (int_ifile(ifile)->h_hold); 31660786Sps} 31760786Sps 31860786Sps public void * 31960786Spsget_filestate(ifile) 32060786Sps IFILE ifile; 32160786Sps{ 32260786Sps return (int_ifile(ifile)->h_filestate); 32360786Sps} 32460786Sps 32560786Sps public void 32660786Spsset_filestate(ifile, filestate) 32760786Sps IFILE ifile; 32860786Sps void *filestate; 32960786Sps{ 33060786Sps int_ifile(ifile)->h_filestate = filestate; 33160786Sps} 33260786Sps 333330571Sdelphij public void 334330571Sdelphijset_altpipe(ifile, p) 335330571Sdelphij IFILE ifile; 336330571Sdelphij void *p; 337330571Sdelphij{ 338330571Sdelphij int_ifile(ifile)->h_altpipe = p; 339330571Sdelphij} 340330571Sdelphij 341330571Sdelphij public void * 342330571Sdelphijget_altpipe(ifile) 343330571Sdelphij IFILE ifile; 344330571Sdelphij{ 345330571Sdelphij return (int_ifile(ifile)->h_altpipe); 346330571Sdelphij} 347330571Sdelphij 348330571Sdelphij public void 349330571Sdelphijset_altfilename(ifile, altfilename) 350330571Sdelphij IFILE ifile; 351330571Sdelphij char *altfilename; 352330571Sdelphij{ 353330571Sdelphij struct ifile *p = int_ifile(ifile); 354330571Sdelphij if (p->h_altfilename != NULL) 355330571Sdelphij free(p->h_altfilename); 356330571Sdelphij p->h_altfilename = altfilename; 357330571Sdelphij} 358330571Sdelphij 359330571Sdelphij public char * 360330571Sdelphijget_altfilename(ifile) 361330571Sdelphij IFILE ifile; 362330571Sdelphij{ 363330571Sdelphij return (int_ifile(ifile)->h_altfilename); 364330571Sdelphij} 365330571Sdelphij 36660786Sps#if 0 36760786Sps public void 36860786Spsif_dump() 36960786Sps{ 370330571Sdelphij struct ifile *p; 37160786Sps 37260786Sps for (p = anchor.h_next; p != &anchor; p = p->h_next) 37360786Sps { 37460786Sps printf("%x: %d. <%s> pos %d,%x\n", 37560786Sps p, p->h_index, p->h_filename, 37660786Sps p->h_scrpos.ln, p->h_scrpos.pos); 37760786Sps ch_dump(p->h_filestate); 37860786Sps } 37960786Sps} 38060786Sps#endif 381