ifile.c revision 294286
155714Skris/* 255714Skris * Copyright (C) 1984-2015 Mark Nudelman 355714Skris * 455714Skris * You may distribute under the terms of either the GNU General Public 555714Skris * License or the Less License, as specified in the README file. 655714Skris * 755714Skris * For more information, see the README file. 855714Skris */ 955714Skris 1055714Skris 1155714Skris/* 1255714Skris * An IFILE represents an input file. 1355714Skris * 1455714Skris * It is actually a pointer to an ifile structure, 1555714Skris * but is opaque outside this module. 1655714Skris * Ifile structures are kept in a linked list in the order they 1755714Skris * appear on the command line. 1855714Skris * Any new file which does not already appear in the list is 1955714Skris * inserted after the current file. 2055714Skris */ 2155714Skris 2255714Skris#include "less.h" 2355714Skris 2455714Skrisextern IFILE curr_ifile; 2555714Skris 2655714Skrisstruct ifile { 2755714Skris struct ifile *h_next; /* Links for command line list */ 2855714Skris struct ifile *h_prev; 2955714Skris char *h_filename; /* Name of the file */ 3055714Skris void *h_filestate; /* File state (used in ch.c) */ 3155714Skris int h_index; /* Index within command line list */ 3255714Skris int h_hold; /* Hold count */ 3355714Skris char h_opened; /* Has this ifile been opened? */ 3455714Skris struct scrpos h_scrpos; /* Saved position within the file */ 3555714Skris}; 3655714Skris 3755714Skris/* 3855714Skris * Convert an IFILE (external representation) 3955714Skris * to a struct file (internal representation), and vice versa. 4055714Skris */ 4155714Skris#define int_ifile(h) ((struct ifile *)(h)) 4255714Skris#define ext_ifile(h) ((IFILE)(h)) 4355714Skris 4455714Skris/* 4555714Skris * Anchor for linked list. 4655714Skris */ 4755714Skrisstatic struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0', 4855714Skris { NULL_POSITION, 0 } }; 4955714Skrisstatic int ifiles = 0; 5055714Skris 5155714Skris static void 5255714Skrisincr_index(p, incr) 5355714Skris register struct ifile *p; 5455714Skris int incr; 5555714Skris{ 5655714Skris for (; p != &anchor; p = p->h_next) 5755714Skris p->h_index += incr; 5855714Skris} 5955714Skris 6055714Skris/* 6155714Skris * Link an ifile into the ifile list. 6268654Skris */ 6368654Skris static void 6468654Skrislink_ifile(p, prev) 6568654Skris struct ifile *p; 6668654Skris struct ifile *prev; 6768654Skris{ 6855714Skris /* 6955714Skris * Link into list. 70110007Smarkm */ 71110007Smarkm if (prev == NULL) 72110007Smarkm prev = &anchor; 73110007Smarkm p->h_next = prev->h_next; 74110007Smarkm p->h_prev = prev; 7568654Skris prev->h_next->h_prev = p; 7668654Skris prev->h_next = p; 7755714Skris /* 78110007Smarkm * Calculate index for the new one, 7955714Skris * and adjust the indexes for subsequent ifiles in the list. 8055714Skris */ 8155714Skris p->h_index = prev->h_index + 1; 8255714Skris incr_index(p->h_next, 1); 8355714Skris ifiles++; 84110007Smarkm} 85160817Ssimon 86238405Sjkim/* 87110007Smarkm * Unlink an ifile from the ifile list. 88110007Smarkm */ 8955714Skris static void 9055714Skrisunlink_ifile(p) 9155714Skris struct ifile *p; 9255714Skris{ 9355714Skris p->h_next->h_prev = p->h_prev; 9455714Skris p->h_prev->h_next = p->h_next; 9555714Skris incr_index(p->h_next, -1); 9655714Skris ifiles--; 9755714Skris} 9855714Skris 99160817Ssimon/* 10055714Skris * Allocate a new ifile structure and stick a filename in it. 10155714Skris * It should go after "prev" in the list 10255714Skris * (or at the beginning of the list if "prev" is NULL). 10355714Skris * Return a pointer to the new ifile structure. 10455714Skris */ 105160817Ssimon static struct ifile * 10655714Skrisnew_ifile(filename, prev) 10755714Skris char *filename; 10855714Skris struct ifile *prev; 10955714Skris{ 11055714Skris register struct ifile *p; 11155714Skris 11255714Skris /* 11355714Skris * Allocate and initialize structure. 11455714Skris */ 11555714Skris p = (struct ifile *) ecalloc(1, sizeof(struct ifile)); 11655714Skris p->h_filename = save(filename); 117160817Ssimon p->h_scrpos.pos = NULL_POSITION; 118238405Sjkim p->h_opened = 0; 119238405Sjkim p->h_hold = 0; 12055714Skris p->h_filestate = NULL; 12168654Skris link_ifile(p, prev); 12268654Skris return (p); 12368654Skris} 12468654Skris 12555714Skris/* 12655714Skris * Delete an existing ifile structure. 12759194Skris */ 128110007Smarkm public void 12955714Skrisdel_ifile(h) 13055714Skris IFILE h; 13155714Skris{ 13255714Skris register struct ifile *p; 133238405Sjkim 134238405Sjkim if (h == NULL_IFILE) 13555714Skris return; 13655714Skris /* 137110007Smarkm * If the ifile we're deleting is the currently open ifile, 13855714Skris * move off it. 13955714Skris */ 140110007Smarkm unmark(h); 14155714Skris if (h == curr_ifile) 14255714Skris curr_ifile = getoff_ifile(curr_ifile); 143110007Smarkm p = int_ifile(h); 14455714Skris unlink_ifile(p); 14555714Skris free(p->h_filename); 146160817Ssimon free(p); 147160817Ssimon} 148160817Ssimon 14955714Skris/* 15055714Skris * Get the ifile after a given one in the list. 15168654Skris */ 152110007Smarkm public IFILE 15355714Skrisnext_ifile(h) 15455714Skris IFILE h; 15555714Skris{ 15655714Skris register struct ifile *p; 15755714Skris 15855714Skris p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 15955714Skris if (p->h_next == &anchor) 160110007Smarkm return (NULL_IFILE); 16155714Skris return (ext_ifile(p->h_next)); 16255714Skris} 16355714Skris 16455714Skris/* 165110007Smarkm * Get the ifile before a given one in the list. 166110007Smarkm */ 167160817Ssimon public IFILE 168110007Smarkmprev_ifile(h) 169110007Smarkm IFILE h; 170110007Smarkm{ 17155714Skris register struct ifile *p; 172110007Smarkm 173160817Ssimon p = (h == NULL_IFILE) ? &anchor : int_ifile(h); 174160817Ssimon if (p->h_prev == &anchor) 175160817Ssimon return (NULL_IFILE); 176160817Ssimon return (ext_ifile(p->h_prev)); 177160817Ssimon} 17855714Skris 17955714Skris/* 180110007Smarkm * Return a different ifile from the given one. 181238405Sjkim */ 182238405Sjkim public IFILE 183110007Smarkmgetoff_ifile(ifile) 18455714Skris IFILE ifile; 185160817Ssimon{ 186160817Ssimon IFILE newifile; 187160817Ssimon 188160817Ssimon if ((newifile = prev_ifile(ifile)) != NULL_IFILE) 189160817Ssimon return (newifile); 190160817Ssimon if ((newifile = next_ifile(ifile)) != NULL_IFILE) 191160817Ssimon return (newifile); 192110007Smarkm return (NULL_IFILE); 193110007Smarkm} 19455714Skris 195238405Sjkim/* 196238405Sjkim * Return the number of ifiles. 197238405Sjkim */ 198238405Sjkim public int 199238405Sjkimnifile() 200238405Sjkim{ 201238405Sjkim return (ifiles); 202238405Sjkim} 203238405Sjkim 204238405Sjkim/* 205238405Sjkim * Find an ifile structure, given a filename. 206238405Sjkim */ 207238405Sjkim static struct ifile * 208238405Sjkimfind_ifile(filename) 209238405Sjkim char *filename; 210238405Sjkim{ 211238405Sjkim register struct ifile *p; 212238405Sjkim 213238405Sjkim for (p = anchor.h_next; p != &anchor; p = p->h_next) 214238405Sjkim if (strcmp(filename, p->h_filename) == 0) 215238405Sjkim return (p); 216238405Sjkim return (NULL); 217238405Sjkim} 218238405Sjkim 219238405Sjkim/* 220194206Ssimon * Get the ifile associated with a filename. 221194206Ssimon * If the filename has not been seen before, 222238405Sjkim * insert the new ifile after "prev" in the list. 223194206Ssimon */ 224238405Sjkim public IFILE 225238405Sjkimget_ifile(filename, prev) 226238405Sjkim char *filename; 227238405Sjkim IFILE prev; 228238405Sjkim{ 229238405Sjkim register struct ifile *p; 230238405Sjkim 23155714Skris if ((p = find_ifile(filename)) == NULL) 23255714Skris p = new_ifile(filename, int_ifile(prev)); 233110007Smarkm return (ext_ifile(p)); 234160817Ssimon} 235160817Ssimon 23655714Skris/* 23755714Skris * Get the filename associated with a ifile. 23855714Skris */ 23955714Skris public char * 24055714Skrisget_filename(ifile) 24155714Skris IFILE ifile; 242160817Ssimon{ 243160817Ssimon if (ifile == NULL) 244160817Ssimon return (NULL); 245160817Ssimon return (int_ifile(ifile)->h_filename); 246160817Ssimon} 247160817Ssimon 248160817Ssimon/* 249160817Ssimon * Get the index of the file associated with a ifile. 250110007Smarkm */ 251160817Ssimon public int 252160817Ssimonget_index(ifile) 25355714Skris IFILE ifile; 25455714Skris{ 255160817Ssimon return (int_ifile(ifile)->h_index); 256160817Ssimon} 25755714Skris 25855714Skris/* 25955714Skris * Save the file position to be associated with a given file. 26055714Skris */ 26155714Skris public void 26255714Skrisstore_pos(ifile, scrpos) 26355714Skris IFILE ifile; 26455714Skris struct scrpos *scrpos; 265110007Smarkm{ 26655714Skris int_ifile(ifile)->h_scrpos = *scrpos; 26755714Skris} 268110007Smarkm 269110007Smarkm/* 270110007Smarkm * Recall the file position associated with a file. 271238405Sjkim * If no position has been associated with the file, return NULL_POSITION. 272238405Sjkim */ 273238405Sjkim public void 274238405Sjkimget_pos(ifile, scrpos) 275110007Smarkm IFILE ifile; 27655714Skris struct scrpos *scrpos; 277110007Smarkm{ 27868654Skris *scrpos = int_ifile(ifile)->h_scrpos; 279110007Smarkm} 280110007Smarkm 281110007Smarkm/* 282110007Smarkm * Mark the ifile as "opened". 283127134Snectar */ 284127134Snectar public void 285238405Sjkimset_open(ifile) 286238405Sjkim IFILE ifile; 287238405Sjkim{ 288238405Sjkim int_ifile(ifile)->h_opened = 1; 289194206Ssimon} 290194206Ssimon 291110007Smarkm/* 292238405Sjkim * Return whether the ifile has been opened previously. 293238405Sjkim */ 294238405Sjkim public int 295238405Sjkimopened(ifile) 296194206Ssimon IFILE ifile; 297194206Ssimon{ 298194206Ssimon return (int_ifile(ifile)->h_opened); 299194206Ssimon} 300194206Ssimon 301238405Sjkim public void 302238405Sjkimhold_ifile(ifile, incr) 30368654Skris IFILE ifile; 30455714Skris int incr; 30555714Skris{ 30655714Skris int_ifile(ifile)->h_hold += incr; 30768654Skris} 30855714Skris 30968654Skris public int 31068654Skrisheld_ifile(ifile) 31168654Skris IFILE ifile; 31268654Skris{ 313238405Sjkim return (int_ifile(ifile)->h_hold); 31468654Skris} 315110007Smarkm 31668654Skris public void * 31768654Skrisget_filestate(ifile) 31868654Skris IFILE ifile; 31968654Skris{ 320110007Smarkm return (int_ifile(ifile)->h_filestate); 32155714Skris} 32268654Skris 32368654Skris public void 32468654Skrisset_filestate(ifile, filestate) 32568654Skris IFILE ifile; 32668654Skris void *filestate; 32768654Skris{ 32868654Skris int_ifile(ifile)->h_filestate = filestate; 32968654Skris} 33068654Skris 331238405Sjkim#if 0 332238405Sjkim public void 333238405Sjkimif_dump() 334238405Sjkim{ 335238405Sjkim register struct ifile *p; 33668654Skris 33768654Skris for (p = anchor.h_next; p != &anchor; p = p->h_next) 33868654Skris { 33968654Skris printf("%x: %d. <%s> pos %d,%x\n", 34068654Skris p, p->h_index, p->h_filename, 34168654Skris p->h_scrpos.ln, p->h_scrpos.pos); 34268654Skris ch_dump(p->h_filestate); 34368654Skris } 34468654Skris} 34568654Skris#endif 346110007Smarkm