Package: exuberant-ctags
Version: 1:5.7-4

I'm fixing some gedit plugins and found that the exuberant-ctags ASP parser is unable to detect classes and is returning a wrong char constant for constants.

Here is a transcript of how to test it:

$ctags customevent.class.asp
$vi tags

Note that although the file is a class definition, the parser is unable note it.

customevent.class.asp content:

<%

' Class: CustomEvent
'
' This class implements a generic way to work with Custom Events in ASP. It's
' the ASP Xtreme Evolution base for an Event-driven programming approach.
'
' Known issues:
'
' - As you can notice by the first example, CustomEvent doesn't work well with ' the VBScript standard Class events "Class_initialize" and "Class_terminate" ' - It's odd but getref() is unable to get the reference of a method or class
'     procedure.
'
' About:
'
' - Written by Fabio Zendhi Nagao <http://zend.lojcomm.com.br> @ January 2009
'
class CustomEvent
' Property: classType
   '
   ' Class type.
   '
   ' Contains:
   '
   '   (string) - type
   '
   public classType
' Property: classVersion
   '
   ' Class version.
   '
   ' Contains:
   '
   '   (float) - version
   '
   public classVersion
' Property: Owner
   '
   ' description
   '
   ' Contains:
   '
   '     (Class) - Should be set with the reference of the Caller.
   '
   public Owner
private Handlers ' Property: Arguments
   '
   ' Arguments to be passed to the handlers.
   '
   ' Contains:
   '
' (Scripting.Dictionary) - A collection with the callback function arguments
   '
   public Arguments
private sub Class_initialize()
       classType    = typename(Me)
       classVersion = "1.0.0"
set Handlers = Server.createObject("Scripting.Dictionary")
       set Arguments = Server.createObject("Scripting.Dictionary")
   end sub
private sub Class_terminate()
       Handlers.removeAll()
       Arguments.removeAll()
       set Handlers  = nothing
       set Arguments = nothing
   end sub
' Subroutine: addHandler
   '
   ' Adds a handler.
   '
   public sub addHandler(fn)
       select case typename(fn)
           case "JScriptTypeInfo"
               set Handlers.item(fn.toString()) = fn
           case else
               set Handlers.item(fn) = getRef(fn)
       end select
   end sub
' Subroutine: removeHandler
   '
   ' description
   '
   public sub removeHandler(fn)
       set Handlers.item(fn) = nothing
       Handlers.remove(fn)
   end sub
' Subroutine: fire
   '
   ' Fires all handlers attached to this event.
   '
   ' Example:
   '
   ' (start code)
   '
   ' class ClassWithEvents
   '     public classType
   '     public classVersion
' ' public onLoad
   '     public onUnload
   '     public onComplimentBefore
   '     public onComplimentAfter
' ' private sub Class_initialize()
   '         classType    = typename(Me)
   '         classVersion = "1.0.0"
' ' set onLoad = new CustomEvent : set onLoad.Owner = Me
   '         set onUnload = new CustomEvent : set onUnload.Owner = Me
' set onComplimentBefore = new CustomEvent : set onComplimentBefore.Owner = Me ' set onComplimentAfter = new CustomEvent : set onComplimentAfter.Owner = Me
   '
   '         onComplimentBefore.Arguments.item("firstname") = "Fabio"
   '         onComplimentBefore.Arguments.item("lastname") = "Nagao"
   '         onComplimentBefore.Arguments.item("nickname") = "nagaozen"
   '         call onLoad.fire()
   '     end sub
' ' private sub Class_terminate()
   '         call onUnload.fire()
' ' set onLoad = nothing
   '         set onUnload = nothing
   '         set onComplimentBefore = nothing
   '         set onComplimentAfter = nothing
   '     end sub
' ' public function compliment()
   '         call onComplimentBefore.fire()
   '         Response.write("Method compliment called." & vbNewline)
   '         call onComplimentAfter.fire()
   '     end function
' ' end class
   '
   '
   '
   ' sub ev_onLoad(ev)
   '     Response.write("Event onLoad has been fired" & vbNewline)
   ' end sub
   '
   ' sub ev_onUnLoad(ev)
   '     Response.write("Event onUnLoad has been fired" & vbNewline)
   ' end sub
   '
   ' sub ev_onComplimentBefore(ev)
