home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 10 / Fresh_Fish_10_2352.bin / new / dev / lang / sgmls / src / entgen.c < prev    next >
C/C++ Source or Header  |  1994-07-10  |  12KB  |  518 lines

  1. /* entgen.c -
  2.  
  3.    Implement entgen() which generates a list of filenames from a struct fpi.
  4.  
  5.    Written by James Clark (jjc@jclark.com).
  6. */
  7.  
  8. #include "config.h"
  9.  
  10. #ifdef HAVE_ACCESS
  11.  
  12. #ifdef HAVE_UNISTD_H
  13. #include <unistd.h>        /* For R_OK. */
  14. #endif /* HAVE_UNISTD_H */
  15.  
  16. #ifndef R_OK
  17. #define R_OK 4
  18. #endif /* not R_OK */
  19.  
  20. #endif /* HAVE_ACCESS */
  21.  
  22. #include "sgmlaux.h"
  23.  
  24. /* Environment variable that contains path. */
  25. #ifndef PATH_ENV_VAR
  26. #define PATH_ENV_VAR "SGML_PATH"
  27. #endif
  28. /* Default search path.  See field() for interpretation of %*. */
  29. #ifndef DEFAULT_PATH
  30. #define DEFAULT_PATH "/usr/local/lib/sgml/%O/%C/%T:%N.%X:%N.%D"
  31. #endif
  32.  
  33. #ifndef PATH_FILE_SEP
  34. #define PATH_FILE_SEP ':'
  35. #endif
  36.  
  37. #ifndef SYSID_FILE_SEP
  38. #define SYSID_FILE_SEP ':'
  39. #endif
  40.  
  41. /* This says: change space to underscore, slash to percent. */
  42.  
  43. #ifndef MIN_DAT_SUBS_FROM
  44. #define MIN_DAT_SUBS_FROM " /"
  45. #endif
  46. #ifndef MIN_DAT_SUBS_TO
  47. #define MIN_DAT_SUBS_TO "_%"
  48. #endif
  49.  
  50. static int field P((struct fpi *, int, char *));
  51. static int mindatcpy P((char *, char *, int, int));
  52. static int testopen P((char *));
  53. static UNIV sysidgen P((char *));
  54. static UNIV catsysidgen P((const char *, const char *));
  55. static const char *basename P((const char *));
  56.  
  57. static char *path = 0;
  58.  
  59. /* Non-zero if searching should be performed when a system identifier
  60. is specified. */
  61. static int sysidsrch = 0;
  62.  
  63. #define EMPTY_VERSION "default"
  64.  
  65. static char *classes[] = {
  66.      "capacity",
  67.      "charset",
  68.      "notation",
  69.      "syntax",
  70.      "document",
  71.      "dtd",
  72.      "elements",
  73.      "entities",
  74.      "lpd",
  75.      "nonsgml",
  76.      "shortref",
  77.      "subdoc",
  78.      "text"
  79.      };
  80.  
  81. /* This is mainly for compatibility with arcsgml. */
  82.  
  83. static char *genext[] = {
  84.      "nsd",  /* Non-SGML data entity. */
  85.      "gml",  /* GML document or text entity. */
  86.      "spe",  /* System parameter entity. */
  87.      "dtd",  /* Document type definition. */
  88.      "lpd",  /* Link process definition. */
  89.      "pns",  /* Public non-SGML data entity. */
  90.      "pge",  /* Public general entity. */
  91.      "ppe",  /* Public parameter entity. */
  92.      "pdt",  /* Public document type definition. */
  93.      "plp",  /* Public link process definition. */
  94.      "vns",  /* Display version non-SGML data entity. */
  95.      "vge",  /* Display version general entity. */
  96.      "vpe",  /* Display version parameter entity. */
  97.      "vdt",  /* Display version document type definition.*/
  98.      "vlp",  /* Display version link process definition.*/
  99. };
  100.  
  101. static char *ext[] = {
  102.      "sgml",            /* SGML subdocument */
  103.      "data",            /* Data */
  104.      "text",            /* General text */
  105.      "parm",            /* Parameter entity */
  106.      "dtd",            /* Document type definition */
  107.      "lpd",            /* Link process definition */
  108. };
  109.  
  110. static CATALOG catalog;
  111.  
  112. VOID entginit(swp)
  113. struct switches *swp;
  114. {
  115.      catalog = swp->catalog;
  116. }
  117.  
  118. /* Like memcpy, but substitute, fold to lower case (if fold is
  119. non-zero) and null terminate.  This is used both for minimum data and
  120. for names. If p is NULL, do nothing. Return len. */
  121.  
  122. static int mindatcpy(p, q, len, fold)
  123. char *p, *q;
  124. int len;
  125. int fold;
  126. {
  127.      static char subsfrom[] = MIN_DAT_SUBS_FROM;
  128.      static char substo[] = MIN_DAT_SUBS_TO;
  129.      int n;
  130.  
  131.      if (!p)
  132.       return len;
  133.      for (n = len; --n >= 0; q++) {
  134.       char *r = strchr(subsfrom, *q);
  135.       if (!r) {
  136.            if (fold && ISASCII(*q) && isupper((UNCH)*q))
  137.             *p++ = tolower((UNCH)*q);
  138.            else
  139.             *p++ = *q;
  140.       }
  141.       else {
  142.            int i = r - subsfrom;
  143.            if (i < sizeof(substo) - 1)
  144.             *p++ = substo[i];
  145.       }
  146.      }
  147.      *p = '\0';
  148.      return len;
  149. }
  150.  
  151.  
  152. /* Return length of field.  Copy into buf if non-NULL. */
  153.  
  154. static int field(f, c, buf)
  155. struct fpi *f;
  156. int c;
  157. char *buf;
  158. {
  159.      int n;
  160.  
  161.      switch (c) {
  162.      case '%':
  163.       if (buf) {
  164.            buf[0] = '%';
  165.            buf[1] = '\0';
  166.       }
  167.       return 1;
  168.      case 'N':            /* the entity, document or dcn name */
  169.       return mindatcpy(buf, (char *)f->fpinm, ustrlen(f->fpinm),
  170.             (f->fpistore != 1 && f->fpistore != 2 && f->fpistore != 3
  171.              ? NAMECASE
  172.              : ENTCASE));
  173.      case 'D':            /* dcn name */
  174.       if (f->fpistore != 1) /* not a external data entity */
  175.            return -1;
  176.       if (f->fpinedcn == 0) /* it's a SUBDOC */
  177.            return -1;
  178.       return mindatcpy(buf, (char *)f->fpinedcn, ustrlen(f->fpinedcn),
  179.                           NAMECASE);
  180.      case 'X':
  181.       /* This is for compatibility with arcsgml */
  182.       if (f->fpistore < 1 || f->fpistore > 5)
  183.            return -1;
  184.       n = (f->fpipubis != 0)*(f->fpiversw > 0 ? 2 : 1)*5+f->fpistore - 1;
  185.       if (buf)
  186.            strcpy(buf, genext[n]);
  187.       return (int)strlen(genext[n]);
  188.      case 'Y':            /* tYpe */
  189.       n = f->fpistore;
  190.       if (n < 1 || n > 5)
  191.            return -1;
  192.       if (n == 1 && f->fpinedcn == 0) /* it's a SUBDOC */
  193.            n = 0;
  194.       if (buf)
  195.            strcpy(buf, ext[n]);
  196.       return (int)strlen(ext[n]);
  197.      case 'P':            /* public identifier */
  198.       if (!f->fpipubis)
  199.            return -1;
  200.       return mindatcpy(buf, (char *)f->fpipubis, ustrlen(f->fpipubis), 0);
  201.      case 'S':            /* system identifier */
  202.       if (!f->fpisysis)
  203.            return -1;
  204.       else {
  205.            UNCH *p;
  206.            n = 0;
  207.            for (p = f->fpisysis; *p; p++)
  208.             if (*p != RSCHAR) {
  209.              if (buf)
  210.                   buf[n] = *p == RECHAR ? '\n' : *p;
  211.              n++;
  212.             }
  213.            return n;
  214.       }
  215.      }
  216.      /* Other fields need a formal public identifier. */
  217.      /* return -1 if the formal public identifier was invalid or missing. */
  218.      if (f->fpiversw < 0 || !f->fpipubis)
  219.       return -1;
  220.  
  221.      switch (c) {
  222.      case 'A':            /* Is it available? */
  223.       return f->fpitt == '+' ? 0 : -1;
  224.      case 'I':            /* Is it ISO? */
  225.       return f->fpiot == '!' ? 0 : -1;
  226.      case 'R':            /* Is it registered? */
  227.       return f->fpiot == '+' ? 0 : -1;
  228.      case 'U':            /* Is it unregistered? */
  229.       return f->fpiot == '-' ? 0 : -1;
  230.      case 'L':            /* public text language */
  231.       if (f->fpic == FPICHARS)
  232.            return -1;
  233.       /* it's entered in all upper case letters */
  234.       return mindatcpy(buf, (char *)f->fpipubis + f->fpil, f->fpill, 1);
  235.      case 'O':            /* owner identifier */
  236.       return mindatcpy(buf, (char *)f->fpipubis + f->fpio, f->fpiol, 0);
  237.      case 'C':            /* public text class */
  238.       n = f->fpic - 1;
  239.       if (n < 0 || n >= sizeof(classes)/sizeof(classes[0]))
  240.            return -1;
  241.       if (buf)
  242.            strcpy(buf, classes[n]);
  243.       return (int)strlen(classes[n]);
  244.      case 'T':            /* text description */
  245.       return mindatcpy(buf, (char *)f->fpipubis + f->fpit, f->fpitl, 0);
  246.      case 'V':
  247.       if (f->fpic < FPICMINV)    /* class doesn't have version */
  248.            return -1;
  249.       if (f->fpiversw > 0)             /* no version */
  250.            return -1;
  251.       if (f->fpivl == 0) {        /* empty version: */
  252.                         /* use device-independent version*/
  253.            if (buf)
  254.             strcpy(buf, EMPTY_VERSION);
  255.            return (int)strlen(EMPTY_VERSION);
  256.       }
  257.       return mindatcpy(buf, (char *)f->fpipubis + f->fpiv, f->fpivl, 0);
  258.      case 'E':                  /* public text designating (escape) sequence */
  259.       if (f->fpic != FPICHARS)
  260.            return -1;
  261.       return mindatcpy(buf, (char *)f->fpipubis + f->fpil, f->fpill, 0);
  262.      default:
  263.       break;
  264.      }
  265.      return -1;
  266. }
  267.  
  268. static int testopen(pathname)
  269. char *pathname;
  270. {
  271. #ifdef HAVE_ACCESS
  272.      return access(pathname, R_OK) >= 0;
  273. #else /* not HAVE_ACCESS */
  274.      FILE *fp;
  275.      fp = fopen(pathname, "r");
  276.      if (!fp)
  277.       return 0;
  278.      fclose(fp);
  279.      return 1;
  280. #endif /* not HAVE_ACCESS */
  281. }
  282.  
  283. /* Return a pointer to an dynamically-allocated buffer that contains
  284.    the names of the files containing this entity, with each filename
  285.    terminated by a '\0', and with the list of filenames terminated by
  286.    another '\0'. */
  287.  
  288. UNIV entgen(f)
  289. struct fpi *f;
  290. {
  291.      char *qname;
  292.      char *file;
  293.      enum catalog_decl_type dtype;
  294.      char *subst = 0;
  295.      const char *sysid;
  296.      const char *catfile;
  297.  
  298.      assert(f->fpistore != 6);    /* Musn't call entgen for a notation. */
  299.      if (!path) {
  300.       char *p;
  301.       char c;
  302.       path = getenv(PATH_ENV_VAR);
  303.       if (!path)
  304.            path = DEFAULT_PATH;
  305.       p = path;
  306.  
  307.       /* Only search for system identifiers if path uses %S. */
  308.       while ((c = *p++) != '\0')
  309.            if (c == '%') {
  310.             if (*p == 'S') {
  311.              sysidsrch = 1;
  312.              break;
  313.             }
  314.             if (*p != '\0' && *p != PATH_FILE_SEP)
  315.              p++;
  316.            }
  317.      }
  318.  
  319.      if