|
|
1.1 ! root 1: /* ! 2: * This is a library module for help file subject lookup. There are ! 3: * three externally available functions and two externally available ! 4: * pointers. ! 5: * ! 6: * The two externally available pointers must be defined and given a ! 7: * value by the program that calls this module, and are ! 8: * char *helpfile; The name of the help file ! 9: * char *helpindex; The name of the help index file ! 10: * ! 11: * The functions that are available are: ! 12: * ! 13: * char *name_gen(basename, pathvar, defpath) char *basename, *pathvar; ! 14: * Returns the full name (including path info) of the ! 15: * file "basename" looked up on pathvar, if found or ! 16: * defpath. The name is returned in a malloc'ed chunk ! 17: * of memory which should be free'd when you are done ! 18: * with it. Returns NULL on failure. ! 19: * ! 20: * int help(topic, output) char *topic; int (*output)(); ! 21: * Lookup the topic and call output with each line of it. ! 22: * Returns 1 if the topic could not be found, -1 if the ! 23: * file could not be accessed. ! 24: * ! 25: * int helpclose(); ! 26: * Close help files and clean up the rest of the world. ! 27: * ! 28: */ ! 29: #include <stdio.h> ! 30: #include <sys/stat.h> ! 31: #include <path.h> ! 32: #include "ed.h" ! 33: ! 34: #define PATHSIZE 64 /* Longest path name */ ! 35: ! 36: #if GEMDOS ! 37: #define DEFHELPATH DEFLIBPATH ! 38: #endif ! 39: ! 40: #if MSDOS ! 41: #define DEFHELPATH DEFLIBPATH ! 42: #endif ! 43: ! 44: #ifdef COHERENT ! 45: #define DEFHELPATH ".:/usr/lib:/etc:/lib:" ! 46: #endif ! 47: ! 48: #ifndef HELPSEP ! 49: #define HELPSEP '@' /* marks a new help entry */ ! 50: #endif ! 51: ! 52: extern uchar *helpfile; /* Help file name */ ! 53: extern uchar *helpindex; /* Help file index */ ! 54: ! 55: static FILE *helpfp; /* Our helpfile */ ! 56: static uchar *helpline; /* Our help buffer */ ! 57: ! 58: /* ! 59: * Structure to speed lookup time. ! 60: */ ! 61: struct look { ! 62: long l_seek; ! 63: uchar *l_name; ! 64: }; ! 65: ! 66: struct look *lread(); ! 67: ! 68: uchar *getenv(); ! 69: char *path(); ! 70: ! 71: /* ! 72: * Create a file name from a basename and an environment variable. ! 73: */ ! 74: uchar * ! 75: name_gen(name, pathvar, defpath) ! 76: register uchar *name; ! 77: uchar *pathvar; ! 78: uchar *defpath; ! 79: { ! 80: register uchar *fullname; ! 81: register uchar *libpath; ! 82: ! 83: if ((fullname = (char *)malloc(PATHSIZE)) == NULL) ! 84: return NULL; ! 85: if ((libpath = getenv(pathvar)) == NULL) ! 86: libpath = defpath; ! 87: if ((libpath = path(libpath, name, AREAD)) == NULL) ! 88: strcpy(fullname, name); ! 89: else ! 90: strcpy(fullname, libpath); ! 91: return fullname; ! 92: } ! 93: ! 94: /* ! 95: * Get name of flex bind file. ! 96: */ ! 97: uchar * ! 98: flexName() ! 99: { ! 100: #ifdef COHERENT ! 101: return (name_gen(".emacs.rc", "HOME", DEFHELPATH)); ! 102: #else ! 103: return (name_gen("emacs.rc", "LIBPATH", DEFHELPATH)); ! 104: #endif ! 105: } ! 106: ! 107: /* Open the help file "name" with access "acs" along the current ! 108: * libpath. ! 109: */ ! 110: static FILE * ! 111: hfopen(name, acs) ! 112: uchar *name; ! 113: uchar *acs; ! 114: { ! 115: uchar *fullname; ! 116: FILE *fp = NULL; ! 117: ! 118: if ((fullname = name_gen(name, "LIBPATH", DEFHELPATH)) == NULL) ! 119: return NULL; /* Can't get full name */ ! 120: fp = fopen(fullname, acs); /* Open the file. */ ! 121: mlwrite(fullname); ! 122: free(fullname); /* Free the namebuffer */ ! 123: return fp; /* return the file ptr */ ! 124: } ! 125: ! 126: /* ! 127: * Get the "stat" of the help file... ! 128: */ ! 129: static hstat(name, sb) ! 130: uchar *name; ! 131: struct stat *sb; ! 132: { ! 133: uchar *fullname; ! 134: register int s; ! 135: ! 136: if ((fullname = name_gen(name, "LIBPATH", DEFHELPATH)) == NULL) ! 137: return -1; /* could not get the name */ ! 138: s = stat(fullname, sb); /* stat the file. */ ! 139: free(fullname); ! 140: return s; ! 141: } ! 142: ! 143: helpclose() { ! 144: if (helpfp != NULL) ! 145: fclose(helpfp); ! 146: if (helpline != NULL) ! 147: free(helpline); ! 148: helpfp = helpline = NULL; ! 149: } ! 150: ! 151: /* ! 152: * program interface to the help file. open file(s) as needed. ! 153: * subsequent calls will not need to search and open them ! 154: * again -- output function takes a string arg and does something ! 155: * with it. Non-zero return means no help found. ! 156: */ ! 157: help(topic, output) ! 158: uchar *topic; ! 159: int (*output)(); ! 160: { ! 161: if (helpfp == NULL) ! 162: if ((helpfp = hfopen(helpfile, "r")) == NULL) ! 163: return -1; ! 164: if (helpline == NULL) ! 165: if ((helpline = malloc(NLINE)) == NULL) ! 166: return -1; ! 167: return (lookup(topic, helpfp, helpindex, output)); ! 168: } ! 169: ! 170: /* ! 171: * Make an index of help for a given topic. ! 172: * Non-zero return means no topics found. ! 173: */ ! 174: indexhelp(topic, output) ! 175: uchar *topic; ! 176: int (*output)(); ! 177: { ! 178: if (helpfp == NULL) ! 179: if ((helpfp = hfopen(helpfile, "r")) == NULL) ! 180: return -1; ! 181: if (helpline == NULL) ! 182: if ((helpline = malloc(NLINE)) == NULL) ! 183: return -1; ! 184: return (doindex(topic, helpfp, output)); ! 185: } ! 186: ! 187: /* ! 188: * Lookup a command in the given file. ! 189: * The format is to look for HELPSEP (@) lines. ! 190: * The optional index-file is provided to speed up ! 191: * the lookup in situations where there is a very ! 192: * large system help file. ! 193: */ ! 194: static lookup(com, fp, ind, output) ! 195: register uchar *com; ! 196: FILE *fp; ! 197: uchar *ind; ! 198: int (*output)(); ! 199: { ! 200: if (fp == NULL) ! 201: return (1); ! 202: fseek(fp, 0L, 0); ! 203: fastlook(com, fp, ind); ! 204: while (fgets(helpline, NLINE, fp) != NULL) ! 205: if (helpline[0] == HELPSEP) { ! 206: helpline[strlen(helpline)-1] = '\0'; ! 207: if (strcmp(com, helpline+1) == 0) { ! 208: while (fgets(helpline, NLINE, fp) != NULL) { ! 209: if (helpline[0] == HELPSEP) ! 210: break; ! 211: helpline[strlen(helpline)-1] = '\0'; ! 212: (*output)(helpline); ! 213: } ! 214: return (0); ! 215: } ! 216: } ! 217: return (1); ! 218: } ! 219: ! 220: /* ! 221: * Possibly seek the helpfile to the right place based on an index file. ! 222: * Return non-zero only when it is impossible to find it. ! 223: */ ! 224: static fastlook(com, fp, ind) ! 225: uchar *com; ! 226: FILE *fp; ! 227: uchar *ind; ! 228: { ! 229: register struct look *lp; ! 230: FILE *ifp; ! 231: static struct stat sb; ! 232: #if !MSDOS ! 233: long htime; ! 234: ! 235: fstat(fileno(fp), &sb); ! 236: htime = sb.st_mtime; ! 237: #endif ! 238: if (ind == NULL) /* No index file? */ ! 239: return; ! 240: if (hstat(ind, &sb) < 0) /* not found ? */ ! 241: return; ! 242: #if !MSDOS ! 243: if (htime < sb.st_mtime) { ! 244: #endif ! 245: if ((ifp = hfopen(ind, "rb")) == NULL) ! 246: return; ! 247: while ((lp = lread(ifp)) != NULL) ! 248: if (strcmp(com, lp->l_name) == 0) { ! 249: fseek(fp, lp->l_seek, 0); ! 250: break; ! 251: } ! 252: fclose(ifp); ! 253: #if !MSDOS ! 254: } ! 255: #endif ! 256: return; ! 257: } ! 258: ! 259: /* ! 260: * Read in a look structure. Return NULL ! 261: * on end of file or error. ! 262: */ ! 263: static struct look * ! 264: lread(fp) ! 265: register FILE *fp; ! 266: { ! 267: register uchar *cp; ! 268: register int c; ! 269: static struct look look; ! 270: static uchar name[50]; ! 271: ! 272: look.l_name = name; ! 273: if (fread(&look.l_seek, sizeof look.l_seek, 1, fp) != 1) ! 274: return (NULL); ! 275: for (cp = name; cp<&name[49]; cp++) { ! 276: if ((c = getc(fp)) == EOF) ! 277: return (NULL); ! 278: *cp = c; ! 279: if (c == '\0') ! 280: break; ! 281: } ! 282: return (&look); ! 283: } ! 284: ! 285: /* Return 0 if s1 found in s2 */ ! 286: static subcmp(s1, s2) ! 287: uchar *s1; ! 288: register uchar *s2; ! 289: { ! 290: register uchar *st; ! 291: register uchar *se; ! 292: ! 293: st = s1; ! 294: for (;;) { ! 295: while (*st != *s2++) ! 296: if (*s2 == '\0') ! 297: return 1; ! 298: if (*st++ == '\0') ! 299: return 0; ! 300: se = s2; ! 301: while (*st++ == *se++) { ! 302: if (*st == '\0') ! 303: return 0; ! 304: if (*se == '\0') ! 305: return 1; ! 306: } ! 307: st = s1; ! 308: } ! 309: } ! 310: ! 311: static int doindex(com, fp, output) ! 312: register uchar *com; ! 313: FILE *fp; ! 314: int (*output)(); ! 315: { ! 316: register int t = 0; ! 317: ! 318: if (fp == NULL) ! 319: return (1); ! 320: fseek(fp, 0L, 0); ! 321: while (fgets(helpline, NLINE, fp) != NULL) { ! 322: if (helpline[0] == HELPSEP) { ! 323: helpline[strlen(helpline)-1] = '\0'; ! 324: if (subcmp(com, helpline+1) == 0) { ! 325: if (fgets(helpline, NLINE, fp) == NULL) ! 326: return t == 0; ! 327: helpline[strlen(helpline)-1] = '\0'; ! 328: (*output)(helpline); ! 329: t++; ! 330: } ! 331: } ! 332: } ! 333: if (t == 0) ! 334: return 1; ! 335: return 0; ! 336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.