Blame SOURCES/ctags-5.8-css.patch

b1280f
diff -up ctags-5.8/css.c.me ctags-5.8/css.c
b1280f
--- ctags-5.8/css.c.me	2012-02-08 13:59:35.000000000 +0100
b1280f
+++ ctags-5.8/css.c	2012-02-08 13:55:16.000000000 +0100
b1280f
@@ -0,0 +1,226 @@
b1280f
+/***************************************************************************
b1280f
+ * css.c
b1280f
+ * Character-based parser for Css definitions
b1280f
+ * Author - Iago Rubio <iagorubio(at)users.sourceforge.net>
b1280f
+ **************************************************************************/
b1280f
+#include "general.h"
b1280f
+
b1280f
+#include <string.h> 
b1280f
+#include <ctype.h> 
b1280f
+
b1280f
+#include "parse.h" 
b1280f
+#include "read.h" 
b1280f
+
b1280f
+
b1280f
+typedef enum eCssKinds {
b1280f
+    K_NONE = -1, K_CLASS, K_SELECTOR, K_ID
b1280f
+} cssKind;
b1280f
+
b1280f
+static kindOption CssKinds [] = {
b1280f
+    { TRUE, 'c', "class", "classes" },
b1280f
+    { TRUE, 's', "selector",  "selectors"  },
b1280f
+    { TRUE, 'i', "id",  "identities"  }
b1280f
+};
b1280f
+
b1280f
+typedef enum _CssParserState {  // state of parsing
b1280f
+  P_STATE_NONE,         // default state
b1280f
+  P_STATE_IN_COMMENT,     // into a comment, only multi line in CSS
b1280f
+  P_STATE_IN_SINGLE_STRING, // into a single quoted string
b1280f
+  P_STATE_IN_DOUBLE_STRING, // into a double quoted string
b1280f
+  P_STATE_IN_DEFINITION,    // on the body of the style definition, nothing for us
b1280f
+  P_STATE_IN_MEDIA,     // on a @media declaration, can be multi-line
b1280f
+  P_STATE_IN_IMPORT,      // on a @import declaration, can be multi-line
b1280f
+  P_STATE_IN_NAMESPACE,   // on a @namespace declaration  
b1280f
+  P_STATE_IN_PAGE,      // on a @page declaration
b1280f
+  P_STATE_IN_FONTFACE,    // on a @font-face declaration
b1280f
+  P_STATE_AT_END        // end of parsing
b1280f
+} CssParserState;
b1280f
+
b1280f
+static void makeCssSimpleTag( vString *name, cssKind kind, boolean delete )
b1280f
+{
b1280f
+  vStringTerminate (name);
b1280f
+  makeSimpleTag (name, CssKinds, kind);
b1280f
+  vStringClear (name);
b1280f
+  if( delete )
b1280f
+    vStringDelete (name);
b1280f
+}
b1280f
+
b1280f
+static boolean isCssDeclarationAllowedChar( const unsigned char *cp )
b1280f
+{
b1280f
+  return  isalnum ((int) *cp) ||
b1280f
+      isspace ((int) *cp) ||
b1280f
+      *cp == '_' || // allowed char
b1280f
+      *cp == '-' || // allowed char     
b1280f
+      *cp == '+' ||   // allow all sibling in a single tag
b1280f
+      *cp == '>' ||   // allow all child in a single tag 
b1280f
+      *cp == '{' ||   // allow the start of the declaration
b1280f
+      *cp == '.' ||   // allow classes and selectors
b1280f
+      *cp == ',' ||   // allow multiple declarations
b1280f
+      *cp == ':' ||   // allow pseudo classes
b1280f
+      *cp == '*' ||   // allow globs as P + *
b1280f
+      *cp == '#';   // allow ids 
b1280f
+}
b1280f
+
b1280f
+static CssParserState parseCssDeclaration( const unsigned char **position, cssKind kind )
b1280f
+{
b1280f
+  vString *name = vStringNew ();
b1280f
+  const unsigned char *cp = *position;
b1280f
+
b1280f
+  // pick to the end of line including children and sibling
b1280f
+  // if declaration is multiline go for the next line 
b1280f
+  while ( isCssDeclarationAllowedChar(cp) || 
b1280f
+      *cp == '\0' )   // track the end of line into the loop
b1280f
+  {
b1280f
+    if( (int) *cp == '\0' )
b1280f
+    { 
b1280f
+      cp = fileReadLine ();
b1280f
+      if( cp == NULL ){
b1280f
+        makeCssSimpleTag(name, kind, TRUE);
b1280f
+        *position = cp;
b1280f
+        return P_STATE_AT_END;
b1280f
+      }
b1280f
+    }
b1280f
+    else if( *cp == ',' )
b1280f
+    {
b1280f
+      makeCssSimpleTag(name, kind, TRUE);
b1280f
+      *position = ++cp;
b1280f
+      return P_STATE_NONE;
b1280f
+    }
b1280f
+    else if( *cp == '{' )
b1280f
+    {
b1280f
+      makeCssSimpleTag(name, kind, TRUE);
b1280f
+      *position = ++cp;
b1280f
+      return P_STATE_IN_DEFINITION;
b1280f
+    }
b1280f
+
b1280f
+    vStringPut (name, (int) *cp);
b1280f
+    ++cp;
b1280f
+  }
b1280f
+  
b1280f
+  makeCssSimpleTag(name, kind, TRUE);
b1280f
+  *position = cp;
b1280f
+
b1280f
+  return P_STATE_NONE;
b1280f
+}
b1280f
+
b1280f
+static CssParserState parseCssLine( const unsigned char *line, CssParserState state )
b1280f
+{
b1280f
+  vString *aux;
b1280f
+
b1280f
+  while( *line != '\0' ) // fileReadLine returns NULL terminated strings
b1280f
+  {
b1280f
+    while (isspace ((int) *line))
b1280f
+      ++line;
b1280f
+    switch( state )
b1280f
+    {
b1280f
+      case P_STATE_NONE:
b1280f
+        // pick first char if alphanumeric is a selector
b1280f
+        if( isalnum ((int) *line) )
b1280f
+          state = parseCssDeclaration( &line, K_SELECTOR );
b1280f
+        else if( *line == '.' ) // a class
b1280f
+          state = parseCssDeclaration( &line, K_CLASS );
b1280f
+        else if( *line == '#' ) // an id
b1280f
+          state = parseCssDeclaration( &line, K_ID );
b1280f
+        else if( *line == '@' ) // at-rules, we'll ignore them
b1280f
+        {
b1280f
+          ++line;
b1280f
+          aux = vStringNew();
b1280f
+          while( !isspace((int) *line) )
b1280f
+          {
b1280f
+            vStringPut (aux, (int) *line);
b1280f
+            ++line;         
b1280f
+          }
b1280f
+          vStringTerminate (aux);
b1280f
+          if( strcmp( aux->buffer, "media" ) == 0 )
b1280f
+            state = P_STATE_IN_MEDIA;
b1280f
+          else if ( strcmp( aux->buffer, "import" ) == 0 )
b1280f
+            state = P_STATE_IN_IMPORT;
b1280f
+          else if ( strcmp( aux->buffer, "namespace" ) == 0 )
b1280f
+            state = P_STATE_IN_NAMESPACE; 
b1280f
+          else if ( strcmp( aux->buffer, "page" ) == 0 )
b1280f
+            state = P_STATE_IN_PAGE;
b1280f
+          else if ( strcmp( aux->buffer, "font-face" ) == 0 )
b1280f
+            state = P_STATE_IN_FONTFACE;
b1280f
+          vStringDelete (aux);
b1280f
+        }
b1280f
+        else if( *line == '*' && *(line-1) == '/' ) // multi-line comment
b1280f
+          state = P_STATE_IN_COMMENT;
b1280f
+      break;
b1280f
+      case P_STATE_IN_COMMENT:
b1280f
+        if( *line == '/' && *(line-1) == '*')
b1280f
+          state = P_STATE_NONE;
b1280f
+      break;
b1280f
+      case  P_STATE_IN_SINGLE_STRING: 
b1280f
+        if( *line == '\'' && *(line-1) != '\\' )
b1280f
+          state = P_STATE_IN_DEFINITION; // PAGE, FONTFACE and DEFINITION are treated the same way
b1280f
+      break;
b1280f
+      case  P_STATE_IN_DOUBLE_STRING:
b1280f
+        if( *line=='"' && *(line-1) != '\\' )
b1280f
+          state = P_STATE_IN_DEFINITION; // PAGE, FONTFACE and DEFINITION are treated the same way
b1280f
+      break;
b1280f
+      case  P_STATE_IN_MEDIA:
b1280f
+        // skip to start of media body or line end
b1280f
+        while( *line != '{' )
b1280f
+        {
b1280f
+          if( *line == '\0' )
b1280f
+            break;
b1280f
+          ++line;
b1280f
+        }
b1280f
+        if( *line == '{' )
b1280f
+            state = P_STATE_NONE;
b1280f
+      break;
b1280f
+      case  P_STATE_IN_IMPORT:
b1280f
+      case  P_STATE_IN_NAMESPACE:
b1280f
+        // skip to end of declaration or line end
b1280f
+        while( *line != ';' )
b1280f
+        {
b1280f
+          if( *line == '\0' )
b1280f
+            break;
b1280f
+          ++line;
b1280f
+        }
b1280f
+        if( *line == ';' )
b1280f
+          state = P_STATE_NONE;
b1280f
+      break;
b1280f
+      case P_STATE_IN_PAGE:
b1280f
+      case P_STATE_IN_FONTFACE:
b1280f
+      case P_STATE_IN_DEFINITION:
b1280f
+        if( *line == '}' )
b1280f
+          state = P_STATE_NONE;
b1280f
+        else if( *line == '\'' )
b1280f
+          state = P_STATE_IN_SINGLE_STRING;
b1280f
+        else if( *line == '"' )
b1280f
+          state = P_STATE_IN_DOUBLE_STRING;
b1280f
+      break;
b1280f
+      case P_STATE_AT_END:
b1280f
+        return state;
b1280f
+      break;
b1280f
+    }   
b1280f
+    line++;
b1280f
+  }
b1280f
+  return state;
b1280f
+}
b1280f
+
b1280f
+static void findCssTags (void)
b1280f
+{
b1280f
+    const unsigned char *line;
b1280f
+  CssParserState state = P_STATE_NONE;
b1280f
+
b1280f
+    while ( (line = fileReadLine ()) != NULL )
b1280f
+    {
b1280f
+    state = parseCssLine( line, state );
b1280f
+    if( state==P_STATE_AT_END ) return;
b1280f
+    }    
b1280f
+}
b1280f
+
b1280f
+/* parser definition */
b1280f
+extern parserDefinition* CssParser (void)
b1280f
+{
b1280f
+    static const char *const extensions [] = { "css", NULL };
b1280f
+    parserDefinition* def = parserNew ("CSS");
b1280f
+    def->kinds      = CssKinds;
b1280f
+    def->kindCount  = KIND_COUNT (CssKinds);
b1280f
+    def->extensions = extensions;
b1280f
+    def->parser     = findCssTags;
b1280f
+    return def;
b1280f
+}
b1280f
+
b1280f
diff -up ctags-5.8/parsers.h.me ctags-5.8/parsers.h
b1280f
--- ctags-5.8/parsers.h.me	2012-02-08 13:56:46.000000000 +0100
b1280f
+++ ctags-5.8/parsers.h	2012-02-08 13:57:25.000000000 +0100
b1280f
@@ -26,6 +26,7 @@
b1280f
 	CppParser, \
