/*
 *	$Source: /u1/X/xman/RCS/man.c,v $
 *	$Header: man.c,v 1.1 87/01/28 15:49:49 swick Exp $
 */

#ifndef lint
static char *rcsid_man_c = "$Header: man.c,v 1.1 87/01/28 15:49:49 swick Exp $";
#endif	lint

#include "xman.h"
/*
 * This would have to be reworked for SYS/V etc.
 */

/*
 * Strange, overblown routine to handle reading in the manual
 * entries. Doesn't even begin to consider "non-standard" (eg. SYS/V)
 * manual directory setup tho it would be fairly easy to extrapolate to.
 */

/*
 * The basic goal is to simply build a list of all manual directories
 * and the file names of the sections w/in those directories into the
 * manual structure (see xman.h).
 *
 * TODO:
 *   This assumes manual sections are either formatted (the "catX" dir
 *   exists) or aren't (only the "manX" dir) on a per DIRECTORY basis.
 *   Thus, if you only format some of your manual pages within a section
 *   this won't quite work right (however, if some dirs are formatted and
 *   some not it should pick this up fine.) It would simply require
 *   saving a bit for each page entry (whether in the "man" section thus
 *   needing to be formatted on the fly or in the "cat" section.)
 */
man() {
  DIR *dir;
  register struct direct *dp;
  char *mans[MAXSECT], *cats[MAXSECT];
  int nmans, ncats;
  int i;
  struct stat sb;
  char *entries[MAXENTRY];
  int nentries;
  struct manual *mp;
  extern char *rindex(), *malloc();
  extern int cmpstrp();

  if((dir = opendir(".")) == NULL) {	/* should be chdir'd to MANDIR now */
    perror(MANDIR);
    exit(1);
  }
  nmanual = nmans = ncats = 0;
  /*
   * Read through this directory and save up any directory name
   * which begins with "man" or "cat"
   */
  while((dp = readdir(dir)) != NULL) {
    if((dp->d_namlen >= LMAN) && (strncmp(dp->d_name,MAN,LMAN) == 0)) {
      if(nmans == MAXSECT) goto toomany;
      if((stat(dp->d_name,&sb) >= 0) && (sb.st_mode & S_IFDIR))
	mans[nmans++] = stralloc(dp->d_name);
    }
    else if((dp->d_namlen >= LCAT) && (strncmp(dp->d_name,CAT,LCAT) == 0)) {
      if(ncats == MAXSECT) goto toomany;
      if((stat(dp->d_name,&sb) >= 0) && (sb.st_mode & S_IFDIR))
	cats[ncats++] = stralloc(dp->d_name);
    }
  }
  closedir(dir);
  /*
   * sort the manual section "man" names, useful later
   */
  qsort(mans,nmans,sizeof(mans[0]),cmpstrp);
  /*
   * Now, match up with cat sections if they exist
   */
  for(i=0; i < nmans ; i++) {
    int j;

    manual[nmanual].man = mans[i];
    manual[nmanual].cat = NULL;
    for(j=0; j < ncats; j++)
      if(mans[i][LMAN] == cats[j][LCAT]) {
	manual[nmanual].cat = cats[j];
	break;
      }
    nmanual++;
  }
  /*
   * Go through each manual directory saving up the individual
   * page entries.
   * Demand that a page entry not start with a '.' but have
   * a dot somewhere.
   */
  for(i=0,mp=manual ; i < nmanual; i++,mp++) {
    int j, longest;
    char **cpp, *cp;
    char *sect;
    struct entry *ep;

    sect = (mp->cat == NULL) ? mp->man : mp->cat;
    chdir(sect);
    dir = opendir(".");
    if(dir == NULL) {
      chdir("..");
      continue;
    }
    nentries = 0;
    cpp = entries;
    longest = 0;
    while((dp = readdir(dir)) != NULL) {
      if(nentries == MAXENTRY) {
	eprintf("Too many manual pages in %s\n",sect);
	eprintf("Try recompiling with larger allocations\n");
	exit(1);
      }
      /* starts with a dot? no dot in name? */
      if((dp->d_name[0] == '.') || ((cp = rindex(dp->d_name,'.')) == NULL))
	continue;
      *cpp++ = stralloc(dp->d_name);
      if((j = (cp - dp->d_name)) > longest) longest = j;
      nentries++;
    }
    closedir(dir);
    chdir("..");
    qsort(entries,nentries,sizeof(entries[0]),cmpstrp);
    /*
     * Now allocate and copy into structure
     */
    mp->entries = (struct entry *) malloc(nentries * sizeof(struct entry));
    for(j=0,cpp=entries,ep = mp->entries; j < nentries; j++,cpp++,ep++)
      ep->label = *cpp;
    mp->longest = longest+1;
    mp->nentries = nentries;
  }
  return;
 toomany:
  eprintf("Too many manual sections, recompile with larger allocations\n");
  exit(1);
}
/*
 * used by qsort() above
 */
cmpstrp(p1,p2) char **p1, **p2;
{
  return(strcmp(*p1,*p2));
}
