Annotation of src/usr.bin/less/ifile.c, Revision 1.1
1.1 ! etheisen 1: /*
! 2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice in the documentation and/or other materials provided with
! 12: * the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
! 15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
! 18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
! 20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
! 21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
! 23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
! 24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27:
! 28: /*
! 29: * An IFILE represents an input file.
! 30: *
! 31: * It is actually a pointer to an ifile structure,
! 32: * but is opaque outside this module.
! 33: * Ifile structures are kept in a linked list in the order they
! 34: * appear on the command line.
! 35: * Any new file which does not already appear in the list is
! 36: * inserted after the current file.
! 37: */
! 38:
! 39: #include "less.h"
! 40:
! 41: extern IFILE curr_ifile;
! 42:
! 43: struct ifile {
! 44: struct ifile *h_next; /* Links for command line list */
! 45: struct ifile *h_prev;
! 46: char *h_filename; /* Name of the file */
! 47: void *h_filestate; /* File state (used in ch.c) */
! 48: int h_index; /* Index within command line list */
! 49: int h_opened; /* Only need one bit */
! 50: struct scrpos h_scrpos; /* Saved position within the file */
! 51: };
! 52:
! 53: /*
! 54: * Convert an IFILE (external representation)
! 55: * to a struct file (internal representation), and vice versa.
! 56: */
! 57: #define int_ifile(h) ((struct ifile *)(h))
! 58: #define ext_ifile(h) ((IFILE)(h))
! 59:
! 60: /*
! 61: * Anchor for linked list.
! 62: */
! 63: static struct ifile anchor = { &anchor, &anchor, 0 };
! 64: static int ifiles = 0;
! 65:
! 66: static void
! 67: incr_index(p, incr)
! 68: register struct ifile *p;
! 69: int incr;
! 70: {
! 71: for (; p != &anchor; p = p->h_next)
! 72: p->h_index += incr;
! 73: }
! 74:
! 75: static void
! 76: link_ifile(p, prev)
! 77: struct ifile *p;
! 78: struct ifile *prev;
! 79: {
! 80: /*
! 81: * Link into list.
! 82: */
! 83: if (prev == NULL)
! 84: prev = &anchor;
! 85: p->h_next = prev->h_next;
! 86: p->h_prev = prev;
! 87: prev->h_next->h_prev = p;
! 88: prev->h_next = p;
! 89: /*
! 90: * Calculate index for the new one,
! 91: * and adjust the indexes for subsequent ifiles in the list.
! 92: */
! 93: p->h_index = prev->h_index + 1;
! 94: incr_index(p->h_next, 1);
! 95: ifiles++;
! 96: }
! 97:
! 98: static void
! 99: unlink_ifile(p)
! 100: struct ifile *p;
! 101: {
! 102: p->h_next->h_prev = p->h_prev;
! 103: p->h_prev->h_next = p->h_next;
! 104: incr_index(p->h_next, -1);
! 105: ifiles--;
! 106: }
! 107:
! 108: /*
! 109: * Allocate a new ifile structure and stick a filename in it.
! 110: * It should go after "prev" in the list
! 111: * (or at the beginning of the list if "prev" is NULL).
! 112: * Return a pointer to the new ifile structure.
! 113: */
! 114: static struct ifile *
! 115: new_ifile(filename, prev)
! 116: char *filename;
! 117: struct ifile *prev;
! 118: {
! 119: register struct ifile *p;
! 120:
! 121: /*
! 122: * Allocate and initialize structure.
! 123: */
! 124: p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
! 125: p->h_filename = save(filename);
! 126: p->h_scrpos.pos = NULL_POSITION;
! 127: p->h_opened = 0;
! 128: link_ifile(p, prev);
! 129: return (p);
! 130: }
! 131:
! 132: /*
! 133: * Delete an existing ifile structure.
! 134: */
! 135: public void
! 136: del_ifile(h)
! 137: IFILE h;
! 138: {
! 139: register struct ifile *p;
! 140:
! 141: if (h == NULL_IFILE)
! 142: return;
! 143: /*
! 144: * If the ifile we're deleting is the currently open ifile,
! 145: * move off it.
! 146: */
! 147: if (h == curr_ifile)
! 148: curr_ifile = getoff_ifile(curr_ifile);
! 149: p = int_ifile(h);
! 150: unlink_ifile(p);
! 151: free(p->h_filename);
! 152: free(p);
! 153: }
! 154:
! 155: /*
! 156: * Get the ifile after a given one in the list.
! 157: */
! 158: public IFILE
! 159: next_ifile(h)
! 160: IFILE h;
! 161: {
! 162: register struct ifile *p;
! 163:
! 164: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
! 165: if (p->h_next == &anchor)
! 166: return (NULL_IFILE);
! 167: return (ext_ifile(p->h_next));
! 168: }
! 169:
! 170: /*
! 171: * Get the ifile before a given one in the list.
! 172: */
! 173: public IFILE
! 174: prev_ifile(h)
! 175: IFILE h;
! 176: {
! 177: register struct ifile *p;
! 178:
! 179: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
! 180: if (p->h_prev == &anchor)
! 181: return (NULL_IFILE);
! 182: return (ext_ifile(p->h_prev));
! 183: }
! 184:
! 185: /*
! 186: * Return a different ifile from the given one.
! 187: */
! 188: public IFILE
! 189: getoff_ifile(ifile)
! 190: IFILE ifile;
! 191: {
! 192: IFILE newifile;
! 193:
! 194: if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
! 195: return (newifile);
! 196: if ((newifile = next_ifile(ifile)) != NULL_IFILE)
! 197: return (newifile);
! 198: return (NULL_IFILE);
! 199: }
! 200:
! 201: /*
! 202: * Return the number of ifiles.
! 203: */
! 204: public int
! 205: nifile()
! 206: {
! 207: return (ifiles);
! 208: }
! 209:
! 210: /*
! 211: * Find an ifile structure, given a filename.
! 212: */
! 213: static struct ifile *
! 214: find_ifile(filename)
! 215: char *filename;
! 216: {
! 217: register struct ifile *p;
! 218:
! 219: for (p = anchor.h_next; p != &anchor; p = p->h_next)
! 220: if (strcmp(filename, p->h_filename) == 0)
! 221: return (p);
! 222: return (NULL);
! 223: }
! 224:
! 225: /*
! 226: * Get the ifile associated with a filename.
! 227: * If the filename has not been seen before,
! 228: * insert the new ifile after "prev" in the list.
! 229: */
! 230: public IFILE
! 231: get_ifile(filename, prev)
! 232: char *filename;
! 233: IFILE prev;
! 234: {
! 235: register struct ifile *p;
! 236:
! 237: if ((p = find_ifile(filename)) == NULL)
! 238: p = new_ifile(filename, int_ifile(prev));
! 239: return (ext_ifile(p));
! 240: }
! 241:
! 242: /*
! 243: * Get the filename associated with a ifile.
! 244: */
! 245: public char *
! 246: get_filename(ifile)
! 247: IFILE ifile;
! 248: {
! 249: if (ifile == NULL)
! 250: return (NULL);
! 251: return (int_ifile(ifile)->h_filename);
! 252: }
! 253:
! 254: /*
! 255: * Get the index of the file associated with a ifile.
! 256: */
! 257: public int
! 258: get_index(ifile)
! 259: IFILE ifile;
! 260: {
! 261: return (int_ifile(ifile)->h_index);
! 262: }
! 263:
! 264: /*
! 265: * Save the file position to be associated with a given file.
! 266: */
! 267: public void
! 268: store_pos(ifile, scrpos)
! 269: IFILE ifile;
! 270: struct scrpos *scrpos;
! 271: {
! 272: int_ifile(ifile)->h_scrpos = *scrpos;
! 273: }
! 274:
! 275: /*
! 276: * Recall the file position associated with a file.
! 277: * If no position has been associated with the file, return NULL_POSITION.
! 278: */
! 279: public void
! 280: get_pos(ifile, scrpos)
! 281: IFILE ifile;
! 282: struct scrpos *scrpos;
! 283: {
! 284: *scrpos = int_ifile(ifile)->h_scrpos;
! 285: }
! 286:
! 287: /*
! 288: * Mark the ifile as "opened".
! 289: */
! 290: public void
! 291: set_open(ifile)
! 292: IFILE ifile;
! 293: {
! 294: int_ifile(ifile)->h_opened = 1;
! 295: }
! 296:
! 297: /*
! 298: * Return whether the ifile has been opened previously.
! 299: */
! 300: public int
! 301: opened(ifile)
! 302: IFILE ifile;
! 303: {
! 304: return (int_ifile(ifile)->h_opened);
! 305: }
! 306:
! 307: public void *
! 308: get_filestate(ifile)
! 309: IFILE ifile;
! 310: {
! 311: return (int_ifile(ifile)->h_filestate);
! 312: }
! 313:
! 314: public void
! 315: set_filestate(ifile, filestate)
! 316: IFILE ifile;
! 317: void *filestate;
! 318: {
! 319: int_ifile(ifile)->h_filestate = filestate;
! 320: }
! 321:
! 322: #if 0
! 323: public void
! 324: if_dump()
! 325: {
! 326: register struct ifile *p;
! 327:
! 328: for (p = anchor.h_next; p != &anchor; p = p->h_next)
! 329: {
! 330: printf("%x: %d. <%s> pos %d,%x\n",
! 331: p, p->h_index, p->h_filename,
! 332: p->h_scrpos.ln, p->h_scrpos.pos);
! 333: ch_dump(p->h_filestate);
! 334: }
! 335: }
! 336: #endif