diff --git a/ctags-5.8-ocaml-crash.patch b/ctags-5.8-ocaml-crash.patch new file mode 100644 index 0000000..8263cca --- /dev/null +++ b/ctags-5.8-ocaml-crash.patch @@ -0,0 +1,251 @@ +diff -up ctags-5.8/ocaml.c.me ctags-5.8/ocaml.c +--- ctags-5.8/ocaml.c.me 2012-08-02 12:42:21.652211192 +0200 ++++ ctags-5.8/ocaml.c 2012-08-02 13:06:59.751283639 +0200 +@@ -72,6 +72,7 @@ typedef enum { + OcaKEYWORD_if, + OcaKEYWORD_in, + OcaKEYWORD_let, ++ OcaKEYWORD_value, + OcaKEYWORD_match, + OcaKEYWORD_method, + OcaKEYWORD_module, +@@ -145,7 +146,7 @@ static const ocaKeywordDesc OcamlKeyword + { "try" , OcaKEYWORD_try }, + { "type" , OcaKEYWORD_type }, + { "val" , OcaKEYWORD_val }, +- { "value" , OcaKEYWORD_let }, /* just to handle revised syntax */ ++ { "value" , OcaKEYWORD_value }, /* just to handle revised syntax */ + { "virtual" , OcaKEYWORD_virtual }, + { "while" , OcaKEYWORD_while }, + { "with" , OcaKEYWORD_with }, +@@ -297,7 +298,6 @@ static void eatComment (lexingState * st + if (st->cp == NULL) + return; + c = st->cp; +- continue; + } + /* we've reached the end of the comment */ + else if (*c == ')' && lastIsStar) +@@ -308,13 +308,33 @@ static void eatComment (lexingState * st + { + st->cp = c; + eatComment (st); ++ + c = st->cp; ++ if (c == NULL) ++ return; ++ + lastIsStar = FALSE; ++ c++; + } ++ /* OCaml has a rule which says : ++ * ++ * "Comments do not occur inside string or character literals. ++ * Nested comments are handled correctly." ++ * ++ * So if we encounter a string beginning, we must parse it to ++ * get a good comment nesting (bug ID: 3117537) ++ */ ++ else if (*c == '"') ++ { ++ st->cp = c; ++ eatString (st); ++ c = st->cp; ++ } + else ++ { + lastIsStar = '*' == *c; +- +- c++; ++ c++; ++ } + } + + st->cp = c; +@@ -554,8 +574,7 @@ static int getLastNamedIndex ( void ) + + for (i = stackIndex - 1; i >= 0; --i) + { +- if (stack[i].contextName->buffer && +- strlen (stack[i].contextName->buffer) > 0) ++ if (vStringLength (stack[i].contextName) > 0) + { + return i; + } +@@ -866,6 +885,11 @@ static void prepareTag (tagEntryInfo * t + tag->kindName = OcamlKinds[kind].name; + tag->kind = OcamlKinds[kind].letter; + ++ if (kind == K_MODULE) ++ { ++ tag->lineNumberEntry = TRUE; ++ tag->lineNumber = 1; ++ } + parentIndex = getLastNamedIndex (); + if (parentIndex >= 0) + { +@@ -880,9 +904,12 @@ static void prepareTag (tagEntryInfo * t + * more information to it in the future */ + static void addTag (vString * const ident, int kind) + { +- tagEntryInfo toCreate; +- prepareTag (&toCreate, ident, kind); +- makeTagEntry (&toCreate); ++ if (OcamlKinds [kind].enabled && ident != NULL && vStringLength (ident) > 0) ++ { ++ tagEntryInfo toCreate; ++ prepareTag (&toCreate, ident, kind); ++ makeTagEntry (&toCreate); ++ } + } + + boolean needStrongPoping = FALSE; +@@ -942,15 +969,17 @@ static void typeRecord (vString * const + } + + /* handle : +- * exception ExceptionName ... */ ++ * exception ExceptionName of ... */ + static void exceptionDecl (vString * const ident, ocaToken what) + { + if (what == OcaIDENTIFIER) + { + addTag (ident, K_EXCEPTION); + } +- /* don't know what to do on else... */ +- ++ else /* probably ill-formed, give back to global scope */ ++ { ++ globalScope (ident, what); ++ } + toDoNext = &globalScope; + } + +@@ -1006,7 +1035,6 @@ static void constructorValidation (vStri + */ + static void typeDecl (vString * const ident, ocaToken what) + { +- + switch (what) + { + /* parameterized */ +@@ -1046,7 +1074,6 @@ static void typeDecl (vString * const id + * let typeRecord handle it. */ + static void typeSpecification (vString * const ident, ocaToken what) + { +- + switch (what) + { + case OcaIDENTIFIER: +@@ -1243,8 +1270,14 @@ static void localLet (vString * const id + * than the let definitions. + * Used after a match ... with, or a function ... or fun ... + * because their syntax is similar. */ +-static void matchPattern (vString * const UNUSED (ident), ocaToken what) ++static void matchPattern (vString * const ident, ocaToken what) + { ++ /* keep track of [], as it ++ * can be used in patterns and can ++ * mean the end of match expression in ++ * revised syntax */ ++ static int braceCount = 0; ++ + switch (what) + { + case Tok_To: +@@ -1252,6 +1285,14 @@ static void matchPattern (vString * cons + toDoNext = &mayRedeclare; + break; + ++ case Tok_BRL: ++ braceCount++; ++ break; ++ ++ case OcaKEYWORD_value: ++ popLastNamed (); ++ globalScope (ident, what); ++ break; + + case OcaKEYWORD_in: + popLastNamed (); +@@ -1269,6 +1310,11 @@ static void mayRedeclare (vString * cons + { + switch (what) + { ++ case OcaKEYWORD_value: ++ /* let globalScope handle it */ ++ globalScope (ident, what); ++ break; ++ + case OcaKEYWORD_let: + case OcaKEYWORD_val: + toDoNext = localLet; +@@ -1388,6 +1434,7 @@ static void classSpecif (vString * const + * nearly a copy/paste of globalLet. */ + static void methodDecl (vString * const ident, ocaToken what) + { ++ + switch (what) + { + case Tok_PARL: +@@ -1435,6 +1482,7 @@ vString *lastModule; + */ + static void moduleSpecif (vString * const ident, ocaToken what) + { ++ + switch (what) + { + case OcaKEYWORD_functor: +@@ -1566,7 +1614,7 @@ static void globalScope (vString * const + { + /* Do not touch, this is used only by the global scope + * to handle an 'and' */ +- static parseNext previousParser = NULL; ++ static parseNext previousParser = &globalScope; + + switch (what) + { +@@ -1608,6 +1656,7 @@ static void globalScope (vString * const + /* val is mixed with let as global + * to be able to handle mli & new syntax */ + case OcaKEYWORD_val: ++ case OcaKEYWORD_value: + case OcaKEYWORD_let: + cleanupPreviousParser (); + toDoNext = &globalLet; +@@ -1617,7 +1666,7 @@ static void globalScope (vString * const + case OcaKEYWORD_exception: + cleanupPreviousParser (); + toDoNext = &exceptionDecl; +- previousParser = NULL; ++ previousParser = &globalScope; + break; + + /* must be a #line directive, discard the +@@ -1769,7 +1818,7 @@ static void computeModuleName ( void ) + if (isLowerAlpha (moduleName->buffer[0])) + moduleName->buffer[0] += ('A' - 'a'); + +- makeSimpleTag (moduleName, OcamlKinds, K_MODULE); ++ addTag (moduleName, K_MODULE); + vStringDelete (moduleName); + } + +@@ -1779,6 +1828,7 @@ static void initStack ( void ) + int i; + for (i = 0; i < OCAML_MAX_STACK_SIZE; ++i) + stack[i].contextName = vStringNew (); ++ stackIndex = 0; + } + + static void clearStack ( void ) +@@ -1794,8 +1844,8 @@ static void findOcamlTags (void) + lexingState st; + ocaToken tok; + +- computeModuleName (); + initStack (); ++ computeModuleName (); + tempIdent = vStringNew (); + lastModule = vStringNew (); + lastClass = vStringNew (); diff --git a/ctags.spec b/ctags.spec index b643b6d..43827ff 100644 --- a/ctags.spec +++ b/ctags.spec @@ -1,7 +1,7 @@ Summary: A C programming language indexing and/or cross-reference tool Name: ctags Version: 5.8 -Release: 6%{?dist} +Release: 7%{?dist} License: GPLv2+ or Public Domain Group: Development/Tools URL: http://ctags.sourceforge.net/ @@ -9,6 +9,7 @@ Source0: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz Patch0: ctags-5.7-destdir.patch Patch1: ctags-5.7-segment-fault.patch Patch2: ctags-5.8-css.patch +Patch3: ctags-5.8-ocaml-crash.patch Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %description @@ -45,6 +46,7 @@ Note: some command line options is not compatible with GNU etags. %patch0 -p1 -b .destdir %patch1 -p1 -b .crash %patch2 -p1 -b .css-support +%patch3 -p1 -b .ocaml-crash %build %configure @@ -87,6 +89,9 @@ rm -rf %{buildroot} %{_mandir}/man1/etags.%{name}.1* %changelog +* Thu Aug 02 2012 Than Ngo - 5.8-7 +- backport from upstream to fix several crashes in ocaml + * Wed Jul 18 2012 Fedora Release Engineering - 5.8-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild