[ctags] bz#786451, add css support

Than Ngo than at fedoraproject.org
Wed Feb 8 13:06:53 UTC 2012


commit 954bda372aaf5443d969167da86cd1b1d564ecc6
Author: Than Ngo <than at redhat.com>
Date:   Wed Feb 8 14:06:44 2012 +0100

    bz#786451, add css support

 ctags-5.8-css.patch |  260 +++++++++++++++++++++++++++++++++++++++++++++++++++
 ctags.spec          |    9 ++-
 2 files changed, 267 insertions(+), 2 deletions(-)
---
diff --git a/ctags-5.8-css.patch b/ctags-5.8-css.patch
new file mode 100644
index 0000000..2744d33
--- /dev/null
+++ b/ctags-5.8-css.patch
@@ -0,0 +1,260 @@
+diff -up ctags-5.8/css.c.me ctags-5.8/css.c
+--- ctags-5.8/css.c.me	2012-02-08 13:59:35.000000000 +0100
++++ ctags-5.8/css.c	2012-02-08 13:55:16.000000000 +0100
+@@ -0,0 +1,226 @@
++/***************************************************************************
++ * css.c
++ * Character-based parser for Css definitions
++ * Author - Iago Rubio <iagorubio(at)users.sourceforge.net>
++ **************************************************************************/
++#include "general.h"
++
++#include <string.h> 
++#include <ctype.h> 
++
++#include "parse.h" 
++#include "read.h" 
++
++
++typedef enum eCssKinds {
++    K_NONE = -1, K_CLASS, K_SELECTOR, K_ID
++} cssKind;
++
++static kindOption CssKinds [] = {
++    { TRUE, 'c', "class", "classes" },
++    { TRUE, 's', "selector",  "selectors"  },
++    { TRUE, 'i', "id",  "identities"  }
++};
++
++typedef enum _CssParserState {  // state of parsing
++  P_STATE_NONE,         // default state
++  P_STATE_IN_COMMENT,     // into a comment, only multi line in CSS
++  P_STATE_IN_SINGLE_STRING, // into a single quoted string
++  P_STATE_IN_DOUBLE_STRING, // into a double quoted string
++  P_STATE_IN_DEFINITION,    // on the body of the style definition, nothing for us
++  P_STATE_IN_MEDIA,     // on a @media declaration, can be multi-line
++  P_STATE_IN_IMPORT,      // on a @import declaration, can be multi-line
++  P_STATE_IN_NAMESPACE,   // on a @namespace declaration  
++  P_STATE_IN_PAGE,      // on a @page declaration
++  P_STATE_IN_FONTFACE,    // on a @font-face declaration
++  P_STATE_AT_END        // end of parsing
++} CssParserState;
++
++static void makeCssSimpleTag( vString *name, cssKind kind, boolean delete )
++{
++  vStringTerminate (name);
++  makeSimpleTag (name, CssKinds, kind);
++  vStringClear (name);
++  if( delete )
++    vStringDelete (name);
++}
++
++static boolean isCssDeclarationAllowedChar( const unsigned char *cp )
++{
++  return  isalnum ((int) *cp) ||
++      isspace ((int) *cp) ||
++      *cp == '_' || // allowed char
++      *cp == '-' || // allowed char     
++      *cp == '+' ||   // allow all sibling in a single tag
++      *cp == '>' ||   // allow all child in a single tag 
++      *cp == '{' ||   // allow the start of the declaration
++      *cp == '.' ||   // allow classes and selectors
++      *cp == ',' ||   // allow multiple declarations
++      *cp == ':' ||   // allow pseudo classes
++      *cp == '*' ||   // allow globs as P + *
++      *cp == '#';   // allow ids 
++}
++
++static CssParserState parseCssDeclaration( const unsigned char **position, cssKind kind )
++{
++  vString *name = vStringNew ();
++  const unsigned char *cp = *position;
++
++  // pick to the end of line including children and sibling
++  // if declaration is multiline go for the next line 
++  while ( isCssDeclarationAllowedChar(cp) || 
++      *cp == '\0' )   // track the end of line into the loop
++  {
++    if( (int) *cp == '\0' )
++    { 
++      cp = fileReadLine ();
++      if( cp == NULL ){
++        makeCssSimpleTag(name, kind, TRUE);
++        *position = cp;
++        return P_STATE_AT_END;
++      }
++    }
++    else if( *cp == ',' )
++    {
++      makeCssSimpleTag(name, kind, TRUE);
++      *position = ++cp;
++      return P_STATE_NONE;
++    }
++    else if( *cp == '{' )
++    {
++      makeCssSimpleTag(name, kind, TRUE);
++      *position = ++cp;
++      return P_STATE_IN_DEFINITION;
++    }
++
++    vStringPut (name, (int) *cp);
++    ++cp;
++  }
++  
++  makeCssSimpleTag(name, kind, TRUE);
++  *position = cp;
++
++  return P_STATE_NONE;
++}
++
++static CssParserState parseCssLine( const unsigned char *line, CssParserState state )
++{
++  vString *aux;
++
++  while( *line != '\0' ) // fileReadLine returns NULL terminated strings
++  {
++    while (isspace ((int) *line))
++      ++line;
++    switch( state )
++    {
++      case P_STATE_NONE:
++        // pick first char if alphanumeric is a selector
++        if( isalnum ((int) *line) )
++          state = parseCssDeclaration( &line, K_SELECTOR );
++        else if( *line == '.' ) // a class
++          state = parseCssDeclaration( &line, K_CLASS );
++        else if( *line == '#' ) // an id
++          state = parseCssDeclaration( &line, K_ID );
++        else if( *line == '@' ) // at-rules, we'll ignore them
++        {
++          ++line;
++          aux = vStringNew();
++          while( !isspace((int) *line) )
++          {
++            vStringPut (aux, (int) *line);
++            ++line;         
++          }
++          vStringTerminate (aux);
++          if( strcmp( aux->buffer, "media" ) == 0 )
++            state = P_STATE_IN_MEDIA;
++          else if ( strcmp( aux->buffer, "import" ) == 0 )
++            state = P_STATE_IN_IMPORT;
++          else if ( strcmp( aux->buffer, "namespace" ) == 0 )
++            state = P_STATE_IN_NAMESPACE; 
++          else if ( strcmp( aux->buffer, "page" ) == 0 )
++            state = P_STATE_IN_PAGE;
++          else if ( strcmp( aux->buffer, "font-face" ) == 0 )
++            state = P_STATE_IN_FONTFACE;
++          vStringDelete (aux);
++        }
++        else if( *line == '*' && *(line-1) == '/' ) // multi-line comment
++          state = P_STATE_IN_COMMENT;
++      break;
++      case P_STATE_IN_COMMENT:
++        if( *line == '/' && *(line-1) == '*')
++          state = P_STATE_NONE;
++      break;
++      case  P_STATE_IN_SINGLE_STRING: 
++        if( *line == '\'' && *(line-1) != '\\' )
++          state = P_STATE_IN_DEFINITION; // PAGE, FONTFACE and DEFINITION are treated the same way
++      break;
++      case  P_STATE_IN_DOUBLE_STRING:
++        if( *line=='"' && *(line-1) != '\\' )
++          state = P_STATE_IN_DEFINITION; // PAGE, FONTFACE and DEFINITION are treated the same way
++      break;
++      case  P_STATE_IN_MEDIA:
++        // skip to start of media body or line end
++        while( *line != '{' )
++        {
++          if( *line == '\0' )
++            break;
++          ++line;
++        }
++        if( *line == '{' )
++            state = P_STATE_NONE;
++      break;
++      case  P_STATE_IN_IMPORT:
++      case  P_STATE_IN_NAMESPACE:
++        // skip to end of declaration or line end
++        while( *line != ';' )
++        {
++          if( *line == '\0' )
++            break;
++          ++line;
++        }
++        if( *line == ';' )
++          state = P_STATE_NONE;
++      break;
++      case P_STATE_IN_PAGE:
++      case P_STATE_IN_FONTFACE:
++      case P_STATE_IN_DEFINITION:
++        if( *line == '}' )
++          state = P_STATE_NONE;
++        else if( *line == '\'' )
++          state = P_STATE_IN_SINGLE_STRING;
++        else if( *line == '"' )
++          state = P_STATE_IN_DOUBLE_STRING;
++      break;
++      case P_STATE_AT_END:
++        return state;
++      break;
++    }   
++    line++;
++  }
++  return state;
++}
++
++static void findCssTags (void)
++{
++    const unsigned char *line;
++  CssParserState state = P_STATE_NONE;
++
++    while ( (line = fileReadLine ()) != NULL )
++    {
++    state = parseCssLine( line, state );
++    if( state==P_STATE_AT_END ) return;
++    }    
++}
++
++/* parser definition */
++extern parserDefinition* CssParser (void)
++{
++    static const char *const extensions [] = { "css", NULL };
++    parserDefinition* def = parserNew ("CSS");
++    def->kinds      = CssKinds;
++    def->kindCount  = KIND_COUNT (CssKinds);
++    def->extensions = extensions;
++    def->parser     = findCssTags;
++    return def;
++}
++
+diff -up ctags-5.8/parsers.h.me ctags-5.8/parsers.h
+--- ctags-5.8/parsers.h.me	2012-02-08 13:56:46.000000000 +0100
++++ ctags-5.8/parsers.h	2012-02-08 13:57:25.000000000 +0100
+@@ -26,6 +26,7 @@
+ 	CppParser, \
+ 	CsharpParser, \
+ 	CobolParser, \
++	CssParser, \
+ 	DosBatchParser, \
+ 	EiffelParser, \
+ 	ErlangParser, \
+diff -up ctags-5.8/source.mak.me ctags-5.8/source.mak
+--- ctags-5.8/source.mak.me	2012-02-08 13:58:02.000000000 +0100
++++ ctags-5.8/source.mak	2012-02-08 13:58:42.000000000 +0100
+@@ -17,6 +17,7 @@ SOURCES = \
+ 	beta.c \
+ 	c.c \
+ 	cobol.c \
++	css.c \
+ 	dosbatch.c \
+ 	eiffel.c \
+ 	entry.c \
+@@ -79,6 +80,7 @@ OBJECTS = \
+ 	beta.$(OBJEXT) \
+ 	c.$(OBJEXT) \
+ 	cobol.$(OBJEXT) \
++	css.$(OBJEXT) \
+ 	dosbatch.$(OBJEXT) \
+ 	eiffel.$(OBJEXT) \
+ 	entry.$(OBJEXT) \
diff --git a/ctags.spec b/ctags.spec
index bd181e5..dedda27 100644
--- a/ctags.spec
+++ b/ctags.spec
@@ -1,13 +1,14 @@
 Summary: A C programming language indexing and/or cross-reference tool
 Name: ctags
 Version: 5.8
-Release: 4%{?dist}
+Release: 5%{?dist}
 License: GPLv2+ or Public Domain
 Group: Development/Tools
+URL: http://ctags.sourceforge.net/
 Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz
 Patch0: ctags-5.7-destdir.patch
 Patch1: ctags-5.7-segment-fault.patch
-URL: http://ctags.sourceforge.net/
+Patch2: ctags-5.8-css.patch
 Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 %description
@@ -43,6 +44,7 @@ Note: some command line options is not compatible with GNU etags.
 %setup -q
 %patch0 -p1 -b .destdir
 %patch1 -p1 -b .crash
+%patch2 -p1 -b .css-support
 
 %build
 %configure
@@ -85,6 +87,9 @@ rm -rf %{buildroot}
 %{_mandir}/man1/etags.%{name}.1*
 
 %changelog
+* Wed Feb 08 2012 Than Ngo <than at redhat.com> - 5.8-5
+- bz#786451, add css support
+
 * Fri Jan 13 2012 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 5.8-4
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
 


More information about the scm-commits mailing list