' Response.write("Event onComplimentBefore has been fired. I was really expecting this method to say: 'Hello World " & ev.Arguments.item("firstname") & " " & ev.Arguments.item("lastname") & " (" & ev.Arguments.item("nickname") & ")'" & vbNewline)
   ' end sub
   '
   ' sub ev_onComplimentAfter(ev)
' Response.write("Event onComplimentAfter has been fired" & vbNewline)
   ' end sub
   '
   ' dim CwE : set CwE = new ClassWithEvents
   ' call CwE.onLoad.addHandler("ev_onLoad")
   ' call CwE.onUnLoad.addHandler("ev_onUnLoad")
   ' call CwE.onComplimentBefore.addHandler("ev_onComplimentBefore")
' call CwE.onComplimentBefore.addHandler(lambda("function(ev){ Response.write('Another handler attached to Event onComplimentAfter. This one is using a lambda function -- Yes, ' + ev.Arguments.item('firstname') + ' ' + ev.Arguments.item('lastname') + ' (' + ev.Arguments.item('nickname') + ') has implemented it for Classic ASP.\r\n') }"))
   ' call CwE.onComplimentAfter.addHandler("ev_onComplimentAfter")
   ' CwE.compliment()
   ' set CwE = nothing
   '
' Response.write("As you can see, this nothing @ line 74 doesn't work as expected. onLoad doesn't work either. But for user methods and procedures the CustomEvent works fine." & vbNewLine)
   '
   ' (end code)
   '
   public sub fire()
       dim fn : for each fn in Handlers
           Handlers.item(fn)(Me)
       next
   end sub
' Function: revealArguments
   '
   ' Reveals the event arguments.
   '
   ' Returns:
   '
   '     (string) - A list of the available event arguments
   '
   ' Example:
   '
   ' (start code)
   '
   ' ' Using the class defined in the example above
   ' dim CwE : set CwE = new ClassWithEvents
   ' Response.write(CwE.onComplimentBefore.revealArguments())
   ' set CwE = nothing
   '
   ' (end code)
   '
   public function revealArguments()
       revealArguments = ""
       dim arg : for each arg in Arguments
           revealArguments = revealArguments & ", " & arg
       next
       revealArguments = mid(revealArguments, 3)
   end function
end class

%>
<script language="javascript" runat="server">
function lambda(f) {
   if(/^function\s*\([ a-z0-9.$_,]*\)\s*{[\S\s]*}$/gim.test(f)) {
       eval("f = " + f.replace(/(\r|\n)/g, ''));
       return f;
   } else {
       return function() {};
   }
}
</script>

I've also made a patch based in the ctags/trunk/asp.c to fix this issue. Fixed asp.c:

/*
*   $Id$
*
*   Copyright (c) 2000, Patrick Dehne <patr...@steidle.net>
*
* This source code is released for free distribution under the terms of the
*   GNU General Public License.
*
*   This module contains functions for generating tags for the ASP (Active
*   Server Pages) web page scripting language.
*/

/*
*   INCLUDE FILES
*/
#include "general.h"  /* must always come first */

#include <string.h>

#include "parse.h"
#include "read.h"
#include "vstring.h"

/*
*   DATA DEFINITIONS
*/
typedef enum {
   K_CONST, K_CLASS, K_FUNCTION, K_SUB, K_DIM
} aspKind;

static kindOption AspKinds [] = {
   { TRUE, 'd', "constant",   "constants"},
   { TRUE, 'c', "class",      "classes"},
   { TRUE, 'f', "function",   "functions"},
   { TRUE, 's', "subroutine", "subroutines"},
   { TRUE, 'v', "variable",   "variables"}
};

/*
*   FUNCTION DEFINITIONS
*/

