home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / xdme1820.lha / XDME / refs.c < prev    next >
C/C++ Source or Header  |  1993-03-09  |  11KB  |  628 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     refs.c
  5.  
  6.     DESCRIPTION
  7.     Bringup a cross reference editor window.  The file S:dme.refs and
  8.     dme.refs in the current directory are searched for the reference.
  9.     If found, the file specified is searched and the segment specified
  10.     loaded as a new file in a new window.
  11.  
  12.     NOTES
  13.  
  14.     BUGS
  15.  
  16.     TODO
  17.  
  18.     EXAMPLES
  19.  
  20.     SEE ALSO
  21.  
  22.     INDEX
  23.  
  24.     HISTORY
  25.     25. Nov 1992    ada created
  26.  
  27. ******************************************************************************/
  28.  
  29. /**************************************
  30.         Includes
  31. **************************************/
  32. #include "defs.h"
  33.  
  34.  
  35. /**************************************
  36.         Globale Variable
  37. **************************************/
  38. Prototype void do_addpath  (void);
  39. Prototype void do_rempath  (void);
  40. Prototype void do_refctags (void);
  41. Prototype void do_ctags    (void);
  42. Prototype void do_refs       (void);
  43. Prototype int searchref    (char *, char *, char **, char **, int *, char **);
  44. Prototype int dirpart       (char *);
  45.  
  46. Prototype LIST PBase;
  47.  
  48. LIST    PBase;            /*  special XDME paths     */
  49.  
  50.  
  51. /**************************************
  52.       Interne Defines & Strukturen
  53. **************************************/
  54. typedef struct _PEN
  55. {
  56.     NODE    Node;
  57.     char  * path;
  58. } PEN;
  59.  
  60.  
  61. /**************************************
  62.         Interne Variable
  63. **************************************/
  64.  
  65.  
  66. /**************************************
  67.        Interne Prototypes
  68. **************************************/
  69.  
  70.  
  71.  
  72. /*
  73.  *  Special XDME paths for REF and CTAGS
  74.  */
  75.  
  76. void do_addpath (void)
  77. {
  78.     PEN * pen;
  79.     short len = strlen (av[1]);
  80.  
  81.     for (pen = (PEN *)GetHead(&PBase); pen; pen=(PEN *)GetSucc((struct Node *)pen))
  82.     {
  83.     if (stricmp (av[1], pen->path) == 0)
  84.         return;
  85.     }
  86.  
  87.     if (pen = malloc (sizeof (PEN) + len + 2))
  88.     {
  89.     pen->path = (char *) (pen + 1);
  90.     strcpy (pen->path, av[1]);
  91.  
  92.     switch (pen->path[len - 1])
  93.     {
  94.         case ':':
  95.         case '/':
  96.         break;
  97.         default:
  98.         strcat (pen->path, "/");
  99.     }
  100.     }
  101.  
  102.     AddTail ((LIST *) & PBase, (NODE *) pen);
  103.     pen->Node.ln_Name = pen->path;
  104. } /* do_addpath */
  105.  
  106.  
  107. void do_rempath (void)
  108. {
  109.     PEN * pen;
  110.  
  111.     for (pen = (PEN *)GetHead(&PBase); pen; pen = (PEN *)GetSucc((struct Node *)pen))
  112.     {
  113.     if (!stricmp (av[1], pen->path))
  114.     {
  115.         Remove ((NODE *) pen);
  116.         free (pen);
  117.     }
  118.     }
  119. } /* do_rempath */
  120.  
  121.  
  122. void do_refctags (void)
  123. {
  124.     BOOL requester;
  125.     BOOL title;
  126.  
  127.     requester = globalflags.NoRequest;
  128.     title     = globalflags.Showtitle;
  129.  
  130.     globalflags.NoRequest = TRUE;
  131.     globalflags.Showtitle = FALSE;
  132.  
  133.     do_ctags ();
  134.  
  135.     if (globalflags.Abortcommand)
  136.     do_refs ();
  137.  
  138.     globalflags.NoRequest = requester;
  139.     globalflags.Showtitle = title;
  140.  
  141.     if (globalflags.Abortcommand)
  142.     error ("%s:\nCannot find anything.", av[0]);
  143. } /* do_refctags */
  144.  
  145.  
  146. /*
  147.  *  Implement ctags
  148.  */
  149.  
  150. void do_ctags (void)
  151. {
  152.     char    str[64];
  153.     char    path[128];
  154.     char    buf[128];
  155.     char    sbuf[128];
  156.     short   xlen;
  157.     short   slen;
  158.     short   dbaselen;
  159.     BPTR    oldlock = CurrentDir (Ep->dirlock);
  160.     ED      * ed;
  161.  
  162.     if (av[1] != NULL)
  163.     {
  164.     strcpy (str, av[1]);
  165.     xlen = strlen (str);
  166.     } else
  167.     {
  168.     strcpy (str, current_word ());
  169.     xlen = strlen (str);
  170.     }
  171.  
  172.     if (!Ep->iconmode)
  173.     title ("search tags");
  174.  
  175.     {
  176.     FILE * fi;
  177.     PEN  * pen;
  178.     long   i;
  179.     short  j,
  180.            len;
  181.  
  182.     dbaselen = dirpart (Ep->name);
  183.     movmem (Ep->name, path, dbaselen);
  184.     strcpy (path + dbaselen, "tags");
  185.  
  186.     /*
  187.      *  Note: pen not used first pass and set to list head, so next
  188.      *  pass it will be the first element.
  189.      *
  190.      *  Note2:  The file path depends on several factors.  (1) tags in
  191.      *        'current' directory, use path to name of current window.
  192.      *        (2) tags in directory in XDME special path, use special
  193.      *        path.  (3) tag entry is a full path name, override
  194.      *        previous directories.
  195.      */
  196.  
  197.     for (pen = (PEN *)GetHead(&PBase); TRUE; )
  198.     {
  199.         mountrequest (0);
  200.  
  201.         if (fi = fopen (path, "r"))
  202.         {
  203.         mountrequest (1);
  204.  
  205.         while ((len = xefgets (fi, buf, 128)) >= 0)
  206.         {
  207.             for (j = 0; buf[j] && buf[j] != ' '; ++j);
  208.  
  209.             if (j == 0 || buf[0] == '#')
  210.             continue;
  211.  
  212.             if (j == xlen && strncmp (str, buf, j) == 0)
  213.             {
  214.             while (buf[j] == ' ')
  215.                 ++j;
  216.  
  217.             /*
  218.              *  Extract the file name into str.  If the
  219.              *  filename does not contain an absolute path,
  220.              *  prepend it with such.
  221.              */
  222.             {
  223.                 char prep = 1;
  224.  
  225.                 for (i = 0; buf[j] && buf[j] != ' '; ++i, ++j)
  226.                 {
  227.                 str[i] = buf[j];
  228.                 if (str[i] == ':')
  229.                     prep = 0;
  230.                 }
  231.  
  232.                 if (prep)
  233.                 {
  234.                 movmem (str, str + dbaselen, i);
  235.                 movmem (path, str, dbaselen);
  236.  
  237.                 i += dbaselen;
  238.                 }
  239.             }
  240.  
  241.             str[i] = 0;
  242.  
  243.             while (buf[j] && buf[j] != '^') /*  SEARCH ARG */
  244.                 ++j;
  245.  
  246.             fclose (fi);
  247.  
  248.             if (buf[j] != '^')
  249.             {
  250.                 error ("ctags:\nError in tags-file");
  251.                 goto done;
  252.             }
  253.  
  254.             ++j;    /* Skip ^ */
  255.  
  256.             /* UN*X FIX: Dme works for Aztec ctags, which has the format:    */
  257.             /*    <tag>    <file>    /^<pattern>                */
  258.             /* However, ctags under UN*X has the following format:        */
  259.             /*    <tag>    <file>    /^<pattern>[$]/             */
  260.             /* We just ignore the '$' and '/' so that both foramts work     */
  261.             /* Thomas Rolfs 27/3/91                     */
  262.  
  263.             {
  264.                 short i = 0;
  265.  
  266.                 while (buf[j] && buf[j] != '$' && buf[j] != '/')
  267.                 {
  268.                 sbuf[i++] = buf[j++];
  269.                 }
  270.  
  271.                 sbuf[i] = 0;
  272.             }
  273.  
  274.             /* End of fix.    */
  275.  
  276.             slen = strlen (sbuf);
  277.  
  278.             if ((ed = finded (str, 0)) == NULL)
  279.             {
  280.                 strcpy (buf, "newwindow newfile `");
  281.                 strcat (buf, str);
  282.                 strcat (buf, "'");
  283.                 do_command (buf);
  284.  
  285.                 /* remove path */
  286.                 strcpy (str, FilePart (str));
  287.  
  288.                 ed = finded (str, 0);
  289.             } else
  290.             {
  291.                 WindowToFront (ed->win);
  292.                 ActivateWindow (ed->win);
  293.             }
  294.  
  295.             if (ed == NULL)
  296.             {
  297.                 error ("ctags:\nunable to load file\n`%s'", str);
  298.                 goto done;
  299.             }
  300.  
  301.             switch_ed (ed);
  302.             text_cursor (0);
  303.  
  304.             for (i = 0; i < ed->lines; ++i)
  305.             {
  306.                 if (strncmp (ed->list[i], sbuf, slen) == 0)
  307.                 break;
  308.             }
  309.  
  310.             sprintf (buf, "first goto %ld", i + 1);
  311.             do_command (buf);
  312.             text_cursor (1);    /* turn cursor on */
  313.  
  314.             goto done;
  315.             }
  316.         }
  317.  
  318.         fclose (fi);
  319.         } else
  320.         {
  321.         mountrequest (1);
  322.         }
  323.  
  324.         if (!pen) break;
  325.  
  326.         pen = (PEN *)GetSucc ((struct Node *)pen);
  327.  
  328.         if (pen)
  329.         {
  330.         strcpy (path, pen->path);
  331.         strcat (path, "tags");
  332.         dbaselen = strlen (pen->path);
  333.         }
  334.     }
  335.     error ("ctags:\ntag `%s'\nnot found", str);
  336.     }
  337. done:
  338.     CurrentDir (oldlock);
  339. } /* do_ctags */
  340.  
  341.  
  342. /*
  343.  *  Implement references
  344.  */
  345.  
  346. void do_refs (void)
  347. {
  348.     static char str[MAXLINELEN];
  349.     static char tmpfile[128];
  350.     static char path[128];
  351.     char      * srch;
  352.     char      * file;
  353.     char      * estr;
  354.     long    len;
  355.     int     bcnt = 10;
  356.     short    slen,
  357.         elen;
  358.     FILE      * fi,
  359.           * fj;
  360.     short    tmph,
  361.         tmpw;
  362.     BPTR    oldlock = CurrentDir (Ep->dirlock);
  363.  
  364.     if (av[1] != NULL)
  365.     {
  366.     strcpy (str, av[1]);
  367.     }
  368.     else
  369.     strcpy (str, current_word ());
  370.  
  371.     strcpy (tmpfile, "t:ref_");
  372.     strncat (tmpfile, str, sizeof (tmpfile) - 32);
  373.  
  374.     title ("search .refs");
  375.  
  376.     {
  377.     PEN * pen;
  378.  
  379.     strcpy (path, "dme.refs");      /*  warning, am assuming 8 char name */
  380.     mountrequest (0);
  381.  
  382.     /* search local refs */
  383.     if (searchref (path, str, &srch, &file, &len, &estr))
  384.     {
  385.         mountrequest (1);
  386.         goto found;
  387.     }
  388.  
  389.     /* search all paths */
  390.     for (pen = (PEN *)GetHead(&PBase); pen; pen=(PEN *)GetSucc(pen))
  391.     {
  392.         strcpy (path, pen->path);
  393.         strcat (path, "dme.refs");
  394.  
  395.         if (searchref (path, str, &srch, &file, &len, &estr))
  396.         {
  397.         mountrequest (1);
  398.         goto found;
  399.         }
  400.     }
  401.  
  402.     error ("refs:\nReference `%s'\nnot found", str);
  403.     mountrequest (1);
  404.     goto done;
  405.     }
  406.  
  407. found:
  408.     title ("search file");
  409.     slen = strlen (srch);
  410.  
  411.     if (estr)
  412.     elen = strlen (estr);
  413.  
  414.     fi = fopen (file, "r");
  415.  
  416.     if (fi == NULL)
  417.     {        /*  try using path prefix   */
  418.     strcpy (str, path);
  419.     strcpy (str + strlen (str) - 8, file);
  420.     fi = fopen (str, "r");
  421.     }
  422.  
  423.     if (fi)
  424.     {
  425.     short lenstr;
  426.  
  427.     if (srch[0] == '@' && srch[1] == '@')
  428.     {
  429.         fseek (fi, atoi (srch + 2), 0);
  430.         if ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0)
  431.         goto autoseek;
  432.     }
  433.  
  434.     while ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0)
  435.     {
  436.         if (strncmp (str, srch, slen) == 0)
  437.         {
  438. autoseek:
  439.         title ("load..");
  440.         if (fj = fopen (tmpfile, "w"))
  441.         {
  442.             tmph = 0;
  443.             tmpw = 0;
  444.  
  445.             do
  446.             {
  447.             if (lenstr > tmpw)
  448.                 tmpw = strlen (str);
  449.  
  450.             tmph ++;
  451.  
  452.             fputs (str, fj);
  453.             fputc ('\n', fj);
  454.  
  455.             if (estr && strncmp (str, estr, elen) == 0)
  456.                 break;
  457.  
  458.             len --;
  459.             }
  460.  
  461.             while ((lenstr = xefgets (fi, str, MAXLINELEN)) >= 0 && len);
  462.  
  463.             fclose (fj);
  464.  
  465.             if (tmph > 10)
  466.             tmph = 10;
  467.             if (tmpw > 80)
  468.             tmpw = 80;
  469.  
  470.             sprintf (str, "openwindow +0+0+%d+%d newfile %s", (tmpw << 3) + 24, (tmph << 3) + 24, tmpfile);
  471.             do_command (str);
  472.             text_cursor (1);    /* turn cursor on */
  473.             unlink (tmpfile);
  474.         } else
  475.         {
  476.             error ("refs:\nUnable to open\n`%s'\nfor write", tmpfile);
  477.         }
  478.  
  479.         fclose (fi);
  480.         free (srch);
  481.         free (file);
  482.  
  483.         if (estr)
  484.             free (estr);
  485.  
  486.         goto done;
  487.         }
  488.         if (--bcnt == 0)
  489.         {  /* check break every so so  */
  490.         bcnt = 50;
  491.  
  492.         if (breakcheck ())
  493.             break;
  494.         }
  495.     }
  496.     fclose (fi);
  497.  
  498.     error ("refs:\nSearch for `%s'\nfailed", str);
  499.     } else
  500.     {
  501.     error ("refs:\nUnable to open\nsub document");
  502.     }
  503.  
  504.     free (srch);
  505.     free (file);
  506.  
  507.     if (estr)
  508.     free (estr);
  509. done:
  510.     CurrentDir (oldlock);
  511. } /* do_refs */
  512.  
  513.  
  514. /*
  515.  *  Reference file format:
  516.  *
  517.  *  `key' `lines' `file' `searchstring'
  518.  *
  519.  *  where `lines' can be a string instead ... like a read-until, otherwise
  520.  *  the number of lines to read from the reference.
  521.  */
  522.  
  523. int searchref (char * file, char * find, char ** psstr, char ** pfile, int * plines, char **pestr)
  524. {
  525.     FILE  * fi;
  526.     char    buf[MAXLINELEN];
  527.     char  * ptr,
  528.       * base;
  529.     char  * b1,
  530.       * b2,
  531.       * b3,
  532.       * b4;
  533.     char    quoted;
  534.  
  535.     /* short findlen = strlen(find); TODO */
  536.  
  537.     if (fi = fopen (file, "r"))
  538.     {
  539.     while (xefgets (fi, (base = buf), MAXLINELEN) >= 0)
  540.     {
  541.         if (buf[0] == '#')
  542.         continue;
  543.  
  544.         ptr = breakout (&base, "ed, &b1);
  545.  
  546.         /* TODO if (ptr && *ptr && strncmp(ptr, find, findlen) == 0) */
  547.         if (ptr && *ptr && strcmp (ptr, find) == 0)
  548.         {
  549.         if (ptr = breakout (&base, "ed, &b2))
  550.         {
  551.             *pestr = NULL;
  552.             *plines = atoi (ptr);
  553.  
  554.             if (*plines == 0)
  555.             {
  556.             *pestr = (char *) malloc (strlen (ptr) + 1);
  557.             strcpy (*pestr, ptr);
  558.             }
  559.  
  560.             if (ptr = breakout (&base, "ed, &b3))
  561.             {
  562.             *pfile = (char *) malloc (strlen (ptr) + 1);
  563.             strcpy (*pfile, ptr);
  564.  
  565.             if (ptr = breakout (&base, "ed, &b4))
  566.             {
  567.                 *psstr = (char *) malloc (strlen (ptr) + 1);
  568.  
  569.                 strcpy (*psstr, ptr);
  570.                 fclose (fi);
  571.  
  572.                 if (b1)
  573.                 free (b1);
  574.                 if (b2)
  575.                 free (b2);
  576.                 if (b3)
  577.                 free (b3);
  578.                 if (b4)
  579.                 free (b4);
  580.  
  581.                 return (1);
  582.             }
  583.  
  584.             free (*pfile);
  585.  
  586.             if (b4)
  587.                 free (b4);
  588.             }
  589.  
  590.             if (pestr)
  591.             free (*pestr);
  592.             if (b3)
  593.             free (b3);
  594.         }
  595.  
  596.         if (b2)
  597.             free (b2);
  598.         }
  599.  
  600.         if (b1)
  601.         free (b1);
  602.     }
  603.  
  604.     fclose (fi);
  605.     }
  606.  
  607.     return (0);
  608. } /* searchref */
  609.  
  610.  
  611. int dirpart (char * str)
  612. {
  613.     short   i;
  614.  
  615.     for (i = strlen (str) - 1; i >= 0; --i)
  616.     {
  617.     if (str[i] == '/' || str[i] == ':')
  618.         break;
  619.     }
  620.  
  621.     return (i + 1);
  622. } /* dirpart */
  623.  
  624.  
  625. /******************************************************************************
  626. *****  ENDE refs.c
  627. ******************************************************************************/
  628.