home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / STVI369G.ZIP / TAGCMD.C < prev    next >
C/C++ Source or Header  |  1990-05-01  |  5KB  |  236 lines

  1. /* #Header: /?????
  2.  *
  3.  * Routines to implement tags, and, especially, tag stacking.
  4.  * Added by Dave Tutelman - 12/89.
  5.  * The dotag() routine is a modification of the posted
  6.  * version by Tony Andrews.
  7.  * The untag() routine is new.
  8.  */
  9.  
  10. #include "stevie.h"
  11.  
  12. #define    LSIZE    256    /* max. size of a line in the tags file */
  13.  
  14. #ifdef TAGSTACK
  15. /*  We build a stack of file records, on which we push info about
  16.  *  current file when dotag() is called.
  17.  */
  18. #define    TAGSTACKSIZE    12        /* how many tag calls can we stack? */
  19. static    struct filerecord {
  20.         char    *name;        /* file name pointer */
  21.         int    linenum;    /* line number when we left */
  22. } tagstack [TAGSTACKSIZE];
  23. static    int    stackindex = 0;        /* here's how we keep track */
  24. #endif
  25.  
  26. extern    char    **files;
  27. extern    int    curfile;
  28. static    void    pushtags(), poptags();
  29.  
  30.  
  31. /*
  32.  * dotag(tag, force) - goto tag.  If force=TRUE, dump pending changes.
  33.  */
  34. void
  35. dotag(tag, force)
  36. char    *tag;
  37. bool_t    force;
  38. {
  39.     FILE    *tp, *fopen();
  40.     char    lbuf[LSIZE];        /* line buffer */
  41.     char    pbuf[LSIZE];        /* search pattern buffer */
  42.     register char    *fname, *str;
  43.     register char    *p;
  44.  
  45.     if ((tp = fopen("tags", "r")) == NULL) {
  46.         emsg("Can't open tags file");
  47.         return;
  48.     }
  49.  
  50.     while (fgets(lbuf, LSIZE, tp) != NULL) {
  51.     
  52.         if ((fname = strchr(lbuf, TAB)) == NULL) {
  53.             emsg("Format error in tags file");
  54.             return;
  55.         }
  56.         *fname++ = '\0';
  57.         if ((str = strchr(fname, TAB)) == NULL) {
  58.             emsg("Format error in tags file");
  59.             return;
  60.         }
  61.         *str++ = '\0';
  62.  
  63.         if (strcmp(lbuf, tag) == 0) {
  64.  
  65.             /*
  66.              * Scan through the search string. If we see a magic
  67.              * char, we have to quote it. This lets us use "real"
  68.              * implementations of ctags.
  69.              */
  70.             p = pbuf;
  71.             *p++ = *str++;        /* copy the '/' or '?' */
  72.             *p++ = *str++;        /* copy the '^' */
  73.  
  74.             for (; *str != NUL ;str++) {
  75.                 if (*str == '\\') {
  76.                     *p++ = *str++;
  77.                     *p++ = *str;
  78.                 } else if (strchr("/?", *str) != NULL) {
  79.                     if (str[1] != '\n') {
  80.                         *p++ = '\\';
  81.                         *p++ = *str;
  82.                     } else
  83.                         *p++ = *str;
  84.                 } else if (strchr("^()*.", *str) != NULL) {
  85.                     *p++ = '\\';
  86.                     *p++ = *str;
  87.                 } else
  88.                     *p++ = *str;
  89.             }
  90.             *p = NUL;
  91.  
  92. #ifdef TAGSTACK
  93.             /* Push current position onto stack, unless this
  94.              * is a startup call using '-t' option. */
  95.             if (Filename!=NULL && *Filename!='\0')
  96.                 pushtags ();
  97. #endif
  98.  
  99.             /*
  100.              * This looks out of order, but by calling stuffin()
  101.              * before doecmd() we keep an extra screen update
  102.              * from occuring. This stuffins() have no effect
  103.              * until we get back to the main loop, anyway.
  104.              */
  105.  
  106.             stuffin(pbuf);        /* str has \n at end */
  107.             stuffin("\007");    /* CTRL('g') */
  108.  
  109.             if (doecmd(fname, force)) {
  110.                 fclose(tp);
  111.                 return;
  112.             } else {
  113. #ifdef TAGSTACK
  114.                 poptags ();    /* cancel stack entry */
  115. #endif
  116.                 stuffin(NULL);    /* clear the input */
  117.             }
  118.         }
  119.     }
  120.     emsg("tag not found");
  121.     fclose(tp);
  122. }
  123.  
  124. /*
  125.  * dountag (spec) - undo the last ':ta' command, popping the tag stack.
  126.  *    spec is the appended character, giving specifics:
  127.  *      '!'    dump pending changes.
  128.  *      'e'    came from K_CCIRCM "shortcut".  do :e# if stack empty.
  129.  *      ' '    do normal untag.
  130.  *      else    bad command.
  131.  */
  132.  
  133. void
  134. dountag (spec)
  135.   char spec;
  136. {
  137. #ifndef TAGSTACK
  138.     badcmd();    /* complain & return */
  139. }
  140. #else
  141.  
  142.     char    force=0, shortcut=0;
  143.     char    *newfile;
  144.     char    buf [LSIZE];
  145.  
  146.     switch (spec) {
  147.       case '!':
  148.         force++;
  149.         break;
  150.       case 'e':
  151.         shortcut++;
  152.         break;
  153.       case ' ':
  154.       case '\n':
  155.       case '\r':
  156.       case '\0':
  157.         break;
  158.       default:
  159.         badcmd();
  160.         return;
  161.     }
  162.  
  163.     /* Check the stack.  If empty, don't pop */
  164.     if (!stackindex) {
  165.         if (shortcut)        /* just edit altfile */
  166.             stuffin(":e #\n");
  167.         else
  168.             emsg("Tags stack empty");
  169.         return;
  170.     }
  171.  
  172.     /* Get the top of the stack, and do the implied edit.
  173.      * If it succeeds, switch; if not, back off */
  174.     newfile = tagstack [stackindex-1].name;
  175.     if (doecmd (newfile, force)) {
  176.         sprintf (buf, "%dG:f\n", tagstack [stackindex-1].linenum);
  177.         stuffin(buf);
  178.         poptags ();
  179.         return;
  180.     }
  181.     else
  182.         stuffin(NULL);
  183. }
  184.  
  185. /*
  186.  * pushtags () - push the current state onto the tagstack.
  187.  */
  188.  
  189. static void
  190. pushtags ()
  191. {
  192.     int    i;
  193.  
  194.     /* If stack full, throw away oldest and push the rest.
  195.      * This is clearly the best and most transparent way to behave,
  196.      * much preferable to either complaining or losing new entry.
  197.      */
  198.     if (stackindex >= TAGSTACKSIZE) {
  199.         for (i=0; i<TAGSTACKSIZE-1; i++) {
  200.             tagstack[i].name    = tagstack[i+1].name;
  201.             tagstack[i].linenum = tagstack[i+1].linenum;
  202.         }
  203.         stackindex--;
  204.     }
  205.  
  206.     /* Get current state, and put it in stack.
  207.      * Right now, the state is file name & line number.
  208.      * This is less than perfect, in that line numbers may change if
  209.      * you edit elsewhere in the file.  Eventually, I'd like to base
  210.      * it on "hidden" marks, if I can implement them.  DMT
  211.      */
  212.     tagstack [stackindex].name    = strsave (Filename);
  213.     tagstack [stackindex].linenum = cntllines (Filemem, Curschar);
  214.     stackindex++;
  215. }
  216.  
  217. /*
  218.  * poptags () - pop the tag stack.
  219.  */
  220.  
  221. static void
  222. poptags ()
  223. {
  224.     if (!stackindex) {
  225.         emsg("Tags stack empty");
  226.         return;
  227.     }
  228.  
  229.     stackindex--;
  230.     free (tagstack [stackindex].name);
  231. }
  232.  
  233. #endif
  234.  
  235.  
  236.