home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / mkdoc / mkdoc.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-27  |  6.6 KB  |  350 lines

  1. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <dirent.h>
  5. #include <sys/stat.h>
  6. #include <unistd.h>
  7.  
  8. char *dj_strlwr(char *s)
  9. {
  10.   char *p = s;
  11.   while (*s)
  12.   {
  13.     if ((*s >= 'A') && (*s <= 'Z'))
  14.       *s += 'a'-'A';
  15.     s++;
  16.   }
  17.   return p;
  18. }
  19.  
  20. struct TreeNode;
  21. struct Node;
  22. int count_nodes = 0;
  23.  
  24. typedef void (*TFunc)(Node *);
  25.  
  26. struct Tree {
  27.   TreeNode *nodes;
  28.   Tree();
  29.   void add(Node *n);
  30.   static void Traverse(TreeNode *tn, TFunc tf);
  31.   void Traverse(TFunc tf);
  32.   Node *find(char *name);
  33. };
  34.  
  35. struct Line {
  36.   struct Line *next;
  37.   char *line;
  38. };
  39.  
  40. struct Node {
  41.   Node *prev, *next;
  42.   char *name;
  43.   char *sname;
  44.   char *cat;
  45.   Line *lines;
  46.   Line *lastline;
  47.   Tree subnodes;
  48.   char *filename;
  49.   Node(char *name, char *cat);
  50.   void add(char *line);
  51. };
  52.  
  53. struct TreeNode {
  54.   TreeNode *before, *after;
  55.   Node *node;
  56.   TreeNode(Node *n);
  57. };
  58.  
  59. Tree categories;
  60. Tree nodes;
  61.  
  62. //-----------------------------------------------------------------------------
  63.  
  64. Node::Node(char *Pname, char *Pcat)
  65. {
  66.   char *cp;
  67.   name = strdup(Pname);
  68.   for (cp=name; *cp == '_'; cp++);
  69.   sname = strdup(cp);
  70.   dj_strlwr(sname);
  71.   cat = strdup(Pcat);
  72.   lines = 0;
  73.   lastline = 0;
  74. }
  75.  
  76. void
  77. Node::add(char *l)
  78. {
  79.   Line *lp = new Line;
  80.   lp->next = 0;
  81.   lp->line = strdup(l);
  82.   if (lastline)
  83.     lastline->next = lp;
  84.   if (!lines)
  85.     lines = lp;
  86.   lastline = lp;
  87. }
  88.  
  89. //-----------------------------------------------------------------------------
  90.  
  91. TreeNode::TreeNode(Node *n)
  92. {
  93.   before = after = 0;
  94.   node = n;
  95. }
  96.  
  97. Tree::Tree()
  98. {
  99.   nodes = 0;
  100. }
  101.  
  102. void
  103. Tree::add(Node *n)
  104. {
  105.   TreeNode *tp = new TreeNode(n);
  106.   TreeNode **np = &nodes;
  107.   while (*np)
  108.   {
  109.     if (strcmp((*np)->node->sname, n->sname) < 0)
  110.       np = &((*np)->after);
  111.     else
  112.       np = &((*np)->before);
  113.   }
  114.   *np = tp;
  115. }
  116.  
  117. Node *set_np_prev = 0;
  118. void
  119. set_np(Node *n)
  120. {
  121.   n->prev = set_np_prev;
  122.   n->next = 0;
  123.   if (set_np_prev)
  124.     set_np_prev->next = n;
  125.   set_np_prev = n;
  126. }
  127.  
  128. void
  129. Tree::Traverse(TreeNode *tn, TFunc tf)
  130. {
  131.   if (!tn)
  132.     return;
  133.   Traverse(tn->before, tf);
  134.   tf(tn->node);
  135.   Traverse(tn->after, tf);
  136. }
  137.  
  138. void
  139. Tree::Traverse(TFunc tf)
  140. {
  141.   set_np_prev = 0;
  142.   Traverse(nodes, set_np);
  143.   Traverse(nodes, tf);
  144. }
  145.  
  146. Node *
  147. Tree::find(char *name)
  148. {
  149.   char *sname;
  150.   for (sname = name; *sname == '_'; sname++);
  151.   sname = strdup(sname);
  152.   dj_strlwr(sname);
  153.  
  154.   TreeNode *tn = nodes;
  155.   while (tn)
  156.   {
  157.     if (strcmp(tn->node->sname, sname) == 0)
  158.     {
  159.       return tn->node;
  160.     }
  161.     if (strcmp(sname, tn->node->sname) < 0)
  162.       tn = tn->before;
  163.     else
  164.       tn = tn->after;
  165.   }
  166.   Node *n = new Node(name, "");
  167.   add(n);
  168.   return n;
  169. }
  170.  
  171. //-----------------------------------------------------------------------------
  172.  
  173. FILE *co;
  174. int print_filenames = 0;
  175.  
  176. void
  177. pnode(Node *n, char *up)
  178. {
  179.   fprintf(co, "@c -----------------------------------------------------------------------------\n");
  180.   fprintf(co, "@node %s, %s, %s, %s\n", n->name,
  181.       n->next ? n->next->name : "", n->prev ? n->prev->name : "", up);
  182.   fprintf(co, "@unnumberedsec %s\n", n->name);
  183.   if (print_filenames)
  184.     fprintf(co, "@c From file %s\n", n->filename);
  185. }
  186.  
  187. void
  188. cprint1(Node *n)
  189. {
  190.   fprintf(co, "* %s::\n", n->name);
  191. }
  192.  
  193. void
  194. cprint2b(Node *n)
  195. {
  196.   fprintf(co, "* %s::\n", n->name);
  197. }
  198.  
  199. void
  200. cprint2(Node *n)
  201. {
  202.   pnode(n, "Functional Categories");
  203.   fprintf(co, "@menu\n");
  204.   n->subnodes.Traverse(cprint2b);
  205.   fprintf(co, "@end menu\n");
  206. }
  207.  
  208. void
  209. nprint1(Node *n)
  210. {
  211.   fprintf(co, "* %s::\n", n->name);
  212. }
  213.  
  214. void
  215. nprint2(Node *n)
  216. {
  217.   pnode(n, "Alphabetical List");
  218.   Line *l;
  219.   for (l=n->lines; l; l=l->next)
  220.   {
  221.     fputs(l->line, co);
  222.     if (strncmp(l->line, "@heading ", 9) == 0)
  223.       fprintf(co, "@iftex\n@donoderef()\n@end iftex\n");
  224.   }
  225. }
  226.  
  227. int is_directory(char *name)
  228. {
  229.       struct stat statbuf;
  230.       int result;
  231.  
  232.       result = stat(name, &statbuf);
  233.       if(result < 0)
  234.               return 0;
  235.       if(S_ISDIR(statbuf.st_mode))
  236.               return 1;
  237.       else    return 0;
  238. }
  239.  
  240. //-----------------------------------------------------------------------------
  241.  
  242. scan_directory(char *which)
  243. {
  244.   Node *curnode;
  245.   DIR *d = opendir(which);
  246.   struct dirent *de;
  247.   while (de = readdir(d))
  248.   {
  249.     if (de->d_name[0] == '.')
  250.       continue;
  251.     char buf[4000];
  252.     sprintf(buf, "%s/%s", which, de->d_name);
  253.  
  254. #ifdef D_OK
  255.     if (access(buf, D_OK) == 0)
  256.     {
  257.       scan_directory(buf);
  258.     }
  259. #else
  260.    /* determine if a directory */
  261.    if(is_directory(buf))
  262.    {
  263.       scan_directory(buf);
  264.    }
  265. #endif
  266.     else if (strstr(buf, ".txh"))
  267.     {
  268.       char *filename = new char[strlen(buf)+1];
  269.       strcpy(filename, buf);
  270.       FILE *ci = fopen(buf, "r");
  271.       if (!ci)
  272.       {
  273.     perror(buf);
  274.     continue;
  275.       }
  276.       curnode = 0;
  277.       while (fgets(buf, 4000, ci))
  278.       {
  279.     if (strncmp(buf, "@c ---", 6) == 0)
  280.     {
  281.     }
  282.     else if (strncmp(buf, "@node ", 6) == 0)
  283.     {
  284.       char name[1000];
  285.       char cat[1000];
  286.       name[0] = 0;
  287.       cat[0] = 0;
  288.       sscanf(buf, "%*s %[^,\n], %[^\n]", name, cat);
  289.       strcat(cat, " functions");
  290.       curnode = new Node(name, cat);
  291.       count_nodes ++;
  292.       curnode->filename = filename;
  293.  
  294.       nodes.add(curnode);
  295.       Node *catn = categories.find(cat);
  296.       catn->filename = filename;
  297.       catn->subnodes.add(curnode);
  298.     }
  299.     else
  300.     {
  301.       if (curnode)
  302.         curnode->add(buf);
  303.     }
  304.       }
  305.       fclose(ci);
  306.     }
  307.   }
  308. }
  309. //-----------------------------------------------------------------------------
  310.  
  311. main(int argc, char **argv)
  312. {
  313.   if (argc < 3)
  314.   {
  315.     fprintf(stderr, "Usage: mkdoc <directory> <output file>\n");
  316.     return 1;
  317.   }
  318.  
  319.   scan_directory(argv[1]);
  320.  
  321.   co = fopen(argv[2], "w");
  322.  
  323.   // Functional Categories
  324.   fprintf(co, "@c -----------------------------------------------------------------------------\n");
  325.   fprintf(co, "@node Functional Categories, Alphabetical List, Introduction, Top\n");
  326.   fprintf(co, "@unnumbered Functional Categories\n");
  327.   fprintf(co, "\n");
  328.   fprintf(co, "@menu\n");
  329.   categories.Traverse(cprint1);
  330.   fprintf(co, "@end menu\n");
  331.  
  332.   categories.Traverse(cprint2);
  333.  
  334.   // Alphabetical List
  335.   fprintf(co, "@c -----------------------------------------------------------------------------\n");
  336.   fprintf(co, "@node Alphabetical List, , Functional Categories, Top\n");
  337.   fprintf(co, "@unnumbered Alphabetical List\n");
  338.   fprintf(co, "\n");
  339.   fprintf(co, "@menu\n");
  340.   nodes.Traverse(nprint1);
  341.   fprintf(co, "@end menu\n");
  342.  
  343.   print_filenames = 1;
  344.  
  345.   nodes.Traverse(nprint2);
  346.   printf("%d nodes processed\n", count_nodes);
  347.   fclose(co);
  348.   return 0;
  349. }
  350.