home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / refs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-04  |  16.4 KB  |  772 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: refs.c 1.3 1994/09/09 12:31:30 digulla Exp digulla $
  5.  
  6.     DESCRIPTION
  7.     [v]ref [string]
  8.     Bringup a cross reference editor window.  The file [refpath]dme.refs
  9.     and dme.refs in the current directory are searched for the reference.
  10.     If found, the file specified is searched and the segment specified
  11.     loaded as a new file in a new (read-only) window.
  12.  
  13.     [v]ctags [string]
  14.     Bringup a cross definition editor window. The file [refpath]tags
  15.     and tags in the current directory are searched for the reference.
  16.     If found, the file specified is shown in a window, and the line
  17.     specified is visited.
  18.  
  19.     HISTORY
  20.     25. Nov 1992    ada created
  21.      3. Mar   93    null added Berkeley-Fix
  22.      1. Jan   94    null added autoinits
  23.      $Log: refs.c $
  24.  * Revision 1.3  1994/09/09  12:31:30  digulla
  25.  * added new style Prototypes, DEFCMD and DEFHELP
  26.  *
  27.  * Revision 1.2  1994/08/19  14:06:41  digulla
  28.  * removed dead assignments
  29.  *
  30.  * Revision 1.1  1994/08/09  13:52:48  digulla
  31.  * Initial revision
  32.  *
  33.  * Revision 1.1  1994/08/09  13:49:24  digulla
  34.  * Initial revision
  35.  *
  36.  
  37. ******************************************************************************/
  38.  
  39. /**************************************
  40.         Includes
  41. **************************************/
  42. #include "defs.h"
  43.  
  44. #define LINES_TO_BREAKCHECK 20
  45.  
  46. /**************************************
  47.         Globale Variable
  48. **************************************/
  49. /* Prototype LIST PBase; */
  50.  
  51. static struct MinList _PBase;
  52. LIST    *PBase      = NULL;           /*  special XDME paths    */
  53. APTR     PathRoot = NULL;
  54.  
  55. /**************************************
  56.       Interne Defines & Strukturen
  57. **************************************/
  58. typedef struct _PEN
  59. {
  60.     NODE    Node;
  61.     char    path[1];
  62. } PEN;
  63.  
  64.  
  65. /**************************************
  66.         Interne Variable
  67. **************************************/
  68.  
  69.  
  70. /**************************************
  71.        Interne Prototypes
  72. **************************************/
  73. static int strnspacecmp (const char * str1, const char * str2, int max);
  74. static int searchref (char * file, char * find, char ** psstr, char ** pfile, long * plines, char **pestr);
  75. static int dirpart (char * str);
  76.  
  77. /* Prototype void path_init (void); */
  78.  
  79. DEFAUTOINIT( path_init )
  80. {
  81. //puts (__FILE__);
  82.  
  83. #if 0
  84.     PBase = (LIST *)&_PBase:
  85.     NewList (PBase);
  86. #else
  87.     PathRoot = HL_SystemList("*RefPaths*");
  88.     PBase    = (void *)HL_LockSubs(PathRoot);
  89.     HL_UnlockSubs(PathRoot);
  90. #endif
  91.  
  92.     av[1] = "";
  93.     do_addpath();
  94. } /* path_init */
  95.  
  96.  
  97.  
  98. /*
  99.  *  Special XDME paths for REF and CTAGS
  100.  */
  101.  
  102. /*DEFHELP #cmd prefs,refs ADDPATH path - Add the specified symbolic directory to XDME's special search path (see REF and CTAGS). */
  103.  
  104. DEFUSERCMD("addpath", 1, CF_VWM|CF_ICO, void, do_addpath, (void),)
  105. {
  106.     PEN * pen;
  107.     //WORD  len = strlen (av[1]);
  108.  
  109.     for (pen = (PEN *)GetHead(PBase); pen; pen=(PEN *)GetSucc((struct Node *)pen))
  110.     {
  111.     if (stricmp (av[1], pen->Node.ln_Name) == 0)
  112.         return;
  113.     }
  114.  
  115. #if 1
  116.     HL_New (av[1], PathRoot, HLF_SYSNODE);
  117. #else
  118.     if (pen = malloc (sizeof (PEN) + len))
  119.     {
  120.     pen->Node.ln_Name = pen->path;
  121.     strcpy (pen->Node.ln_Name, av[1]);
  122.     AddTail (PBase, (NODE *) pen);
  123.     }
  124. #endif
  125.  
  126. } /* do_addpath */
  127.  
  128.  
  129. /*DEFHELP #cmd prefs,refs REMPATH path - Remove a directorys from XDME's special path. */
  130.  
  131. DEFUSERCMD("rempath", 1, CF_VWM|CF_COK|CF_ICO, void, do_rempath, (void),)
  132. {
  133.     PEN * pen;
  134.  
  135.     for (pen = (PEN *)GetHead(PBase); pen; pen = (PEN *)GetSucc((struct Node *)pen))
  136.     {
  137.     if (!stricmp (av[1], pen->Node.ln_Name))
  138.     {
  139. #if 1
  140.         HL_Dispose((void *)pen);
  141. #else
  142.         Remove ((NODE *) pen);
  143.         free (pen);
  144. #endif
  145.         break;
  146.     }
  147.     }
  148. } /* do_rempath */
  149.  
  150.  
  151.  
  152. static int strnspacecmp (const char * str1, const char * str2, int max)
  153. {
  154.     while (*str1 && max)
  155.     {
  156.     if (isspace (*str1))
  157.     {
  158.         if (!isspace (*str2))
  159.         break;
  160.  
  161.         while (isspace (*str1) && max) { str1 ++; max --; }
  162.  
  163.         if (!max)
  164.         break;
  165.  
  166.         while (isspace (*str2)) str2 ++;
  167.     }
  168.     else
  169.     {
  170.         if (*str1 != *str2)
  171.         break;
  172.  
  173.         str1 ++;
  174.         str2 ++;
  175.         max --;
  176.     }
  177.     }
  178.  
  179.     return (max ? *str1 - *str2 : 0);
  180. } /* strnspacecmp */
  181.  
  182.  
  183.  
  184. /*DEFHELP #cmd refs REFCTAGS - The utimate command for hopping through source. First, we try CTAGS and if we don't find anything, we check REF. */
  185. /*DEFHELP #cmd refs VREFCTAGS name - like REFCTAGS, but looks for @{B}name@{UB} */
  186.  
  187. DEFUSERCMD("vrefctags", 1, CF_VWM|CF_ICO, void, do_refctags, (void),;)
  188. DEFUSERCMD("refctags",  0, CF_VWM|CF_ICO, void, do_refctags, (void),)
  189. {
  190.     char *av_bak[2];
  191.     BOOL requester;
  192.     BOOL title;
  193.  
  194.     av_bak[0] = av[0];
  195.     av_bak[1] = av[1];
  196.  
  197.     requester = GETF_NOREQUEST(Ep);
  198.     title     = GETF_SHOWTITLE(Ep);
  199.  
  200.     SETF_NOREQUEST(Ep,TRUE);
  201.     SETF_SHOWTITLE(Ep,FALSE);
  202.  
  203.     do_ctags ();
  204.  
  205.     if (GETF_ABORTCOMMAND(Ep)) {
  206.     SETF_ABORTCOMMAND(Ep,0);
  207.     do_refs ();
  208.     } /* if */
  209.  
  210.     SETF_NOREQUEST(Ep,requester);
  211.     SETF_SHOWTITLE(Ep,title);
  212.  
  213.     if (GETF_ABORTCOMMAND(Ep)) {
  214.     char *str = ((av_bak[1] != NULL) ? (char *)av_bak[1] : current_word ());
  215.     if (!str[0])
  216. DEFMESSAGE( _REF_no_searchstring_defined, "%s:\nNo searchstring defined!\n" )
  217.         error (_REF_no_searchstring_defined, av_bak[0]);
  218.     else
  219.     {
  220.         char buffer[256];
  221.  
  222.         strcpy (buffer, str);
  223.  
  224. DEFMESSAGE( _REF_cant_find_anything_about, "%s:\nCannot find anything about\n`%s'." )
  225.         error (_REF_cant_find_anything_about, av_bak[0], buffer);
  226.     }
  227.     } /* if */
  228. } /* do_refctags */
  229.  
  230.  
  231. /*
  232.  *  Implement ctags
  233.  */
  234.  
  235. /*DEFHELP #cmd refs CTAGS - search for the tag under the cursor (see below) */
  236. /*DEFHELP #cmd refs VCTAGS name - search for tag @{B}name@{UB} */
  237.  
  238. DEFUSERCMD("vctags", 1, CF_VWM, void, do_ctags, (void),;)
  239. DEFUSERCMD("ctags",  0, CF_VWM, void, do_ctags, (void),)
  240. {
  241.     char    str[MAXLINELEN];
  242.     char    path[128];
  243.     char    buf[300];
  244.     char    sbuf[128];
  245.     WORD    xlen;
  246.     WORD    slen;
  247.     /* WORD    dbaselen; unused var */
  248.     BPTR    oldlock = CurrentDir (Ep->dirlock);
  249.     ED      * ed;
  250.     LONG    lineno = -1;
  251.  
  252.     if (av[1] != NULL)
  253.     {
  254.     strcpy (str, av[1]);
  255.     }
  256.     else
  257.     {
  258.     strcpy (str, current_word ());
  259.     }
  260.  
  261.     xlen = strlen (str);
  262.     if (!str[0]) {
  263. DEFMESSAGE( _REF_no_searchstring_defined, "%s:\nNo searchstring defined!\n" )
  264.     error (_REF_no_searchstring_defined, av[0]);
  265.     return;
  266.     } /* if */
  267.  
  268.     if (!GETF_ICONMODE(Ep))
  269. DEFMESSAGE( _REF_search_tags, "search tags" )
  270.     title (_REF_search_tags);
  271.  
  272.     {
  273.     FILE * fi;
  274.     PEN  * pen;
  275.     WORD   j,
  276.            len;
  277. int bcnt = LINES_TO_BREAKCHECK;
  278.     /*
  279.      *  Note: pen not used first pass and set to list head, so next
  280.      *  pass it will be the first element.
  281.      *
  282.      *  Note2:  The file path depends on several factors.  (1) tags in
  283.      *        'current' directory, use path to name of current window.
  284.      *        (2) tags in directory in XDME special path, use special
  285.      *        path.  (3) tag entry is a full path name, override
  286.      *        previous directories.
  287.      */
  288.  
  289.     mountrequest (0);
  290.  
  291.     for (pen=(PEN *)GetHead(PBase); pen;
  292.                     pen=(PEN *)GetSucc((struct Node *)pen))
  293.     {
  294. if (GETF_ABORTCOMMAND(Ep)) break;
  295.  
  296.         strcpy (path, pen->Node.ln_Name);
  297.         AddPart (path, "tags", sizeof(path));
  298.  
  299.         if (fi = fopen (path, "r"))
  300.         {
  301.         mountrequest (1);
  302.  
  303.         while ((len = xefgets (fi, buf, 128)) >= 0)
  304.         {
  305. if (--bcnt == 0)
  306. {  /* check break every so so  */
  307.     bcnt = LINES_TO_BREAKCHECK;
  308.  
  309.     if (breakcheck ())
  310.     break;
  311. }
  312.             for (j = 0; buf[j] && buf[j] != ' '; ++j);
  313.  
  314.             if (j == 0 || buf[0] == '#')
  315.             continue;
  316.  
  317.             if (j == xlen && strncmp (str, buf, j) == 0)
  318.             {
  319.             while (buf[j] == ' ')
  320.                 ++j;
  321.  
  322.             /*
  323.              *  Extract the file name into str.  If the
  324.              *  filename does not contain an absolute path,
  325.              *  prepend it with such.
  326.              */
  327.             {
  328.                 char prep = 1;
  329.                 int i;
  330.  
  331.                 for (i = 0; buf[j] && buf[j] != ' '; ++i, ++j)
  332.                 {
  333.                 str[i] = buf[j];
  334.                 if (str[i] == ':')
  335.                     prep = 0;
  336.                 }
  337.  
  338.                 str[i] = 0;
  339.  
  340.                 if (prep)
  341.                 {
  342.                 char buf[256];
  343.  
  344.                 strcpy (buf, pen->Node.ln_Name);
  345.                 AddPart (buf, str, sizeof(buf));
  346.  
  347.                 strcpy (str, buf);
  348.                 }
  349.             }
  350.  
  351.             fclose (fi);                        /* PATCH_NULL [10 Mar 1993] : moved 2 lines up */
  352.  
  353.             /* BERKELEY FIX: I have found a format in CTags */
  354.             /*    <tag> <file> <linenumber>        */
  355.             /* which is supported now            */
  356.             while (isspace(buf[j])) ++j;          /* PATCH_NULL [10 Mar 1993] : added */
  357.  
  358.             if (is_number (buf+j))              /* PATCH_NULL [10 Mar 1993] : added */
  359.             {                    /* PATCH_NULL [10 Mar 1993] : added */
  360.                 lineno = atol (buf+j)-1;        /* PATCH_NULL [10 Mar 1993] : added */
  361.             }                    /* PATCH_NULL [10 Mar 1993] : added */
  362.             else                    /* PATCH_NULL [10 Mar 1993] : added */
  363.             {                    /* PATCH_NULL [10 Mar 1993] : added */
  364.                 while (buf[j] && buf[j] != '^') /*  SEARCH ARG */
  365.                 ++j;
  366.  
  367.  
  368.                 if (buf[j] != '^')
  369.                 {
  370. DEFMESSAGE( _REF_error_in_tagsfile, "ctags:\nError in tags-file" )
  371.                 error (_REF_error_in_tagsfile, av[0]);
  372.                 goto done;
  373.                 }
  374.  
  375.                 ++j;    /* Skip ^ */
  376.  
  377.                 /* UN*X FIX: Dme works for Aztec ctags, which has the format:   */
  378.                 /*        <tag>   <file>  /^<pattern>                 */
  379.                 /* However, ctags under UN*X has the following format:        */
  380.                 /*        <tag>   <file>  /^<pattern>[$]/                */
  381.                 /* We just ignore the '$' and '/' so that both foramts work     */
  382.                 /* Thomas Rolfs 27/3/91                        */
  383.  
  384.                 {
  385.                 int i = 0;
  386.  
  387.                 while (buf[j] && buf[j] != '^' && buf[j] != '$'
  388.                         && buf[j] != '/' && buf[j] != '?')
  389.                 {
  390.                     sbuf[i++] = buf[j++];
  391.                 }
  392.  
  393.                 sbuf[i] = 0;
  394.                 }
  395.  
  396.                 /* End of fix.  */
  397.  
  398.                 slen = strlen (sbuf);
  399.             } /* if */                /* PATCH_NULL [10 Mar 1993] : added */
  400.  
  401.             if ((ed = finded (FilePart(str), 0)) == NULL) /* PATCH_NULL 20-07-94 added "FilePart" */
  402.             {
  403.                 strcpy (buf, "newwindow newfile `");
  404.                 strcat (buf, str);
  405.                 strcat (buf, "' viewmode on");
  406.                 do_command (buf);
  407.  
  408.                 /* remove path */
  409.                 strcpy (str, FilePart (str));
  410.  
  411.                 ed = finded (str, 0);
  412.             } else
  413.             {
  414.                 WindowToFront (ed->win);
  415.                 ActivateWindow (ed->win);
  416.             }
  417.  
  418.             if (ed == NULL)
  419.             {
  420. DEFMESSAGE( _REF_cant_load_file, "%s:\nunable to load file\n`%s'" )
  421.                 error (_REF_cant_load_file, av[0], str);
  422.                 goto done;
  423.             }
  424.  
  425.             switch_ed (ed);
  426.             text_cursor (0);
  427.  
  428.             if (lineno < 0)                                    /* PATCH_NULL [10 Mar 1993] : added */
  429.             {
  430.                 for (lineno = 0; lineno < ed->lines; ++lineno) /* PATCH_NULL [10 Mar 1993] : i -> lineno */
  431.                 {
  432.                 if (strnspacecmp (sbuf, ed->list[lineno], slen) == 0)
  433.                     break;
  434.                 }
  435.  
  436.                 if (lineno == ed->lines)
  437.                 {
  438.                 int i;
  439.  
  440. printf ("searching:\n");
  441. for (i=0; sbuf[i] && i<slen; i++)
  442. {
  443.     printf ("%02x", sbuf[i]);
  444.     if (i & 3 == 3)
  445.     printf (" ");
  446. }
  447. printf ("\n");
  448.                 }
  449.             }
  450.  
  451.             sprintf (buf, "first goto %ld", lineno + 1);
  452.             do_command (buf);
  453.             text_cursor (1);    /* turn cursor on */
  454.  
  455.             goto done;
  456.             }
  457.         }
  458.  
  459.         fclose (fi);
  460.  
  461.         mountrequest (0);
  462.         }
  463.     }
  464.  
  465. DEFMESSAGE( _REF_tag_not_found, "ctags:\ntag `%s'\nnot found" )
  466.     error (_REF_tag_not_found, str);
  467.  
  468.     mountrequest (1);
  469.     }
  470. done:
  471.     CurrentDir (oldlock);
  472. } /* do_ctags */
  473.  
  474.  
  475. /*
  476.  *  Implement references
  477.  */
  478.  
  479. /*DEFHELP #cmd refs REF - reference string under cursor (see below) */
  480. /*DEFHELP #cmd refs VREF name - reference @{B}name@{UB} */
  481.  
  482. DEFUSERCMD("vref", 1, CF_VWM|CF_ICO, void, do_refs, (void),;)
  483. DEFUSERCMD("ref",  0, CF_VWM|CF_ICO, void, do_refs, (void),)
  484. {
  485.     static char str[MAXLINELEN];
  486.     static char tmpfile[128];
  487.     static char path[128];
  488.     char      * srch;
  489.     char      * file;
  490.     char      * estr;
  491.     long    len;
  492.     int     bcnt = 10;
  493.     WORD    slen,
  494.         elen;
  495.     FILE      * fi,
  496.           * fj;
  497.     WORD    tmph,
  498.         tmpw;
  499.     BPTR    oldlock = CurrentDir (Ep->dirlock);
  500.  
  501.     if (av[1] != NULL)
  502.     {
  503.     strcpy (str, av[1]);
  504.     }
  505.     else
  506.     strcpy (str, current_word ());
  507.  
  508.     if (!str[0]) {
  509. DEFMESSAGE( _REF_no_searchstring_defined, "%s:\nNo searchstring defined!\n" )
  510.     error (_REF_no_searchstring_defined, av[0]);
  511.     return;
  512.     } /* if */
  513.  
  514.  
  515.     strcpy (tmpfile, "t:ref_");
  516.     strncat (tmpfile, str, sizeof (tmpfile) - 32);
  517.  
  518. DEFMESSAGE( _REF_search_refs, "search .refs" )
  519.     title (_REF_search_refs);
  520.  
  521.     {
  522.     PEN * pen;
  523.  
  524.     mountrequest (0);
  525.  
  526.     /* search all paths */
  527.     for (pen = (PEN *)GetHead(PBase); pen; pen=(PEN *)GetSucc(pen))
  528.     {
  529. if (GETF_ABORTCOMMAND(Ep)) break;
  530.         strcpy (path, pen->Node.ln_Name);
  531.         AddPart (path, "dme.refs", sizeof (path));
  532.  
  533.         if (searchref (path, str, &srch, &file, &len, &estr))
  534.         {
  535.         mountrequest (1);
  536.         goto found;
  537.         }
  538.     }
  539.  
  540. DEFMESSAGE( _REF_reference_not_found, "refs:\nReference `%s'\nnot found" )
  541.     error (_REF_reference_not_found, str);
  542.     mountrequest (1);
  543.     goto done;
  544.     }
  545.  
  546. found:
  547. DEFMESSAGE( _REF_search_file, "search file" )
  548.     title (_REF_search_file);
  549.     slen = strlen (srch);
  550.  
  551.     if (estr)
  552.     elen = strlen (estr);
  553.  
  554.     fi = fopen (file, "r");
  555.  
  556.     if (fi == NULL)
  557.     {        /*  try using path prefix   */
  558.     strcpy (str, path);
  559.     strcpy (str + strlen (str) - 8, file);
  560.     fi = fopen (str, "r");
  561.     }
  562.  
  563.     if (fi)
  564.     {
  565.     WORD  lenstr;
  566.  
  567.     if (srch[0] == '@' && srch[1] == '@')
  568.     {
  569.         fseek (fi, atoi (srch + 2), 0);
  570.         if ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0)
  571.         goto autoseek;
  572.     }
  573.  
  574.     while ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0)
  575.     {
  576.         if (strncmp (str, srch, slen) == 0)
  577.         {
  578. autoseek:
  579. DEFMESSAGE( _REF_load, "load.." )
  580.         title (_REF_load);
  581.         if (fj = fopen (tmpfile, "w"))
  582.         {
  583.             tmph = 0;
  584.             tmpw = 0;
  585.  
  586.             do
  587.             {
  588.             if (lenstr > tmpw)
  589.                 tmpw = strlen (str);
  590.  
  591.             tmph ++;
  592.  
  593.             fputs (str, fj);
  594.             fputc ('\n', fj);
  595.  
  596.             if (estr && strncmp (str, estr, elen) == 0)
  597.                 break;
  598.  
  599.             len --;
  600.             }
  601.  
  602.             while ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0 && len);
  603.  
  604.             fclose (fj);
  605.  
  606.             if (tmph > 10)
  607.             tmph = 10;
  608.             if (tmpw > 80)
  609.             tmpw = 80;
  610.  
  611.             sprintf (str, "openwindow +0+0+%d+%d newfile %s viewmode on", (tmpw << 3) + 24, (tmph << 3) + 24, tmpfile);
  612.             do_command (str);
  613.             text_cursor (1);    /* turn cursor on */
  614.             unlink (tmpfile);
  615.         } else
  616.         {
  617. DEFMESSAGE( _REF_cant_open_outfile, "%s:\nUnable to open\n`%s'\nfor write" )
  618.             error (_REF_cant_open_outfile, av[0], tmpfile);
  619.         }
  620.  
  621.         fclose (fi);
  622.         free (srch);
  623.         free (file);
  624.  
  625.         if (estr)
  626.             free (estr);
  627.  
  628.         goto done;
  629.         }
  630.         if (--bcnt == 0)
  631.         {  /* check break every so so  */
  632.         bcnt = LINES_TO_BREAKCHECK;
  633.  
  634.         if (breakcheck ())
  635.             break;
  636.         }
  637.     }
  638.     fclose (fi);
  639.  
  640. DEFMESSAGE( _REF_search_for_failed, "%s:\nSearch for `%s'\nfailed" )
  641.     error (_REF_search_for_failed, av[0], str);
  642.     } else
  643.     {
  644. DEFMESSAGE( _REF_cant_open_subdoc, "refs:\nUnable to open\nsub document" )
  645.     error (_REF_cant_open_subdoc, av[0]);
  646.     }
  647.  
  648.     free (srch);
  649.     free (file);
  650.  
  651.     if (estr)
  652.     free (estr);
  653. done:
  654.     CurrentDir (oldlock);
  655. } /* do_refs */
  656.  
  657.  
  658. /*
  659.  *  Reference file format:
  660.  *
  661.  *  `key' `lines' `file' `searchstring'
  662.  *
  663.  *  where `lines' can be a string instead ... like a read-until, otherwise
  664.  *  the number of lines to read from the reference.
  665.  */
  666.  
  667. static int searchref (char * file, char * find, char ** psstr, char ** pfile, long * plines, char **pestr)
  668. {
  669.     FILE  * fi;
  670.     char    buf[MAXLINELEN];
  671.     char  * ptr,
  672.       * base;
  673.     char  * b1,
  674.       * b2,
  675.       * b3,
  676.       * b4;
  677.     char    quoted;
  678.  
  679.     /* WORD  findlen = strlen(find); TODO */
  680.  
  681.     if (fi = fopen (file, "r"))
  682.     {
  683.     while (xefgets (fi, (base = buf), MAXLINELEN) >= 0)
  684.     {
  685.         if (buf[0] == '#')
  686.         continue;
  687.  
  688.         ptr = breakout (&base, "ed, &b1);
  689.  
  690.         /* TODO if (ptr && *ptr && strncmp(ptr, find, findlen) == 0) */
  691.         if (ptr && *ptr && strcmp (ptr, find) == 0)
  692.         {
  693.         if (ptr = breakout (&base, "ed, &b2))
  694.         {
  695.             *pestr = NULL;
  696.             *plines = atoi (ptr);
  697.  
  698.             if (*plines == 0)
  699.             {
  700.             *pestr = (char *) malloc (strlen (ptr) + 1);
  701.             strcpy (*pestr, ptr);
  702.             }
  703.  
  704.             if (ptr = breakout (&base, "ed, &b3))
  705.             {
  706.             *pfile = (char *) malloc (strlen (ptr) + 1);
  707.             strcpy (*pfile, ptr);
  708.  
  709.             if (ptr = breakout (&base, "ed, &b4))
  710.             {
  711.                 *psstr = (char *) malloc (strlen (ptr) + 1);
  712.  
  713.                 strcpy (*psstr, ptr);
  714.                 fclose (fi);
  715.  
  716.                 if (b1)
  717.                 free (b1);
  718.                 if (b2)
  719.                 free (b2);
  720.                 if (b3)
  721.                 free (b3);
  722.                 if (b4)
  723.                 free (b4);
  724.  
  725.                 return (1);
  726.             }
  727.  
  728.             free (*pfile);
  729.  
  730.             if (b4)
  731.                 free (b4);
  732.             }
  733.  
  734.             if (pestr)
  735.             free (*pestr);
  736.             if (b3)
  737.             free (b3);
  738.         }
  739.  
  740.         if (b2)
  741.             free (b2);
  742.         }
  743.  
  744.         if (b1)
  745.         free (b1);
  746.     }
  747.  
  748.     fclose (fi);
  749.     }
  750.  
  751.     return (0);
  752. } /* searchref */
  753.  
  754.  
  755. static int dirpart (char * str)
  756. {
  757.     WORD    i;
  758.  
  759.     for (i = strlen (str) - 1; i >= 0; --i)
  760.     {
  761.     if (str[i] == '/' || str[i] == ':')
  762.         break;
  763.     }
  764.  
  765.     return (i + 1);
  766. } /* dirpart */
  767.  
  768.  
  769. /******************************************************************************
  770. *****  ENDE refs.c
  771. ******************************************************************************/
  772.