|
|
coherent
/*
* This is a library module for help file subject lookup. There are
* three externally available functions and two externally available
* pointers.
*
* The two externally available pointers must be defined and given a
* value by the program that calls this module, and are
* char *helpfile; The name of the help file
* char *helpindex; The name of the help index file
*
* The functions that are available are:
*
* char *name_gen(basename, pathvar, defpath) char *basename, *pathvar;
* Returns the full name (including path info) of the
* file "basename" looked up on pathvar, if found or
* defpath. The name is returned in a malloc'ed chunk
* of memory which should be free'd when you are done
* with it. Returns NULL on failure.
*
* int help(topic, output) char *topic; int (*output)();
* Lookup the topic and call output with each line of it.
* Returns 1 if the topic could not be found, -1 if the
* file could not be accessed.
*
* int helpclose();
* Close help files and clean up the rest of the world.
*
*/
#include <stdio.h>
#include <sys/stat.h>
#include <path.h>
#include "ed.h"
#define PATHSIZE 64 /* Longest path name */
#if GEMDOS
#define DEFHELPATH DEFLIBPATH
#endif
#if MSDOS
#define DEFHELPATH DEFLIBPATH
#endif
#ifdef COHERENT
#define DEFHELPATH ".:/usr/lib:/etc:/lib:"
#endif
#ifndef HELPSEP
#define HELPSEP '@' /* marks a new help entry */
#endif
extern uchar *helpfile; /* Help file name */
extern uchar *helpindex; /* Help file index */
static FILE *helpfp; /* Our helpfile */
static uchar *helpline; /* Our help buffer */
/*
* Structure to speed lookup time.
*/
struct look {
long l_seek;
uchar *l_name;
};
struct look *lread();
uchar *getenv();
char *path();
/*
* Create a file name from a basename and an environment variable.
*/
uchar *
name_gen(name, pathvar, defpath)
register uchar *name;
uchar *pathvar;
uchar *defpath;
{
register uchar *fullname;
register uchar *libpath;
if ((fullname = (char *)malloc(PATHSIZE)) == NULL)
return NULL;
if ((libpath = getenv(pathvar)) == NULL)
libpath = defpath;
if ((libpath = path(libpath, name, AREAD)) == NULL)
strcpy(fullname, name);
else
strcpy(fullname, libpath);
return fullname;
}
/*
* Get name of flex bind file.
*/
uchar *
flexName()
{
#ifdef COHERENT
return (name_gen(".emacs.rc", "HOME", DEFHELPATH));
#else
return (name_gen("emacs.rc", "LIBPATH", DEFHELPATH));
#endif
}
/* Open the help file "name" with access "acs" along the current
* libpath.
*/
static FILE *
hfopen(name, acs)
uchar *name;
uchar *acs;
{
uchar *fullname;
FILE *fp = NULL;
if ((fullname = name_gen(name, "LIBPATH", DEFHELPATH)) == NULL)
return NULL; /* Can't get full name */
fp = fopen(fullname, acs); /* Open the file. */
mlwrite(fullname);
free(fullname); /* Free the namebuffer */
return fp; /* return the file ptr */
}
/*
* Get the "stat" of the help file...
*/
static hstat(name, sb)
uchar *name;
struct stat *sb;
{
uchar *fullname;
register int s;
if ((fullname = name_gen(name, "LIBPATH", DEFHELPATH)) == NULL)
return -1; /* could not get the name */
s = stat(fullname, sb); /* stat the file. */
free(fullname);
return s;
}
helpclose() {
if (helpfp != NULL)
fclose(helpfp);
if (helpline != NULL)
free(helpline);
helpfp = helpline = NULL;
}
/*
* program interface to the help file. open file(s) as needed.
* subsequent calls will not need to search and open them
* again -- output function takes a string arg and does something
* with it. Non-zero return means no help found.
*/
help(topic, output)
uchar *topic;
int (*output)();
{
if (helpfp == NULL)
if ((helpfp = hfopen(helpfile, "r")) == NULL)
return -1;
if (helpline == NULL)
if ((helpline = malloc(NLINE)) == NULL)
return -1;
return (lookup(topic, helpfp, helpindex, output));
}
/*
* Make an index of help for a given topic.
* Non-zero return means no topics found.
*/
indexhelp(topic, output)
uchar *topic;
int (*output)();
{
if (helpfp == NULL)
if ((helpfp = hfopen(helpfile, "r")) == NULL)
return -1;
if (helpline == NULL)
if ((helpline = malloc(NLINE)) == NULL)
return -1;
return (doindex(topic, helpfp, output));
}
/*
* Lookup a command in the given file.
* The format is to look for HELPSEP (@) lines.
* The optional index-file is provided to speed up
* the lookup in situations where there is a very
* large system help file.
*/
static lookup(com, fp, ind, output)
register uchar *com;
FILE *fp;
uchar *ind;
int (*output)();
{
if (fp == NULL)
return (1);
fseek(fp, 0L, 0);
fastlook(com, fp, ind);
while (fgets(helpline, NLINE, fp) != NULL)
if (helpline[0] == HELPSEP) {
helpline[strlen(helpline)-1] = '\0';
if (strcmp(com, helpline+1) == 0) {
while (fgets(helpline, NLINE, fp) != NULL) {
if (helpline[0] == HELPSEP)
break;
helpline[strlen(helpline)-1] = '\0';
(*output)(helpline);
}
return (0);
}
}
return (1);
}
/*
* Possibly seek the helpfile to the right place based on an index file.
* Return non-zero only when it is impossible to find it.
*/
static fastlook(com, fp, ind)
uchar *com;
FILE *fp;
uchar *ind;
{
register struct look *lp;
FILE *ifp;
static struct stat sb;
#if !MSDOS
long htime;
fstat(fileno(fp), &sb);
htime = sb.st_mtime;
#endif
if (ind == NULL) /* No index file? */
return;
if (hstat(ind, &sb) < 0) /* not found ? */
return;
#if !MSDOS
if (htime < sb.st_mtime) {
#endif
if ((ifp = hfopen(ind, "rb")) == NULL)
return;
while ((lp = lread(ifp)) != NULL)
if (strcmp(com, lp->l_name) == 0) {
fseek(fp, lp->l_seek, 0);
break;
}
fclose(ifp);
#if !MSDOS
}
#endif
return;
}
/*
* Read in a look structure. Return NULL
* on end of file or error.
*/
static struct look *
lread(fp)
register FILE *fp;
{
register uchar *cp;
register int c;
static struct look look;
static uchar name[50];
look.l_name = name;
if (fread(&look.l_seek, sizeof look.l_seek, 1, fp) != 1)
return (NULL);
for (cp = name; cp<&name[49]; cp++) {
if ((c = getc(fp)) == EOF)
return (NULL);
*cp = c;
if (c == '\0')
break;
}
return (&look);
}
/* Return 0 if s1 found in s2 */
static subcmp(s1, s2)
uchar *s1;
register uchar *s2;
{
register uchar *st;
register uchar *se;
st = s1;
for (;;) {
while (*st != *s2++)
if (*s2 == '\0')
return 1;
if (*st++ == '\0')
return 0;
se = s2;
while (*st++ == *se++) {
if (*st == '\0')
return 0;
if (*se == '\0')
return 1;
}
st = s1;
}
}
static int doindex(com, fp, output)
register uchar *com;
FILE *fp;
int (*output)();
{
register int t = 0;
if (fp == NULL)
return (1);
fseek(fp, 0L, 0);
while (fgets(helpline, NLINE, fp) != NULL) {
if (helpline[0] == HELPSEP) {
helpline[strlen(helpline)-1] = '\0';
if (subcmp(com, helpline+1) == 0) {
if (fgets(helpline, NLINE, fp) == NULL)
return t == 0;
helpline[strlen(helpline)-1] = '\0';
(*output)(helpline);
t++;
}
}
}
if (t == 0)
return 1;
return 0;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.