static void findAspTags (void)
{
   vString *name = vStringNew ();
   const unsigned char *line;

   while ((line = fileReadLine ()) != NULL)
   {
       const unsigned char *cp = line;

       while (*cp != '\0')
       {
           /* jump over whitespace */
           while (isspace ((int)*cp))
               cp++;

           /* jump over strings */
           if (*cp == '"')
           {
               cp++;
               while (*cp!='"' && *cp!='\0')
                   cp++;
           }

           /* jump over comments */
           else if (*cp == '\'')
               break;
/* jump over end function/sub lines */
           else if (strncasecmp ((const char*) cp, "end", (size_t) 3)== 0)
           {
               cp += 3;
               if (isspace ((int)*cp))
               {
                   while (isspace ((int)*cp))
                       ++cp;

if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0)
                   {
                       cp+=8;
                       break;
                   }

else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
                   {
                       cp+=3;
                       break;
                   }
               }
           }

           /* jump over exit function/sub lines */
           else if (strncasecmp ((const char*) cp, "exit", (size_t) 4)==0)
           {
               cp += 4;
               if (isspace ((int) *cp))
               {
                   while (isspace ((int) *cp))
                       ++cp;

if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0)
                   {
                       cp+=8;
                       break;
                   }

else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
                   {
                       cp+=3;
                       break;
                   }
               }
           }

           /* class? */
else if (strncasecmp ((const char*) cp, "class", (size_t) 5) == 0)
           {
               cp += 5;

               if (isspace ((int) *cp))
               {
                   while (isspace ((int) *cp))
                       ++cp;
                   while (isalnum ((int) *cp)  ||  *cp == '_')
                   {
                       vStringPut (name, (int) *cp);
                       ++cp;
                   }
                   vStringTerminate (name);
                   makeSimpleTag (name, AspKinds, K_CLASS);
                   vStringClear (name);
               }
           }

           /* function? */
else if (strncasecmp ((const char*) cp, "function", (size_t) 8) == 0)
           {
               cp += 8;

               if (isspace ((int) *cp))
               {
                   while (isspace ((int) *cp))
                       ++cp;
                   while (isalnum ((int) *cp)  ||  *cp == '_')
                   {
                       vStringPut (name, (int) *cp);
                       ++cp;
                   }
                   vStringTerminate (name);
                   makeSimpleTag (name, AspKinds, K_FUNCTION);
                   vStringClear (name);
               }
           }

           /* sub? */
           else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
           {
               cp += 3;
               if (isspace ((int) *cp))
               {
                   while (isspace ((int) *cp))
                       ++cp;
                   while (isalnum ((int) *cp)  ||  *cp == '_')
                   {
                       vStringPut (name, (int) *cp);
                       ++cp;
                   }
                   vStringTerminate (name);
                   makeSimpleTag (name, AspKinds, K_SUB);
                   vStringClear (name);
               }
           }

           /* dim variable? */
           else if (strncasecmp ((const char*) cp, "dim", (size_t) 3) == 0)
           {
               cp += 3;
               if (isspace ((int) *cp))
               {
                   while (isspace ((int) *cp))
                       ++cp;
                   while (isalnum ((int) *cp)  ||  *cp == '_')
                   {
                       vStringPut (name, (int) *cp);
                       ++cp;
                   }
                   vStringTerminate (name);
                   makeSimpleTag (name, AspKinds, K_DIM);
                   vStringClear (name);
               }
           }

           /* const declaration? */
else if (strncasecmp ((const char*) cp, "const", (size_t) 5) == 0)
           {
               cp += 5;
               if (isspace ((int) *cp))
               {
                   while (isspace ((int) *cp))
                       ++cp;
                   while (isalnum ((int) *cp)  ||  *cp == '_')
                   {
                       vStringPut (name, (int) *cp);
                       ++cp;
                   }
                   vStringTerminate (name);
                   makeSimpleTag (name, AspKinds, K_CONST);
                   vStringClear (name);
               }
           }

           /* nothing relevant */
           else if (*cp != '\0')
               cp++;
       }
   }
   vStringDelete (name);
}

extern parserDefinition* AspParser (void)
{
   static const char *const extensions [] = { "asp", "asa", NULL };
   parserDefinition* def = parserNew ("Asp");
   def->kinds      = AspKinds;
   def->kindCount  = KIND_COUNT (AspKinds);
   def->extensions = extensions;
   def->parser     = findAspTags;
   return def;
}

/* vi:set tabstop=4 shiftwidth=4: */

My kernel is: Linux nagaozen-linux 2.6.28-11-generic #42-Ubuntu SMP Fri Apr 17 01:58:03 UTC 2009 x86_64 GNU/Linux
My shared C library is: 2.9-4ubuntu6



--
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to