home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / misc / adoc / source / libfun.c < prev    next >
C/C++ Source or Header  |  1995-04-13  |  21KB  |  925 lines

  1. /*                                                               -*- C -*-
  2.  *  LIBFUN.C
  3.  *
  4.  *  (c)Copyright 1995 by Tobias Ferber,  All Rights Reserved
  5.  *
  6.  *  This file is part of ADOC.
  7.  *
  8.  *  ADOC is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published
  10.  *  by the Free Software Foundation; either version 1 of the License,
  11.  *  or (at your option) any later version.
  12.  *
  13.  *  ADOC is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. /* $VER: $Id: libfun.c,v 1.13 1995/04/12 13:33:43 tf Exp $ */
  24.  
  25. #include <ctype.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <stdio.h>
  29.  
  30. #include "libfun.h"
  31.  
  32. /* strexpand.c */
  33. extern char *strexpand(char *, char **);
  34.  
  35. /* repair buggy realloc() implementation */
  36. #define my_realloc(ptr,size)  ( (ptr) ? realloc(ptr,size) : malloc(size) )
  37.  
  38. /* minimum #of chars added to funsec.data with each realloc() */
  39. #define SECMINSIZE 1024
  40.  
  41. /* list of sections in a function description */
  42.  
  43. typedef struct funsec
  44. {
  45.   struct funsec *succ, *pred;
  46.   char *name;          /* section title keyword */
  47.   struct {
  48.     char *text;        /* section text */
  49.     size_t len;        /* strlen(text) */
  50.     size_t size;       /* #of chars allocated for text */
  51.   } data;
  52.  
  53. } funsec_t;
  54.  
  55.  
  56. /* library function nodes */
  57.  
  58. typedef struct libfun
  59. {
  60.   struct libfun *succ, *pred;
  61.   char *name;          /* name of the function: `library/function' */
  62.   struct funsec *sec;  /* list of sections in the function description */
  63.  
  64. } libfun_t;
  65.  
  66.  
  67. /* variables */
  68.  
  69. static libfun_t *funlist  = (libfun_t *)0;  /* list of all functions */
  70. static libfun_t *funstack = (libfun_t *)0;  /* function on the stack */
  71. static libfun_t *thisfun  = (libfun_t *)0;  /* the current function (the one constructed last) */
  72. static funsec_t *thissec  = (funsec_t *)0;  /* the current section in the current function */
  73.  
  74. char *pushfun(void) { char *result= funstack ? funstack->name : (char *)0; funstack = thisfun;  return result; }
  75. char *popfun(void)  { char *result= funstack ? funstack->name : (char *)0; thisfun  = funstack; return result; }
  76.  
  77. /**/
  78.  
  79. static libfun_t *libfun_head(libfun_t *lf) { return (lf && lf->pred) ? libfun_head(lf->pred) : lf; }
  80. static libfun_t *libfun_tail(libfun_t *lf) { return (lf && lf->succ) ? libfun_tail(lf->succ) : lf; }
  81.  
  82. static funsec_t *funsec_head(funsec_t *fs) { return (fs && fs->pred) ? funsec_head(fs->pred) : fs; }
  83. static funsec_t *funsec_tail(funsec_t *fs) { return (fs && fs->succ) ? funsec_tail(fs->succ) : fs; }
  84.  
  85. /****** libfun/newfun ********************************************************
  86. *
  87. *   NAME
  88. *       newfun -- Begin a new function
  89. *
  90. *   SYNOPSIS
  91. *       error= newfun(fun);
  92. *
  93. *       int funindent(char *fun);
  94. *
  95. *   FUNCTION
  96. *       This function adds the function `fun'.  All sections added via
  97. *       newsec() will be made sections of this function.
  98. *
  99. *   INPUTS
  100. *       fun           - The name of the function to add.
  101. *                       (should be of the form "library/function")
  102. *
  103. *   RESULT
  104. *       error         - either 0 on success or !=0 in case of an error
  105. *
  106. *   SEE ALSO
  107. *       newsec(), funfree()
  108. *
  109. ******************************************************************************
  110. *
  111. */
  112.  
  113. static libfun_t *libfun_new(char *fun)
  114. {
  115.   libfun_t *lf= (libfun_t *)0;
  116.  
  117.   if(fun)
  118.   {
  119.     lf= (libfun_t *)malloc( sizeof(libfun_t) );
  120.  
  121.     if(lf)
  122.     {
  123.       lf->name= strdup(fun);
  124.  
  125.       if(lf->name)
  126.       {
  127.         lf->succ =
  128.         lf->pred = (libfun_t *)0;
  129.         lf->sec  = (funsec_t *)0;
  130.       }
  131.       else
  132.       {
  133.         free(lf);
  134.         lf= (libfun_t *)0;
  135.       }
  136.     }
  137.   }
  138.  
  139.   return lf;
  140. }
  141.  
  142. /**/
  143.  
  144. int newfun(char *fun)
  145. {
  146.   libfun_t *new= libfun_new(fun);
  147.  
  148.   if(new)
  149.   {
  150.     libfun_t *lf= libfun_tail(funlist);
  151.  
  152.     if(lf)
  153.     {
  154.       lf->succ= new;
  155.       new->pred= lf;
  156.     }
  157.     else funlist= new;
  158.   }
  159.  
  160.   thisfun= new;
  161.   thissec= new->sec;
  162.  
  163.   return new ? 0:1;
  164. }
  165.  
  166. /****** libfun/funsort *******************************************************
  167. *
  168. *   NAME
  169. *       funsort -- Sort all functions defined via newfun()
  170. *
  171. *   SYNOPSIS
  172. *       funsort();
  173. *
  174. *       void funsort(void);
  175. *
  176. *   FUNCTION
  177. *       Here we sort all functions defined via newfun() alphabetically.
  178. *
  179. *   INPUTS
  180. *       none
  181. *
  182. *   RESULT
  183. *       none
  184. *
  185. *   SEE ALSO
  186. *       newfun(), funfree()
  187. *
  188. ******************************************************************************
  189. *
  190. */
  191.  
  192. static int funbubble(libfun_t *a)
  193. {
  194.   int result= 0;
  195.  
  196.   /* perform a recursive bubble-sort on `a' and it's successors
  197.      return the #of bubbles */
  198.  
  199.   if(a && a->succ)
  200.   {
  201.     libfun_t *b= a->succ;
  202.  
  203.     if( strcmp(a->name, b->name) > 0 )
  204.     {
  205.       if( (b->pred= a->pred) )
  206.         b->pred->succ= b;
  207.  
  208.       if( (a->succ= b->succ) )
  209.         a->succ->pred= a;
  210.  
  211.       b->succ= a;
  212.       a->pred= b;
  213.  
  214.       ++result;
  215.     }
  216.  
  217.     result += funbubble(b);
  218.   }
  219.  
  220.   return result;
  221. }
  222.  
  223. /**/
  224.  
  225. void funsort(void)
  226. {
  227.   /* as long as there are bubbles... */
  228.   while( funbubble(libfun_head(funlist)) );
  229.  
  230.   /* sorting might have made another libfun_t the head of funlist */
  231.   funlist= libfun_head(funlist);
  232.  
  233.   for(thisfun= funlist; thisfun; thisfun= thisfun->succ)
  234.   {
  235.     /* make sure that thisfun->sec is the head of the sections */
  236.     thisfun->sec= funsec_head(thisfun->sec);
  237.   }
  238.  
  239.   thisfun= (libfun_t *)0;
  240.   thissec= (funsec_t *)0;
  241. }
  242.  
  243.  
  244. /****** libfun/funexpand *****************************************************
  245. *
  246. *   NAME
  247. *       funexpand -- Expand macros in all function bodies (unused)
  248. *
  249. *   SYNOPSIS
  250. *       error= funexpand(macros);
  251. *
  252. *       int funexpand(char **macros);
  253. *
  254. *   FUNCTION
  255. *       This function performs a strexpand() on all body text sections of all
  256. *       functions.
  257. *
  258. *   INPUTS
  259. *       macros        - the expansion table for strexpand()
  260. *
  261. *   RESULT
  262. *       error         - either 0 on success or !=0 in case of an error
  263. *
  264. *   SEE ALSO
  265. *       strexpand()
  266. *
  267. ******************************************************************************
  268. *
  269. */
  270.  
  271. int funexpand(char **macros)
  272. {
  273.   int err= 0;
  274.  
  275.   libfun_t *lf;
  276.   funsec_t *fs;
  277.  
  278.   for(lf= libfun_head(funlist); lf && (err==0); lf= lf->succ)
  279.   {
  280.     for(fs= funsec_head(lf->sec); fs && (err==0); fs= fs->succ)
  281.     {
  282.       if( fs->data.text )
  283.       {
  284.         char *x= strexpand(fs->data.text, macros);
  285.  
  286.         if(x)
  287.         {
  288.           free(fs->data.text);
  289.           fs->data.text= x;
  290.         }
  291.         else err= 1;
  292.       }
  293.     }
  294.   }
  295.  
  296.   return err;
  297. }
  298.  
  299.  
  300. /****** libfun/funindent *****************************************************
  301. *
  302. *   NAME
  303. *       funindent -- Perform an indentation correction on all functions
  304. *
  305. *   SYNOPSIS
  306. *       error= funindent(indent, tabsize);
  307. *
  308. *       int funindent(int indent, int tabsize);
  309. *
  310. *   FUNCTION
  311. *       This function performs a global rework on all functions defined via
  312. *       newfun().  The first thing this function does is converting tabs in
  313. *       all body text lines into spaces.  Then the indentation of body text
  314. *       lines in all functions is then resized to `indent' spaces.
  315. *       The indentation is minimized if `indent' is 0.   The `tabsize' is
  316. *       needed to compute the minimum indentation of a body text, i.e. the
  317. *       maximum width of a columnar block beginning at column 1 which cuts
  318. *       leading white space without hurting any text.
  319. *
  320. *   INPUTS
  321. *       indent        - The number of spaces used for the new indentation
  322. *                       of all body text lines
  323. *       tabsize       - The number of columns between two tab stops
  324. *
  325. *   RESULT
  326. *       error         - either 0 on success or !=0 in case of an error
  327. *
  328. *   SEE ALSO
  329. *
  330. ******************************************************************************
  331. *
  332. */
  333.  
  334. int funindent(int indent, int tabsize)
  335. {
  336.   int err= 0;
  337.  
  338.   libfun_t *lf;
  339.   funsec_t *fs;
  340.  
  341.   for(lf= libfun_head(funlist); lf && (err==0); lf= lf->succ)
  342.   {
  343.     for(fs= funsec_head(lf->sec); fs && (err==0); fs= fs->succ)
  344.     {
  345.       char *s= fs->data.text;
  346.  
  347. /*printf("%s: %s\n",lf->name,fs->name);*/
  348.  
  349.       if(s && *s)
  350.       {
  351.         int num_lines = 1; /* the number of lines in the body text  */
  352.         int num_tabs  = 0; /* number of tabs used in the body text  */
  353.         int i, k;          /* indentation counter                   */
  354.         int i_min= -1;     /* minimum indentation of this body text */
  355.  
  356.         /* compute the minimum indentation `i_min' in `s' */
  357.  
  358.         while(*s)
  359.         {
  360.           /* get the indentation `i' of the current line */
  361.           for(i=0; *s==' ' || *s=='\t'; s++) {
  362.             if(*s=='\t') i+= tabsize, i-= (i%tabsize), num_tabs++;
  363.             else i++;
  364.           }
  365.  
  366.           if( i>0 && (i<i_min || i_min<0) )
  367.             i_min= i;
  368.  
  369.           for(;*s && *s!='\n';s++)
  370.             if(*s=='\t') ++num_tabs;
  371.  
  372.           while(*s=='\n')
  373.             ++s, ++num_lines;
  374.         }
  375.  
  376.         if(i_min > 1)
  377.         {
  378.           /* allocate a new string buffer for the indented fs->data.text */
  379.           char *x= (char *)malloc( (size_t)(strlen(s= fs->data.text) + num_lines*indent + num_tabs*tabsize + 1) );
  380.  
  381.           if(x)
  382.           {
  383.             char *t= x;
  384.  
  385.             while(*s)
  386.             {
  387.               /* get the indentation of the current line */
  388.               for(i=0; *s==' ' || *s=='\t'; s++) {
  389.                 if(*s=='\t') i+= tabsize, i-= (i%tabsize);
  390.                 else i++;
  391.               }
  392.  
  393.               if( *s && (*s!='\n') )
  394.               {
  395.                 /* cut the columnar block & add the new indentation */
  396.                 for(k= i - i_min + indent; k>0; k--)
  397.                   *t++= ' ';
  398.  
  399.                 /* `i' still holds the indentation of the old body text line.
  400.                    We need this value to expand tabs as if we would still
  401.                    have the old indentation */
  402.  
  403.                 for(; *s && *s!='\n'; s++)
  404.                 {
  405.                   if(*s=='\t')
  406.                   {
  407.                     /* DICE (Amiga) compiles the following line wrong! */
  408.                     /*do { *t++= ' '; } while( (++i) % tabsize );*/
  409.                     do { *t++= ' '; i++; } while( (i % tabsize) );
  410.                   }
  411.                   else i++, *t++= *s;
  412.                 }
  413.               }
  414.  
  415.               while(*s=='\n')
  416.                 *t++= *s++;
  417.             }
  418.             *t= '\0';
  419.  
  420.             free(fs->data.text);
  421.             fs->data.text= x;
  422.           }
  423.           else err= __LINE__;
  424.         }
  425.       }
  426.     }
  427.   }
  428.  
  429.   return err;
  430. }
  431.  
  432. /****** libfun/newsec ********************************************************
  433. *
  434. *   NAME
  435. *       newsec -- Add a new heading to the current function description
  436. *
  437. *   SYNOPSIS
  438. *       error= newsec(title);
  439. *
  440. *       int newsec(char *title);
  441. *
  442. *   FUNCTION
  443. *       This function adds a new section heading `title' to the current
  444. *       function description which began with the last newfun() call.
  445. *       The following calls of addtext() will add the text to this new
  446. *       section.
  447. *
  448. *   INPUTS
  449. *       title         - The section heading keyword
  450. *
  451. *   RESULT
  452. *       error         - either 0 on success or !=0 in case of an error
  453. *
  454. *   SEE ALSO
  455. *       newfun(), addtext()
  456. *
  457. ******************************************************************************
  458. *
  459. */
  460.  
  461. static funsec_t *funsec_new(char *title)
  462. {
  463.   funsec_t *fs= (funsec_t *)malloc( sizeof(funsec_t) );
  464.  
  465.   if(fs)
  466.   {
  467.     fs->name= (title) ? strdup(title) : (char *)0;
  468.  
  469.     if(title && !fs->name)
  470.     {
  471.       free(fs);
  472.       fs= (funsec_t *)0;
  473.     }
  474.  
  475.     else
  476.     {
  477.       fs->succ =
  478.       fs->pred = (funsec_t *)0;
  479.  
  480.       fs->data.text = (char *)0;
  481.       fs->data.len  =
  482.       fs->data.size = 0;
  483.     }
  484.   }
  485.  
  486.   return fs;
  487. }
  488.  
  489. /**/
  490.  
  491. int newsec(char *title)
  492. {
  493.   int err= 0;
  494.  
  495.   if(thisfun)
  496.   {
  497.     funsec_t *new= funsec_new(title);
  498.  
  499.     if(new)
  500.     {
  501.       funsec_t *fs= funsec_tail(thisfun->sec);
  502.  
  503.       if(fs)
  504.       {
  505.         fs->succ= new;
  506.         new->pred= fs;
  507.       }
  508.       else thisfun->sec= new;
  509.     }
  510.     else err= 2;
  511.  
  512.     thissec= new;
  513.   }
  514.   else err= 1;
  515.  
  516.   return err;
  517. }
  518.  
  519. /****** libfun/addtext *******************************************************
  520. *
  521. *   NAME
  522. *       addtext -- Add a new line of text to the current function description
  523. *
  524. *   SYNOPSIS
  525. *       error= addtext(text);
  526. *
  527. *       int funindent(char *text);
  528. *
  529. *   FUNCTION
  530. *       This function dynamically adds a new line of text to the current
  531. *       section in the current function description.  There does not need
  532. *       to be a trailing newline `\n' at the end of `text'.
  533. *
  534. *   INPUTS
  535. *       text          - The string to add to the description
  536. *
  537. *   RESULT
  538. *       error         - either 0 on success or !=0 in case of an error
  539. *
  540. *   NOTES
  541. *       Body text can only be added to a section.  There must be at least
  542. *       one newsec() following newfun() before this function can add body
  543. *       text lines.
  544. *
  545. *   SEE ALSO
  546. *       newsec(), funfree()
  547. *
  548. ******************************************************************************
  549. *
  550. */
  551.  
  552. int addtext(char *text)
  553. {
  554.   int err= 0;
  555.  
  556.   if(thissec)
  557.   {
  558.     if(text)
  559.     {
  560.       /* get the minimum needed size of the text block */
  561.       size_t len= thissec->data.len + 1 + strlen(text) + 1;  /* '\n' + '\0' */
  562.  
  563.       /* see if we have enough room for '\n' and text */
  564.       if(len >= thissec->data.size)
  565.       {
  566.         /* resize the text buffer to the needed size + SECMINSIZE chars */
  567.         char *old= thissec->data.text;
  568.         char *new= (char *)my_realloc(old, (SECMINSIZE + len) * sizeof(char) );
  569.  
  570.         if(new)
  571.         {
  572.           thissec->data.text = new;
  573.           thissec->data.size = SECMINSIZE + len;
  574.  
  575.           if(!old)
  576.             *new= '\0';
  577.         }
  578.         else /* !new */
  579.         {
  580.           free(thissec->data.text);
  581.           thissec->data.text = (char *)0;
  582.           thissec->data.len  =
  583.           thissec->data.size = 0;
  584.           err= 1;
  585.         }
  586.       }
  587.  
  588.       /* append the new `text' portion to the section text */
  589.       if(thissec->data.text)
  590.       {
  591.         if(*thissec->data.text)
  592.           strcat(thissec->data.text,"\n");
  593.  
  594.         if(*text)
  595.           strcat(thissec->data.text,text);
  596.  
  597.         thissec->data.len= strlen(thissec->data.text);
  598.       }
  599.  
  600.     }
  601.     /* else: no error */
  602.   }
  603.   else err= -1;
  604.  
  605.   return err;
  606. }
  607.  
  608.  
  609. /****** libfun/getfun ********************************************************
  610. *
  611. *   NAME
  612. *       getfun -- Get a function by name
  613. *
  614. *   SYNOPSIS
  615. *       fun= getfun(name)
  616. *
  617. *       char *getfun(char *name);
  618. *
  619. *   FUNCTION
  620. *       This function searches the list of function descriptions for
  621. *       a function `name' and returns a pointer `fun' to the name of the
  622. *       function or a (char *)0 if there is no such function `name'.
  623. *
  624. *   INPUTS
  625. *       name          - The name of the function to look for
  626. *
  627. *   RESULT
  628. *       fun           - The real name of the function `name' or (char *)0
  629. *                       if no function `name' was found.
  630. *
  631. *   SEE ALSO
  632. *       newfun(), getsec()
  633. *
  634. ******************************************************************************
  635. *
  636. */
  637.  
  638. char *getfun(char *name)
  639. {
  640.   libfun_t *lf= (libfun_t *)0;
  641.  
  642.   if(name)
  643.   {
  644.     for(lf= libfun_head(funlist); (lf && strcmp(lf->name, name)); lf= lf->succ)
  645.       ;
  646.   }
  647.   else lf= thisfun;
  648.  
  649.   return lf ? lf->name : (char *)0;
  650. }
  651.  
  652.  
  653. /****** libfun/getsec ********************************************************
  654. *
  655. *   NAME
  656. *       getsec -- Get a section text via section heading
  657. *
  658. *   SYNOPSIS
  659. *       text= getsec(heading)
  660. *
  661. *       char *getsec(char *heading);
  662. *
  663. *   FUNCTION
  664. *       This function searches for the section `heading' in the function 
  665. *       description of the current function.  If this section exists then
  666. *       the corresponding section text is returned.
  667. *
  668. *   INPUTS
  669. *       heading       - The section title keyword to look for
  670. *
  671. *   RESULT
  672. *       text          - The section text of that section or (char *)0 if
  673. *                       there is no such section in the description of the
  674. *                       current function.
  675. *
  676. *   SEE ALSO
  677. *       newsec(), getfun()
  678. *
  679. ******************************************************************************
  680. *
  681. */
  682.  
  683. char *getsec(char *name)
  684. {
  685.   funsec_t *fs= (funsec_t *)0;
  686.  
  687.   if(name)
  688.   {
  689.     if(thisfun)
  690.     {
  691.       for(fs= funsec_head(thisfun->sec); (fs && strcmp(fs->name, name)); fs= fs->succ)
  692.         ;
  693.     }
  694.   }
  695.   else fs= thissec;
  696.  
  697.   return fs ? fs->data.text : (char *)0;
  698. }
  699.  
  700.  
  701. /****** libfun/islib **********************************************************
  702. *
  703. *   NAME
  704. *       islib -- Find a library in the list of functions
  705. *
  706. *   SYNOPSIS
  707. *       gotit= islib(name)
  708. *
  709. *       int islib(char *name);
  710. *
  711. *   FUNCTION
  712. *       Scan the list of functions for a function which begins with `name' 
  713. *       and has a `/' immediately following `name'.
  714. *
  715. *   INPUTS
  716. *       name           - The name of the library (without a trailing `/')
  717. *
  718. *   RESULT
  719. *       gotit          - 1 if there is at least one function `name/...'
  720. *                        0 otherwise.
  721. *
  722. ******************************************************************************
  723. *
  724. */
  725.  
  726. int islib(char *name)
  727. {
  728.   libfun_t *lf= (libfun_t *)0;
  729.  
  730.   if(name)
  731.   {
  732.     size_t l= strlen(name);
  733.                
  734.     for(lf= libfun_head(funlist); (lf && strncmp(lf->name, name, l)); lf= lf->succ)
  735.       ;
  736.     if(lf && lf->name && (lf->name)[l]!='/')
  737.       lf= (libfun_t *)0;
  738.   }
  739.  
  740.   return lf ? 1:0;
  741. }
  742.  
  743.  
  744. /****** libfun/stepfun *******************************************************
  745. *
  746. *   NAME
  747. *       stepfun -- Move the current function pointer
  748. *
  749. *   SYNOPSIS
  750. *       fun= stepfun(trigger);
  751. *
  752. *       char *stepfun(int trigger);
  753. *
  754. *   FUNCTION
  755. *       This function moves the current function pointer according to the
  756. *       `trigger' value.
  757. *
  758. *   INPUTS
  759. *       trigger       - < 0 moves back `-trigger' functions
  760. *                       = 0 moves to the first function
  761. *                       > 0 moves forward `trigger' functions
  762. *
  763. *   RESULT
  764. *       fun           - The name of the function or (char *)0
  765. *
  766. *   SEE ALSO
  767. *       stepsec()
  768. *
  769. ******************************************************************************
  770. *
  771. */
  772.  
  773. char *stepfun(int trigger)
  774. {
  775.   char *result= (char *)0;
  776.  
  777.   if(trigger > 0)
  778.   {
  779.     for(; thisfun && (trigger > 0); trigger--)
  780.       thisfun= thisfun->succ;
  781.   }
  782.   else if(trigger < 0)
  783.   {
  784.     for(; thisfun && (trigger < 0); trigger++)
  785.       thisfun= thisfun->pred;
  786.   }
  787.   else /* trigger == 0 */
  788.     thisfun= libfun_head(funlist);
  789.  
  790.   if(thisfun)
  791.   {
  792.     thissec= funsec_head(thisfun->sec);
  793.     result= thisfun->name;
  794.   }
  795.   else thissec= (funsec_t *)0;
  796.  
  797.   return result;
  798. }
  799.  
  800.  
  801. /****** libfun/stepsec *******************************************************
  802. *
  803. *   NAME
  804. *       stepsec -- Move the current section pointer
  805. *
  806. *   SYNOPSIS
  807. *       sec= stepsec(trigger);
  808. *
  809. *       char *stepsec(int trigger);
  810. *
  811. *   FUNCTION
  812. *       This function moves the current section pointer according to the
  813. *       `trigger' value.
  814. *
  815. *   INPUTS
  816. *       trigger       - < 0 moves back `-trigger' sections
  817. *                       = 0 moves to the first section
  818. *                       > 0 moves forward `trigger' sections
  819. *
  820. *   RESULT
  821. *       sec           - The name of the section or (char *)0
  822. *
  823. *   SEE ALSO
  824. *       stepfun()
  825. *
  826. ******************************************************************************
  827. *
  828. */
  829.  
  830. char *stepsec(int trigger)
  831. {
  832.   char *result= (char *)0;
  833.  
  834.   if(trigger > 0)
  835.   {
  836.     for(; thissec && (trigger > 0); trigger--)
  837.       thissec= thissec->succ;
  838.   }
  839.   else if(trigger < 0)
  840.   {
  841.     for(; thissec && (trigger < 0); trigger++)
  842.       thissec= thissec->pred;
  843.   }
  844.   else /* trigger == 0 */
  845.   {
  846.     if(thisfun)
  847.       thissec= funsec_head(thisfun->sec);
  848.  
  849.     else
  850.       thissec= (funsec_t *)0;
  851.   }
  852.  
  853.   if(thissec)
  854.     result= thissec->name;
  855.  
  856.   return result;
  857. }
  858.  
  859.  
  860. /****** libfun/funfree *******************************************************
  861. *
  862. *   NAME
  863. *       funfree -- Dispose all function descriptions
  864. *
  865. *   SYNOPSIS
  866. *       funfree();
  867. *
  868. *       void funfree(void);
  869. *
  870. *   FUNCTION
  871. *       This function disposes all function descriptions including all their
  872. *       sections.
  873. *
  874. *   INPUTS
  875. *       none
  876. *
  877. *   RESULT
  878. *       none
  879. *
  880. *   SEE ALSO
  881. *       newfun(), newsec(), addtext()
  882. *
  883. ******************************************************************************
  884. *
  885. */
  886.  
  887. static funsec_t *funsec_dispose(funsec_t *fs)
  888. {
  889.   if(fs)
  890.   {
  891.     fs->succ= funsec_dispose(fs->succ);
  892.  
  893.     if(fs->name)
  894.       free(fs->name);
  895.  
  896.     if(fs->data.text)
  897.       free(fs->data.text);
  898.   }
  899.  
  900.   return (funsec_t *)0;
  901. }
  902.  
  903. static libfun_t *libfun_dispose(libfun_t *lf)
  904. {
  905.   if(lf)
  906.   {
  907.     lf->succ= libfun_dispose(lf->succ);
  908.  
  909.     if(lf->name)
  910.       free(lf->name);
  911.  
  912.     lf->sec= funsec_dispose( funsec_head(lf->sec) );
  913.  
  914.     free(lf);
  915.   }
  916.  
  917.   return (libfun_t *)0;
  918. }
  919.  
  920. void funfree(void)
  921. {
  922.   funlist= thisfun= libfun_dispose( libfun_head(funlist) );
  923.   thissec= (funsec_t *)0;
  924. }
  925.