b1280f
 	CsharpParser, \
b1280f
 	CobolParser, \
b1280f
+	CssParser, \
b1280f
 	DosBatchParser, \
b1280f
 	EiffelParser, \
b1280f
 	ErlangParser, \
b1280f
diff -up ctags-5.8/source.mak.me ctags-5.8/source.mak
b1280f
--- ctags-5.8/source.mak.me	2012-02-08 13:58:02.000000000 +0100
b1280f
+++ ctags-5.8/source.mak	2012-02-08 13:58:42.000000000 +0100
b1280f
@@ -17,6 +17,7 @@ SOURCES = \
b1280f
 	beta.c \
b1280f
 	c.c \
b1280f
 	cobol.c \
b1280f
+	css.c \
b1280f
 	dosbatch.c \
b1280f
 	eiffel.c \
b1280f
 	entry.c \
b1280f
@@ -79,6 +80,7 @@ OBJECTS = \
b1280f
 	beta.$(OBJEXT) \
b1280f
 	c.$(OBJEXT) \
b1280f
 	cobol.$(OBJEXT) \
b1280f
+	css.$(OBJEXT) \
b1280f
 	dosbatch.$(OBJEXT) \
b1280f
 	eiffel.$(OBJEXT) \
b1280f
 	entry.$(OBJEXT) \