Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F9349292
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Subscribers
None
View Options
diff --git a/Test/Package.pm b/Test/Package.pm
index 4913c7f1..c9444f26 100644
--- a/Test/Package.pm
+++ b/Test/Package.pm
@@ -1,52 +1,56 @@
# This file is intended to test package keyword support along with
# multi-line subroutine definitions, like this:
# sub
#
# somefunction
# {...
+package Test::One;
+
+package Test::One::Two;
+
package Test;
use strict;
use warnings;
sub
init {
}
use constant
CONST => 1;
=head2 quo
This is 'quo' subroutine
=cut
sub quo;
quo;
Test::quo;
sub quo {
goto END;
die;
END:
print "END!\n";
return;
}
sub xuz :lvalue;
sub xtz (&@;$) :lvalue;
sub
# This should create a tag
dude
{
1;
}
1;
diff --git a/perl.c b/perl.c
index d3027960..58797a48 100644
--- a/perl.c
+++ b/perl.c
@@ -1,350 +1,350 @@
/*
* $Id$
*
* Copyright (c) 2000-2003, Darren Hiebert
*
* 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 PERL language
* files.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <string.h>
#include "options.h"
#include "read.h"
#include "routines.h"
#include "vstring.h"
#define TRACE_PERL_C 0
#define TRACE if (TRACE_PERL_C) printf("perl.c:%d: ", __LINE__), printf
/*
* DATA DEFINITIONS
*/
typedef enum {
K_NONE = -1,
K_CONSTANT,
K_FORMAT,
K_LABEL,
K_PACKAGE,
K_SUBROUTINE,
K_SUBROUTINE_DECLARATION
} perlKind;
static kindOption PerlKinds [] = {
{ TRUE, 'c', "constant", "constants" },
{ TRUE, 'f', "format", "formats" },
{ TRUE, 'l', "label", "labels" },
{ TRUE, 'p', "package", "packages" },
{ TRUE, 's', "subroutine", "subroutines" },
{ FALSE, 'd', "subroutine declaration", "subroutine declarations" },
};
/*
* FUNCTION DEFINITIONS
*/
static boolean isIdentifier1 (int c)
{
return (boolean) (isalpha (c) || c == '_');
}
static boolean isIdentifier (int c)
{
return (boolean) (isalnum (c) || c == '_');
}
static boolean isPodWord (const char *word)
{
boolean result = FALSE;
if (isalpha (*word))
{
const char *const pods [] = {
"head1", "head2", "head3", "head4", "over", "item", "back",
"pod", "begin", "end", "for"
};
const size_t count = sizeof (pods) / sizeof (pods [0]);
const char *white = strpbrk (word, " \t");
const size_t len = (white!=NULL) ? (size_t)(white-word) : strlen (word);
char *const id = (char*) eMalloc (len + 1);
size_t i;
strncpy (id, word, len);
id [len] = '\0';
for (i = 0 ; i < count && ! result ; ++i)
{
if (strcmp (id, pods [i]) == 0)
result = TRUE;
}
eFree (id);
}
return result;
}
/*
* Perl subroutine declaration may look like one of the following:
*
* sub abc;
* sub abc :attr;
* sub abc (proto);
* sub abc (proto) :attr;
*
* Note that there may be more than one attribute. Attributes may
* have things in parentheses (they look like arguments). Anything
* inside of those parentheses goes. Prototypes may contain semi-colons.
* The matching end when we encounter (outside of any parentheses) either
* a semi-colon (that'd be a declaration) or an left curly brace
* (definition).
*
* This is pretty complicated parsing (plus we all know that only perl can
* parse Perl), so we are only promising best effort here.
*
* If we can't determine what this is (due to a file ending, for example),
* we will return FALSE.
*/
static boolean isSubroutineDeclaration (const unsigned char *cp)
{
boolean attr = FALSE;
int nparens = 0;
do {
for ( ; *cp; ++cp) {
SUB_DECL_SWITCH:
switch (*cp) {
case ':':
if (nparens)
break;
else if (TRUE == attr)
return FALSE; /* Invalid attribute name */
else
attr = TRUE;
break;
case '(':
++nparens;
break;
case ')':
--nparens;
break;
case ' ':
case '\t':
break;
case ';':
if (!nparens)
return TRUE;
case '{':
if (!nparens)
return FALSE;
default:
if (attr) {
if (isIdentifier1(*cp)) {
cp++;
while (isIdentifier (*cp))
cp++;
attr = FALSE;
goto SUB_DECL_SWITCH; /* Instead of --cp; */
} else {
return FALSE;
}
} else if (nparens) {
break;
} else {
return FALSE;
}
}
}
} while (NULL != (cp = fileReadLine ()));
return FALSE;
}
/* Algorithm adapted from from GNU etags.
* Perl support by Bart Robinson <lomew@cs.utah.edu>
* Perl sub names: look for /^ [ \t\n]sub [ \t\n]+ [^ \t\n{ (]+/
*/
static void findPerlTags (void)
{
vString *name = vStringNew ();
vString *package = NULL;
boolean skipPodDoc = FALSE;
const unsigned char *line;
while ((line = fileReadLine ()) != NULL)
{
boolean spaceRequired = FALSE;
boolean qualified = FALSE;
const unsigned char *cp = line;
perlKind kind = K_NONE;
if (skipPodDoc)
{
if (strncmp ((const char*) line, "=cut", (size_t) 4) == 0)
skipPodDoc = FALSE;
continue;
}
else if (line [0] == '=')
{
skipPodDoc = isPodWord ((const char*)line + 1);
continue;
}
else if (strcmp ((const char*) line, "__DATA__") == 0)
break;
else if (strcmp ((const char*) line, "__END__") == 0)
break;
else if (line [0] == '#')
continue;
while (isspace (*cp))
cp++;
if (strncmp((const char*) cp, "sub", (size_t) 3) == 0)
{
TRACE("this looks like a sub\n");
cp += 3;
kind = K_SUBROUTINE;
spaceRequired = TRUE;
qualified = TRUE;
}
else if (strncmp((const char*) cp, "use", (size_t) 3) == 0)
{
cp += 3;
if (!isspace(*cp))
continue;
while (*cp && isspace (*cp))
++cp;
if (strncmp((const char*) cp, "constant", (size_t) 8) != 0)
continue;
cp += 8;
kind = K_CONSTANT;
spaceRequired = TRUE;
qualified = TRUE;
}
else if (strncmp((const char*) cp, "package", (size_t) 7) == 0)
{
/* This will point to space after 'package' so that a tag
can be made */
const unsigned char *space = cp += 7;
if (package == NULL)
package = vStringNew ();
else
vStringClear (package);
while (isspace (*cp))
cp++;
while ((int) *cp != ';' && !isspace ((int) *cp))
{
vStringPut (package, (int) *cp);
cp++;
}
vStringCatS (package, "::");
cp = space; /* Rewind */
kind = K_PACKAGE;
spaceRequired = TRUE;
qualified = TRUE;
}
else if (strncmp((const char*) cp, "format", (size_t) 6) == 0)
{
cp += 6;
kind = K_FORMAT;
spaceRequired = TRUE;
qualified = TRUE;
}
else
{
if (isIdentifier1 (*cp))
{
const unsigned char *p = cp;
while (isIdentifier (*p))
++p;
if ((int) *p == ':' && (int) *(p + 1) != ':')
kind = K_LABEL;
}
}
if (kind != K_NONE)
{
TRACE("cp0: %s\n", (const char *) cp);
if (spaceRequired && *cp && !isspace (*cp))
continue;
TRACE("cp1: %s\n", (const char *) cp);
while (isspace (*cp))
cp++;
while (!*cp || '#' == *cp) { /* Gobble up empty lines
and comments */
cp = fileReadLine ();
if (!cp)
goto END_MAIN_WHILE;
while (isspace (*cp))
cp++;
}
- while (isIdentifier (*cp))
+ while (isIdentifier (*cp) || (K_PACKAGE == kind && ':' == *cp))
{
vStringPut (name, (int) *cp);
cp++;
}
if (K_FORMAT == kind &&
vStringLength (name) == 0 && /* cp did not advance */
'=' == *cp)
{
/* format's name is optional. If it's omitted, 'STDOUT'
is assumed. */
vStringCatS (name, "STDOUT");
}
vStringTerminate (name);
TRACE("name: %s\n", name->buffer);
if (K_SUBROUTINE == kind && TRUE == isSubroutineDeclaration(cp))
{
if (TRUE == PerlKinds[K_SUBROUTINE_DECLARATION].enabled) {
kind = K_SUBROUTINE_DECLARATION;
} else {
vStringClear (name);
continue;
}
}
if (vStringLength (name) > 0)
{
makeSimpleTag (name, PerlKinds, kind);
if (Option.include.qualifiedTags && qualified &&
package != NULL && vStringLength (package) > 0)
{
vString *const qualifiedName = vStringNew ();
vStringCopy (qualifiedName, package);
vStringCat (qualifiedName, name);
makeSimpleTag (qualifiedName, PerlKinds, kind);
vStringDelete (qualifiedName);
}
}
vStringClear (name);
}
}
END_MAIN_WHILE:
vStringDelete (name);
if (package != NULL)
vStringDelete (package);
}
extern parserDefinition* PerlParser (void)
{
static const char *const extensions [] = { "pl", "pm", "plx", "perl", NULL };
parserDefinition* def = parserNew ("Perl");
def->kinds = PerlKinds;
def->kindCount = KIND_COUNT (PerlKinds);
def->extensions = extensions;
def->parser = findPerlTags;
return def;
}
/* vi:set tabstop=4 shiftwidth=4 noexpandtab: */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Jul 4 2025, 7:15 PM (6 w, 2 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3452658
Attached To
rPUC universal-ctags debian packaging
Event Timeline
Log In to Comment