13ae02089SMasatake YAMATO /*
23ae02089SMasatake YAMATO * Copyright (c) 2000-2003, Darren Hiebert
33ae02089SMasatake YAMATO *
43ae02089SMasatake YAMATO * This source code is released for free distribution under the terms of the
50ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
63ae02089SMasatake YAMATO *
73ae02089SMasatake YAMATO * This module contains functions for generating tags for PERL language
83ae02089SMasatake YAMATO * files.
93ae02089SMasatake YAMATO */
103ae02089SMasatake YAMATO
113ae02089SMasatake YAMATO /*
123ae02089SMasatake YAMATO * INCLUDE FILES
133ae02089SMasatake YAMATO */
143ae02089SMasatake YAMATO #include "general.h" /* must always come first */
153ae02089SMasatake YAMATO
163ae02089SMasatake YAMATO #include <string.h>
173ae02089SMasatake YAMATO
183ae02089SMasatake YAMATO #include "entry.h"
19cd677fe6SMasatake YAMATO #include "perl.h"
209092a057SMasatake YAMATO #include "promise.h"
213ae02089SMasatake YAMATO #include "read.h"
223ae02089SMasatake YAMATO #include "routines.h"
23acae9f99SDmitri Tikhonov #include "selectors.h"
24cd677fe6SMasatake YAMATO #include "subparser.h"
253ae02089SMasatake YAMATO #include "vstring.h"
2635c59e96SMasatake YAMATO #include "xtag.h"
273ae02089SMasatake YAMATO
283ae02089SMasatake YAMATO #define TRACE_PERL_C 0
293ae02089SMasatake YAMATO #define TRACE if (TRACE_PERL_C) printf("perl.c:%d: ", __LINE__), printf
303ae02089SMasatake YAMATO
313ae02089SMasatake YAMATO /*
323ae02089SMasatake YAMATO * DATA DEFINITIONS
333ae02089SMasatake YAMATO */
34cd677fe6SMasatake YAMATO typedef enum PerlKindType perlKind;
35b02a66cdSMasatake YAMATO typedef enum PerlModuleRoleType perlModuleRole;
36b02a66cdSMasatake YAMATO
37b02a66cdSMasatake YAMATO static roleDefinition PerlModuleRoles [] = {
38b02a66cdSMasatake YAMATO { true, "used", "specified in `use' built-in function" },
3950c83de6SMasatake YAMATO { true, "unused", "specified in `no' built-in function" },
40b02a66cdSMasatake YAMATO };
413ae02089SMasatake YAMATO
42*08bf1b99SMasatake YAMATO typedef enum {
43*08bf1b99SMasatake YAMATO R_HEREDOC_ENDLABEL,
44*08bf1b99SMasatake YAMATO } perlHeredocRole;
45*08bf1b99SMasatake YAMATO
46*08bf1b99SMasatake YAMATO static roleDefinition PerlHeredocRoles [] = {
47*08bf1b99SMasatake YAMATO { true, "endmarker", "end marker" },
48*08bf1b99SMasatake YAMATO };
49*08bf1b99SMasatake YAMATO
50e112e8abSMasatake YAMATO static kindDefinition PerlKinds [] = {
51ce990805SThomas Braun { true, 'c', "constant", "constants" },
52ce990805SThomas Braun { true, 'f', "format", "formats" },
53ce990805SThomas Braun { true, 'l', "label", "labels" },
54ce990805SThomas Braun { true, 'p', "package", "packages" },
55ce990805SThomas Braun { true, 's', "subroutine", "subroutines" },
56ce990805SThomas Braun { false, 'd', "subroutineDeclaration", "subroutine declarations" },
57b02a66cdSMasatake YAMATO { false, 'M', "module", "modules",
58b02a66cdSMasatake YAMATO .referenceOnly = true, ATTACH_ROLES(PerlModuleRoles)},
59*08bf1b99SMasatake YAMATO { false, 'h', "heredoc", "marker for here document",
60*08bf1b99SMasatake YAMATO .referenceOnly = false, ATTACH_ROLES (PerlHeredocRoles) },
61*08bf1b99SMasatake YAMATO };
62*08bf1b99SMasatake YAMATO
63*08bf1b99SMasatake YAMATO struct hereDocMarker {
64*08bf1b99SMasatake YAMATO vString *marker;
65*08bf1b99SMasatake YAMATO bool indented;
66*08bf1b99SMasatake YAMATO int corkIndex;
67*08bf1b99SMasatake YAMATO };
68*08bf1b99SMasatake YAMATO
69*08bf1b99SMasatake YAMATO struct hereDocMarkerManager {
70*08bf1b99SMasatake YAMATO ptrArray *markers;
71*08bf1b99SMasatake YAMATO size_t current;
723ae02089SMasatake YAMATO };
733ae02089SMasatake YAMATO
743ae02089SMasatake YAMATO /*
753ae02089SMasatake YAMATO * FUNCTION DEFINITIONS
763ae02089SMasatake YAMATO */
773ae02089SMasatake YAMATO
notifyEnteringPod()78d7ad8c78SMasatake YAMATO static void notifyEnteringPod ()
79cd677fe6SMasatake YAMATO {
80cd677fe6SMasatake YAMATO subparser *sub;
81cd677fe6SMasatake YAMATO
82cd677fe6SMasatake YAMATO foreachSubparser (sub, false)
83cd677fe6SMasatake YAMATO {
84cd677fe6SMasatake YAMATO perlSubparser *perlsub = (perlSubparser *)sub;
85cd677fe6SMasatake YAMATO if (perlsub->enteringPodNotify)
86cd677fe6SMasatake YAMATO {
87cd677fe6SMasatake YAMATO enterSubparser (sub);
88cd677fe6SMasatake YAMATO perlsub->enteringPodNotify (perlsub);
89cd677fe6SMasatake YAMATO leaveSubparser ();
90cd677fe6SMasatake YAMATO }
91cd677fe6SMasatake YAMATO }
92cd677fe6SMasatake YAMATO }
93cd677fe6SMasatake YAMATO
notifyLeavingPod()94cd677fe6SMasatake YAMATO static void notifyLeavingPod ()
95cd677fe6SMasatake YAMATO {
96cd677fe6SMasatake YAMATO subparser *sub;
97cd677fe6SMasatake YAMATO
98cd677fe6SMasatake YAMATO foreachSubparser (sub, false)
99cd677fe6SMasatake YAMATO {
100cd677fe6SMasatake YAMATO perlSubparser *perlsub = (perlSubparser *)sub;
101cd677fe6SMasatake YAMATO if (perlsub->leavingPodNotify)
102cd677fe6SMasatake YAMATO {
103cd677fe6SMasatake YAMATO enterSubparser (sub);
104cd677fe6SMasatake YAMATO perlsub->leavingPodNotify (perlsub);
105cd677fe6SMasatake YAMATO leaveSubparser ();
106cd677fe6SMasatake YAMATO }
107cd677fe6SMasatake YAMATO }
108cd677fe6SMasatake YAMATO }
109cd677fe6SMasatake YAMATO
notifyFindingQuotedWord(int moduleIndex,const char * qwd)1105be4c343SMasatake YAMATO static void notifyFindingQuotedWord (int moduleIndex,
1115be4c343SMasatake YAMATO const char *qwd)
1125be4c343SMasatake YAMATO {
1135be4c343SMasatake YAMATO subparser *sub;
1145be4c343SMasatake YAMATO
1155be4c343SMasatake YAMATO foreachSubparser (sub, false)
1165be4c343SMasatake YAMATO {
1175be4c343SMasatake YAMATO perlSubparser *perlsub = (perlSubparser *)sub;
1185be4c343SMasatake YAMATO if (perlsub->findingQuotedWordNotify)
1195be4c343SMasatake YAMATO {
1205be4c343SMasatake YAMATO enterSubparser (sub);
1215be4c343SMasatake YAMATO perlsub->findingQuotedWordNotify (perlsub,
1225be4c343SMasatake YAMATO moduleIndex,
1235be4c343SMasatake YAMATO qwd);
1245be4c343SMasatake YAMATO leaveSubparser ();
1255be4c343SMasatake YAMATO }
1265be4c343SMasatake YAMATO }
1275be4c343SMasatake YAMATO }
1285be4c343SMasatake YAMATO
isIdentifier1(int c)129ce990805SThomas Braun static bool isIdentifier1 (int c)
1303ae02089SMasatake YAMATO {
131ce990805SThomas Braun return (bool) (isalpha (c) || c == '_');
1323ae02089SMasatake YAMATO }
1333ae02089SMasatake YAMATO
isIdentifier(int c)134ce990805SThomas Braun static bool isIdentifier (int c)
1353ae02089SMasatake YAMATO {
136ce990805SThomas Braun return (bool) (isalnum (c) || c == '_');
1373ae02089SMasatake YAMATO }
1383ae02089SMasatake YAMATO
isPodWord(const char * word)139ce990805SThomas Braun static bool isPodWord (const char *word)
1403ae02089SMasatake YAMATO {
1413ae02089SMasatake YAMATO /* Perl POD words are three to eight characters in size. We use this
1423ae02089SMasatake YAMATO * fact to find (or not find) the right side of the word and then
1433ae02089SMasatake YAMATO * perform comparisons, if necessary, of POD words of that size.
1443ae02089SMasatake YAMATO */
1453ae02089SMasatake YAMATO size_t len;
1463ae02089SMasatake YAMATO for (len = 0; len < 9; ++len)
1473ae02089SMasatake YAMATO if ('\0' == word[len] || ' ' == word[len] || '\t' == word[len])
1483ae02089SMasatake YAMATO break;
1493ae02089SMasatake YAMATO switch (len) {
1503ae02089SMasatake YAMATO case 3:
1513ae02089SMasatake YAMATO return 0 == strncmp(word, "end", 3)
1523ae02089SMasatake YAMATO || 0 == strncmp(word, "for", 3)
1533ae02089SMasatake YAMATO || 0 == strncmp(word, "pod", 3);
1543ae02089SMasatake YAMATO case 4:
1553ae02089SMasatake YAMATO return 0 == strncmp(word, "back", 4)
1563ae02089SMasatake YAMATO || 0 == strncmp(word, "item", 4)
1573ae02089SMasatake YAMATO || 0 == strncmp(word, "over", 4);
1583ae02089SMasatake YAMATO case 5:
1593ae02089SMasatake YAMATO return 0 == strncmp(word, "begin", 5)
1603ae02089SMasatake YAMATO || 0 == strncmp(word, "head1", 5)
1613ae02089SMasatake YAMATO || 0 == strncmp(word, "head2", 5)
1623ae02089SMasatake YAMATO || 0 == strncmp(word, "head3", 5)
1633ae02089SMasatake YAMATO || 0 == strncmp(word, "head4", 5);
1643ae02089SMasatake YAMATO case 8:
1653ae02089SMasatake YAMATO return 0 == strncmp(word, "encoding", 8);
1663ae02089SMasatake YAMATO default:
167ce990805SThomas Braun return false;
1683ae02089SMasatake YAMATO }
1693ae02089SMasatake YAMATO }
1703ae02089SMasatake YAMATO
1713ae02089SMasatake YAMATO /*
1723ae02089SMasatake YAMATO * Perl subroutine declaration may look like one of the following:
1733ae02089SMasatake YAMATO *
1743ae02089SMasatake YAMATO * sub abc;
1753ae02089SMasatake YAMATO * sub abc :attr;
1763ae02089SMasatake YAMATO * sub abc (proto);
1773ae02089SMasatake YAMATO * sub abc (proto) :attr;
1783ae02089SMasatake YAMATO *
1793ae02089SMasatake YAMATO * Note that there may be more than one attribute. Attributes may
1803ae02089SMasatake YAMATO * have things in parentheses (they look like arguments). Anything
1813ae02089SMasatake YAMATO * inside of those parentheses goes. Prototypes may contain semi-colons.
1823ae02089SMasatake YAMATO * The matching end when we encounter (outside of any parentheses) either
1833ae02089SMasatake YAMATO * a semi-colon (that'd be a declaration) or an left curly brace
1843ae02089SMasatake YAMATO * (definition).
1853ae02089SMasatake YAMATO *
1863ae02089SMasatake YAMATO * This is pretty complicated parsing (plus we all know that only perl can
1873ae02089SMasatake YAMATO * parse Perl), so we are only promising best effort here.
1883ae02089SMasatake YAMATO *
1893ae02089SMasatake YAMATO * If we can't determine what this is (due to a file ending, for example),
190ce990805SThomas Braun * we will return false.
1913ae02089SMasatake YAMATO */
isSubroutineDeclaration(const unsigned char * cp)192ce990805SThomas Braun static bool isSubroutineDeclaration (const unsigned char *cp)
1933ae02089SMasatake YAMATO {
194ce990805SThomas Braun bool attr = false;
1953ae02089SMasatake YAMATO int nparens = 0;
1963ae02089SMasatake YAMATO
1973ae02089SMasatake YAMATO do {
1983ae02089SMasatake YAMATO for ( ; *cp; ++cp) {
1993ae02089SMasatake YAMATO SUB_DECL_SWITCH:
2003ae02089SMasatake YAMATO switch (*cp) {
2013ae02089SMasatake YAMATO case ':':
2023ae02089SMasatake YAMATO if (nparens)
2033ae02089SMasatake YAMATO break;
204ce990805SThomas Braun else if (true == attr)
205ce990805SThomas Braun return false; /* Invalid attribute name */
2063ae02089SMasatake YAMATO else
207ce990805SThomas Braun attr = true;
2083ae02089SMasatake YAMATO break;
2093ae02089SMasatake YAMATO case '(':
2103ae02089SMasatake YAMATO ++nparens;
2113ae02089SMasatake YAMATO break;
2123ae02089SMasatake YAMATO case ')':
2133ae02089SMasatake YAMATO --nparens;
2143ae02089SMasatake YAMATO break;
2153ae02089SMasatake YAMATO case ' ':
2163ae02089SMasatake YAMATO case '\t':
2173ae02089SMasatake YAMATO break;
2183ae02089SMasatake YAMATO case ';':
2193ae02089SMasatake YAMATO if (!nparens)
220ce990805SThomas Braun return true;
2213ae02089SMasatake YAMATO case '{':
2223ae02089SMasatake YAMATO if (!nparens)
223ce990805SThomas Braun return false;
2243ae02089SMasatake YAMATO default:
2253ae02089SMasatake YAMATO if (attr) {
2263ae02089SMasatake YAMATO if (isIdentifier1(*cp)) {
2273ae02089SMasatake YAMATO cp++;
2283ae02089SMasatake YAMATO while (isIdentifier (*cp))
2293ae02089SMasatake YAMATO cp++;
230ce990805SThomas Braun attr = false;
2313ae02089SMasatake YAMATO goto SUB_DECL_SWITCH; /* Instead of --cp; */
2323ae02089SMasatake YAMATO } else {
233ce990805SThomas Braun return false;
2343ae02089SMasatake YAMATO }
2353ae02089SMasatake YAMATO } else if (nparens) {
2363ae02089SMasatake YAMATO break;
2373ae02089SMasatake YAMATO } else {
238ce990805SThomas Braun return false;
2393ae02089SMasatake YAMATO }
2403ae02089SMasatake YAMATO }
2413ae02089SMasatake YAMATO }
2421b312fe7SMasatake YAMATO } while (NULL != (cp = readLineFromInputFile ()));
2433ae02089SMasatake YAMATO
244ce990805SThomas Braun return false;
2453ae02089SMasatake YAMATO }
2463ae02089SMasatake YAMATO
2473ae02089SMasatake YAMATO /* `end' points to the equal sign. Parse from right to left to get the
2483ae02089SMasatake YAMATO * identifier. Assume we're dealing with something of form \s*\w+\s*=>
2493ae02089SMasatake YAMATO */
makeTagFromLeftSide(const char * begin,const char * end,vString * name,vString * package)2503ae02089SMasatake YAMATO static void makeTagFromLeftSide (const char *begin, const char *end,
2513ae02089SMasatake YAMATO vString *name, vString *package)
2523ae02089SMasatake YAMATO {
2533ae02089SMasatake YAMATO tagEntryInfo entry;
2543ae02089SMasatake YAMATO const char *b, *e;
255cd677fe6SMasatake YAMATO if (! PerlKinds[KIND_PERL_CONSTANT].enabled)
2564a95e4a5SColomban Wendling return;
2573ae02089SMasatake YAMATO for (e = end - 1; e > begin && isspace(*e); --e)
2583ae02089SMasatake YAMATO ;
2593ae02089SMasatake YAMATO if (e < begin)
2603ae02089SMasatake YAMATO return;
2613ae02089SMasatake YAMATO for (b = e; b >= begin && isIdentifier(*b); --b)
2623ae02089SMasatake YAMATO ;
2633ae02089SMasatake YAMATO /* Identifier must be either beginning of line of have some whitespace
2643ae02089SMasatake YAMATO * on its left:
2653ae02089SMasatake YAMATO */
2663ae02089SMasatake YAMATO if (b < begin || isspace(*b) || ',' == *b)
2673ae02089SMasatake YAMATO ++b;
2683ae02089SMasatake YAMATO else if (b != begin)
2693ae02089SMasatake YAMATO return;
270a8e897fcSDmitri Tikhonov if (e - b + 1 <= 0)
271a8e897fcSDmitri Tikhonov return; /* Left side of => has an invalid identifier. */
2723ae02089SMasatake YAMATO vStringClear(name);
2733ae02089SMasatake YAMATO vStringNCatS(name, b, e - b + 1);
274cd677fe6SMasatake YAMATO initTagEntry(&entry, vStringValue(name), KIND_PERL_CONSTANT);
2753ae02089SMasatake YAMATO makeTagEntry(&entry);
27635c59e96SMasatake YAMATO if (isXtagEnabled (XTAG_QUALIFIED_TAGS) && package && vStringLength(package)) {
2773ae02089SMasatake YAMATO vStringClear(name);
2783ae02089SMasatake YAMATO vStringCopy(name, package);
2793ae02089SMasatake YAMATO vStringNCatS(name, b, e - b + 1);
280cd677fe6SMasatake YAMATO initTagEntry(&entry, vStringValue(name), KIND_PERL_CONSTANT);
2815022e63aSMasatake YAMATO markTagExtraBit (&entry, XTAG_QUALIFIED_TAGS);
2823ae02089SMasatake YAMATO makeTagEntry(&entry);
2833ae02089SMasatake YAMATO }
2843ae02089SMasatake YAMATO }
2853ae02089SMasatake YAMATO
makeTagForModule(const char * name,int role)2865be4c343SMasatake YAMATO static int makeTagForModule (const char *name, int role)
287b02a66cdSMasatake YAMATO {
288b02a66cdSMasatake YAMATO tagEntryInfo entry;
289b02a66cdSMasatake YAMATO initRefTagEntry(&entry, name, KIND_PERL_MODULE, role);
2905be4c343SMasatake YAMATO return makeTagEntry(&entry);
291b02a66cdSMasatake YAMATO }
292b02a66cdSMasatake YAMATO
2933ae02089SMasatake YAMATO enum const_state { CONST_STATE_NEXT_LINE, CONST_STATE_HIT_END };
2943ae02089SMasatake YAMATO
2953ae02089SMasatake YAMATO /* Parse a single line, find as many NAME => VALUE pairs as we can and try
2963ae02089SMasatake YAMATO * to detect the end of the hashref.
2973ae02089SMasatake YAMATO */
parseConstantsFromLine(const char * cp,vString * name,vString * package)2983ae02089SMasatake YAMATO static enum const_state parseConstantsFromLine (const char *cp,
2993ae02089SMasatake YAMATO vString *name, vString *package)
3003ae02089SMasatake YAMATO {
3013ae02089SMasatake YAMATO while (1) {
3023ae02089SMasatake YAMATO const size_t sz = strcspn(cp, "#}=");
3033ae02089SMasatake YAMATO switch (cp[sz]) {
3043ae02089SMasatake YAMATO case '=':
305ebaf5175SMasatake YAMATO if ('>' == cp[sz + 1])
3063ae02089SMasatake YAMATO makeTagFromLeftSide(cp, cp + sz, name, package);
3073ae02089SMasatake YAMATO break;
3083ae02089SMasatake YAMATO case '}': /* Assume this is the end of the hashref. */
3093ae02089SMasatake YAMATO return CONST_STATE_HIT_END;
3103ae02089SMasatake YAMATO case '\0': /* End of the line. */
3113ae02089SMasatake YAMATO case '#': /* Assume this is a comment and thus end of the line. */
3123ae02089SMasatake YAMATO return CONST_STATE_NEXT_LINE;
3133ae02089SMasatake YAMATO }
3143ae02089SMasatake YAMATO cp += sz + 1;
3153ae02089SMasatake YAMATO }
3163ae02089SMasatake YAMATO }
3173ae02089SMasatake YAMATO
3183ae02089SMasatake YAMATO /* Parse constants declared via hash reference, like this:
3193ae02089SMasatake YAMATO * use constant {
3203ae02089SMasatake YAMATO * A => 1,
3213ae02089SMasatake YAMATO * B => 2,
3223ae02089SMasatake YAMATO * };
3233ae02089SMasatake YAMATO * The approach we take is simplistic, but it covers the vast majority of
3243ae02089SMasatake YAMATO * cases well. There can be some false positives.
3253ae02089SMasatake YAMATO * Returns 0 if found the end of the hashref, -1 if we hit EOF
3263ae02089SMasatake YAMATO */
parseConstantsFromHashRef(const unsigned char * cp,vString * name,vString * package)3273ae02089SMasatake YAMATO static int parseConstantsFromHashRef (const unsigned char *cp,
3283ae02089SMasatake YAMATO vString *name, vString *package)
3293ae02089SMasatake YAMATO {
3303ae02089SMasatake YAMATO while (1) {
3313ae02089SMasatake YAMATO enum const_state state =
3323ae02089SMasatake YAMATO parseConstantsFromLine((const char *) cp, name, package);
3333ae02089SMasatake YAMATO switch (state) {
3343ae02089SMasatake YAMATO case CONST_STATE_NEXT_LINE:
3351b312fe7SMasatake YAMATO cp = readLineFromInputFile();
3363ae02089SMasatake YAMATO if (cp)
3373ae02089SMasatake YAMATO break;
3383ae02089SMasatake YAMATO else
3393ae02089SMasatake YAMATO return -1;
3403ae02089SMasatake YAMATO case CONST_STATE_HIT_END:
3413ae02089SMasatake YAMATO return 0;
3423ae02089SMasatake YAMATO }
3433ae02089SMasatake YAMATO }
3443ae02089SMasatake YAMATO }
3453ae02089SMasatake YAMATO
parseQuotedWords(const unsigned char * cp,vString * name,int moduleIndex)3465be4c343SMasatake YAMATO static void parseQuotedWords(const unsigned char *cp,
3475be4c343SMasatake YAMATO vString *name, int moduleIndex)
3485be4c343SMasatake YAMATO {
3495be4c343SMasatake YAMATO unsigned char end = *cp++;
3505be4c343SMasatake YAMATO switch (end)
3515be4c343SMasatake YAMATO {
3525be4c343SMasatake YAMATO case '[': end = ']'; break;
3535be4c343SMasatake YAMATO case '(': end = ')'; break;
3545be4c343SMasatake YAMATO case '{': end = '}'; break;
3555be4c343SMasatake YAMATO case '<': end = '>'; break;
3565be4c343SMasatake YAMATO }
3575be4c343SMasatake YAMATO
3585be4c343SMasatake YAMATO do {
3595be4c343SMasatake YAMATO while (*cp && *cp != end)
3605be4c343SMasatake YAMATO {
3615be4c343SMasatake YAMATO if (isspace(*cp))
3625be4c343SMasatake YAMATO {
3635be4c343SMasatake YAMATO notifyFindingQuotedWord (moduleIndex, vStringValue(name));
3645be4c343SMasatake YAMATO vStringClear(name);
3655be4c343SMasatake YAMATO cp++;
3665be4c343SMasatake YAMATO continue;
3675be4c343SMasatake YAMATO }
3685be4c343SMasatake YAMATO
3695be4c343SMasatake YAMATO if (*cp == '\\')
3705be4c343SMasatake YAMATO {
3715be4c343SMasatake YAMATO cp++;
3725be4c343SMasatake YAMATO if (*cp == '\0')
3735be4c343SMasatake YAMATO break;
3745be4c343SMasatake YAMATO }
3755be4c343SMasatake YAMATO
3765be4c343SMasatake YAMATO vStringPut(name, *cp);
3775be4c343SMasatake YAMATO cp++;
3785be4c343SMasatake YAMATO }
3795be4c343SMasatake YAMATO if (!vStringIsEmpty(name))
3805be4c343SMasatake YAMATO notifyFindingQuotedWord (moduleIndex, vStringValue(name));
3815be4c343SMasatake YAMATO
3825be4c343SMasatake YAMATO if (*cp == end)
3835be4c343SMasatake YAMATO break;
3845be4c343SMasatake YAMATO } while ((cp = readLineFromInputFile()) != NULL);
3855be4c343SMasatake YAMATO }
3865be4c343SMasatake YAMATO
387*08bf1b99SMasatake YAMATO /*
388*08bf1b99SMasatake YAMATO * Extract heredoc markers and skip the heredoc areas.
389*08bf1b99SMasatake YAMATO *
390*08bf1b99SMasatake YAMATO * - https://perldoc.perl.org/perlop#%3C%3CEOF
391*08bf1b99SMasatake YAMATO */
hereDocMarkerNew(bool indented)392*08bf1b99SMasatake YAMATO static struct hereDocMarker *hereDocMarkerNew (bool indented)
393*08bf1b99SMasatake YAMATO {
394*08bf1b99SMasatake YAMATO struct hereDocMarker *marker = xMalloc(1, struct hereDocMarker);
395*08bf1b99SMasatake YAMATO
396*08bf1b99SMasatake YAMATO marker->indented = indented;
397*08bf1b99SMasatake YAMATO marker->marker = vStringNew();
398*08bf1b99SMasatake YAMATO marker->corkIndex = CORK_NIL;
399*08bf1b99SMasatake YAMATO
400*08bf1b99SMasatake YAMATO return marker;
401*08bf1b99SMasatake YAMATO }
402*08bf1b99SMasatake YAMATO
hereDocMarkerDelete(struct hereDocMarker * marker)403*08bf1b99SMasatake YAMATO static void hereDocMarkerDelete (struct hereDocMarker *marker)
404*08bf1b99SMasatake YAMATO {
405*08bf1b99SMasatake YAMATO vStringDelete (marker->marker);
406*08bf1b99SMasatake YAMATO eFree (marker);
407*08bf1b99SMasatake YAMATO }
408*08bf1b99SMasatake YAMATO
readHereDocMarker(unsigned char * line,vString * marker,unsigned char quote_char)409*08bf1b99SMasatake YAMATO static unsigned char *readHereDocMarker (unsigned char *line,
410*08bf1b99SMasatake YAMATO vString *marker,
411*08bf1b99SMasatake YAMATO unsigned char quote_char)
412*08bf1b99SMasatake YAMATO {
413*08bf1b99SMasatake YAMATO unsigned char *cp = line;
414*08bf1b99SMasatake YAMATO bool backslash = false;
415*08bf1b99SMasatake YAMATO
416*08bf1b99SMasatake YAMATO for (cp = line; *cp != '\0'; cp++)
417*08bf1b99SMasatake YAMATO {
418*08bf1b99SMasatake YAMATO if (backslash)
419*08bf1b99SMasatake YAMATO {
420*08bf1b99SMasatake YAMATO vStringPut (marker, *cp);
421*08bf1b99SMasatake YAMATO backslash = false;
422*08bf1b99SMasatake YAMATO continue;
423*08bf1b99SMasatake YAMATO }
424*08bf1b99SMasatake YAMATO
425*08bf1b99SMasatake YAMATO if (quote_char == '"' && (*cp == '\\'))
426*08bf1b99SMasatake YAMATO {
427*08bf1b99SMasatake YAMATO backslash = true;
428*08bf1b99SMasatake YAMATO continue;
429*08bf1b99SMasatake YAMATO }
430*08bf1b99SMasatake YAMATO
431*08bf1b99SMasatake YAMATO if (quote_char && *cp == quote_char)
432*08bf1b99SMasatake YAMATO {
433*08bf1b99SMasatake YAMATO cp++;
434*08bf1b99SMasatake YAMATO break;
435*08bf1b99SMasatake YAMATO }
436*08bf1b99SMasatake YAMATO
437*08bf1b99SMasatake YAMATO if (!quote_char && !isIdentifier(*cp))
438*08bf1b99SMasatake YAMATO break;
439*08bf1b99SMasatake YAMATO
440*08bf1b99SMasatake YAMATO vStringPut (marker, *cp);
441*08bf1b99SMasatake YAMATO }
442*08bf1b99SMasatake YAMATO
443*08bf1b99SMasatake YAMATO return cp;
444*08bf1b99SMasatake YAMATO }
445*08bf1b99SMasatake YAMATO
collectHereDocMarkers(struct hereDocMarkerManager * mgr,const unsigned char * line)446*08bf1b99SMasatake YAMATO static void collectHereDocMarkers (struct hereDocMarkerManager *mgr,
447*08bf1b99SMasatake YAMATO const unsigned char *line)
448*08bf1b99SMasatake YAMATO {
449*08bf1b99SMasatake YAMATO unsigned char *starter = (unsigned char*)strstr((char *)line, "<<");
450*08bf1b99SMasatake YAMATO unsigned char *cp = NULL;
451*08bf1b99SMasatake YAMATO bool indented = false;
452*08bf1b99SMasatake YAMATO unsigned char quote_char = 0;
453*08bf1b99SMasatake YAMATO
454*08bf1b99SMasatake YAMATO if (starter == NULL)
455*08bf1b99SMasatake YAMATO return;
456*08bf1b99SMasatake YAMATO
457*08bf1b99SMasatake YAMATO cp = starter + 2;
458*08bf1b99SMasatake YAMATO while (isspace (*cp))
459*08bf1b99SMasatake YAMATO cp++;
460*08bf1b99SMasatake YAMATO
461*08bf1b99SMasatake YAMATO if (*cp == '\0')
462*08bf1b99SMasatake YAMATO return;
463*08bf1b99SMasatake YAMATO
464*08bf1b99SMasatake YAMATO /* Is shift operator? */
465*08bf1b99SMasatake YAMATO if (isdigit (*cp))
466*08bf1b99SMasatake YAMATO {
467*08bf1b99SMasatake YAMATO /* Scan the rest of the string. */
468*08bf1b99SMasatake YAMATO collectHereDocMarkers (mgr, ++cp);
469*08bf1b99SMasatake YAMATO return;
470*08bf1b99SMasatake YAMATO }
471*08bf1b99SMasatake YAMATO
472*08bf1b99SMasatake YAMATO if (*cp == '~') {
473*08bf1b99SMasatake YAMATO indented = true;
474*08bf1b99SMasatake YAMATO cp++;
475*08bf1b99SMasatake YAMATO if (*cp == '\0')
476*08bf1b99SMasatake YAMATO return;
477*08bf1b99SMasatake YAMATO while (isspace (*cp))
478*08bf1b99SMasatake YAMATO cp++;
479*08bf1b99SMasatake YAMATO if (*cp == '\0')
480*08bf1b99SMasatake YAMATO return;
481*08bf1b99SMasatake YAMATO }
482*08bf1b99SMasatake YAMATO
483*08bf1b99SMasatake YAMATO switch (*cp)
484*08bf1b99SMasatake YAMATO {
485*08bf1b99SMasatake YAMATO case '\'':
486*08bf1b99SMasatake YAMATO case '"':
487*08bf1b99SMasatake YAMATO case '`':
488*08bf1b99SMasatake YAMATO quote_char = *cp;
489*08bf1b99SMasatake YAMATO /* Fall through */
490*08bf1b99SMasatake YAMATO case '\\':
491*08bf1b99SMasatake YAMATO cp++;
492*08bf1b99SMasatake YAMATO if (*cp == '\0')
493*08bf1b99SMasatake YAMATO return;
494*08bf1b99SMasatake YAMATO break;
495*08bf1b99SMasatake YAMATO default:
496*08bf1b99SMasatake YAMATO break;
497*08bf1b99SMasatake YAMATO }
498*08bf1b99SMasatake YAMATO
499*08bf1b99SMasatake YAMATO struct hereDocMarker *marker = hereDocMarkerNew (indented);
500*08bf1b99SMasatake YAMATO const unsigned char *last_cp = cp;
501*08bf1b99SMasatake YAMATO cp = readHereDocMarker(cp, marker->marker, quote_char);
502*08bf1b99SMasatake YAMATO if (vStringLength (marker->marker) > 0)
503*08bf1b99SMasatake YAMATO {
504*08bf1b99SMasatake YAMATO marker->corkIndex = makeSimpleTag (marker->marker,
505*08bf1b99SMasatake YAMATO KIND_PERL_HEREDOCMARKER);
506*08bf1b99SMasatake YAMATO ptrArrayAdd (mgr->markers, marker);
507*08bf1b99SMasatake YAMATO }
508*08bf1b99SMasatake YAMATO else
509*08bf1b99SMasatake YAMATO hereDocMarkerDelete (marker);
510*08bf1b99SMasatake YAMATO
511*08bf1b99SMasatake YAMATO if (*cp != '\0' && cp != last_cp)
512*08bf1b99SMasatake YAMATO collectHereDocMarkers (mgr, cp);
513*08bf1b99SMasatake YAMATO }
514*08bf1b99SMasatake YAMATO
isInHereDoc(struct hereDocMarkerManager * mgr,const unsigned char * line)515*08bf1b99SMasatake YAMATO static bool isInHereDoc (struct hereDocMarkerManager *mgr,
516*08bf1b99SMasatake YAMATO const unsigned char *line)
517*08bf1b99SMasatake YAMATO {
518*08bf1b99SMasatake YAMATO if (ptrArrayCount (mgr->markers) == 0)
519*08bf1b99SMasatake YAMATO return false;
520*08bf1b99SMasatake YAMATO
521*08bf1b99SMasatake YAMATO const unsigned char *cp = line;
522*08bf1b99SMasatake YAMATO struct hereDocMarker *current = ptrArrayItem (mgr->markers, mgr->current);
523*08bf1b99SMasatake YAMATO if (current->indented)
524*08bf1b99SMasatake YAMATO {
525*08bf1b99SMasatake YAMATO while (isspace(*cp))
526*08bf1b99SMasatake YAMATO cp++;
527*08bf1b99SMasatake YAMATO }
528*08bf1b99SMasatake YAMATO if (strncmp((const char *)cp, vStringValue (current->marker), vStringLength (current->marker)) == 0
529*08bf1b99SMasatake YAMATO && (cp [vStringLength (current->marker)] == '\0'
530*08bf1b99SMasatake YAMATO || (!isIdentifier (cp [vStringLength (current->marker)]))))
531*08bf1b99SMasatake YAMATO {
532*08bf1b99SMasatake YAMATO tagEntryInfo *tag = getEntryInCorkQueue (current->corkIndex);
533*08bf1b99SMasatake YAMATO if (tag)
534*08bf1b99SMasatake YAMATO tag->extensionFields.endLine = getInputLineNumber();
535*08bf1b99SMasatake YAMATO mgr->current++;
536*08bf1b99SMasatake YAMATO if (mgr->current == ptrArrayCount (mgr->markers))
537*08bf1b99SMasatake YAMATO {
538*08bf1b99SMasatake YAMATO ptrArrayClear (mgr->markers);
539*08bf1b99SMasatake YAMATO mgr->current = 0;
540*08bf1b99SMasatake YAMATO }
541*08bf1b99SMasatake YAMATO }
542*08bf1b99SMasatake YAMATO return true;
543*08bf1b99SMasatake YAMATO }
544*08bf1b99SMasatake YAMATO
initHereDocMarkerManager(struct hereDocMarkerManager * mgr)545*08bf1b99SMasatake YAMATO static void initHereDocMarkerManager(struct hereDocMarkerManager *mgr)
546*08bf1b99SMasatake YAMATO {
547*08bf1b99SMasatake YAMATO mgr->markers = ptrArrayNew((ptrArrayDeleteFunc)hereDocMarkerDelete);
548*08bf1b99SMasatake YAMATO mgr->current = 0;
549*08bf1b99SMasatake YAMATO }
550*08bf1b99SMasatake YAMATO
finiHereDocMarkerManager(struct hereDocMarkerManager * mgr)551*08bf1b99SMasatake YAMATO static void finiHereDocMarkerManager(struct hereDocMarkerManager *mgr)
552*08bf1b99SMasatake YAMATO {
553*08bf1b99SMasatake YAMATO ptrArrayDelete (mgr->markers);
554*08bf1b99SMasatake YAMATO mgr->markers = NULL;
555*08bf1b99SMasatake YAMATO mgr->current = 0;
556*08bf1b99SMasatake YAMATO }
557*08bf1b99SMasatake YAMATO
5583ae02089SMasatake YAMATO /* Algorithm adapted from from GNU etags.
5593ae02089SMasatake YAMATO * Perl support by Bart Robinson <lomew@cs.utah.edu>
5603ae02089SMasatake YAMATO * Perl sub names: look for /^ [ \t\n]sub [ \t\n]+ [^ \t\n{ (]+/
5613ae02089SMasatake YAMATO */
findPerlTags(void)5623ae02089SMasatake YAMATO static void findPerlTags (void)
5633ae02089SMasatake YAMATO {
5643ae02089SMasatake YAMATO vString *name = vStringNew ();
5653ae02089SMasatake YAMATO vString *package = NULL;
566ce990805SThomas Braun bool skipPodDoc = false;
5673ae02089SMasatake YAMATO const unsigned char *line;
5689092a057SMasatake YAMATO unsigned long podStart = 0UL;
5693ae02089SMasatake YAMATO
5703b0c2ae1SMasatake YAMATO /* A pod area can be after __END__ marker.
5713b0c2ae1SMasatake YAMATO * Perl parser itself doesn't need to parse the area
5723b0c2ae1SMasatake YAMATO * after the marker. Parsing the area is needed only
5733b0c2ae1SMasatake YAMATO * if Perl parser runs Pod parser as a guest.
5743b0c2ae1SMasatake YAMATO * This variable is set true when it is needed.
5753b0c2ae1SMasatake YAMATO */
5763b0c2ae1SMasatake YAMATO bool parse_only_pod_area = false;
5773b0c2ae1SMasatake YAMATO
5783ae02089SMasatake YAMATO /* Core modules AutoLoader and SelfLoader support delayed compilation
5793ae02089SMasatake YAMATO * by allowing Perl code that follows __END__ and __DATA__ tokens,
5803ae02089SMasatake YAMATO * respectively. When we detect that one of these modules is used
5813ae02089SMasatake YAMATO * in the file, we continue processing even after we see the
5823ae02089SMasatake YAMATO * corresponding token that would usually terminate parsing of the
5833ae02089SMasatake YAMATO * file.
5843ae02089SMasatake YAMATO */
5853ae02089SMasatake YAMATO enum {
5863ae02089SMasatake YAMATO RESPECT_END = (1 << 0),
5873ae02089SMasatake YAMATO RESPECT_DATA = (1 << 1),
5883ae02089SMasatake YAMATO } respect_token = RESPECT_END | RESPECT_DATA;
5893ae02089SMasatake YAMATO
590*08bf1b99SMasatake YAMATO struct hereDocMarkerManager hdoc_mgr;
591*08bf1b99SMasatake YAMATO initHereDocMarkerManager (&hdoc_mgr);
592*08bf1b99SMasatake YAMATO
5931b312fe7SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
5943ae02089SMasatake YAMATO {
595ce990805SThomas Braun bool spaceRequired = false;
596ce990805SThomas Braun bool qualified = false;
5973ae02089SMasatake YAMATO const unsigned char *cp = line;
598cd677fe6SMasatake YAMATO perlKind kind = KIND_PERL_NONE;
5993ae02089SMasatake YAMATO tagEntryInfo e;
6003ae02089SMasatake YAMATO
601*08bf1b99SMasatake YAMATO if (isInHereDoc (&hdoc_mgr, line))
602*08bf1b99SMasatake YAMATO continue;
603*08bf1b99SMasatake YAMATO
6043ae02089SMasatake YAMATO if (skipPodDoc)
6053ae02089SMasatake YAMATO {
6063ae02089SMasatake YAMATO if (strncmp ((const char*) line, "=cut", (size_t) 4) == 0)
6079092a057SMasatake YAMATO {
608ce990805SThomas Braun skipPodDoc = false;
6099092a057SMasatake YAMATO if (podStart != 0UL)
6109092a057SMasatake YAMATO {
611cd677fe6SMasatake YAMATO notifyLeavingPod ();
6129092a057SMasatake YAMATO makePromise ("Pod",
6139092a057SMasatake YAMATO podStart, 0,
6149092a057SMasatake YAMATO getInputLineNumber(), 0,
6159092a057SMasatake YAMATO getSourceLineNumber());
6169092a057SMasatake YAMATO podStart = 0UL;
6179092a057SMasatake YAMATO }
6189092a057SMasatake YAMATO }
6193ae02089SMasatake YAMATO continue;
6203ae02089SMasatake YAMATO }
6213ae02089SMasatake YAMATO else if (line [0] == '=')
6223ae02089SMasatake YAMATO {
6233ae02089SMasatake YAMATO skipPodDoc = isPodWord ((const char*)line + 1);
6249092a057SMasatake YAMATO if (skipPodDoc)
625cd677fe6SMasatake YAMATO {
6269092a057SMasatake YAMATO podStart = getSourceLineNumber ();
627d7ad8c78SMasatake YAMATO notifyEnteringPod ();
628cd677fe6SMasatake YAMATO }
6293ae02089SMasatake YAMATO continue;
6303ae02089SMasatake YAMATO }
6313ae02089SMasatake YAMATO else if (strcmp ((const char*) line, "__DATA__") == 0)
6323ae02089SMasatake YAMATO {
6333ae02089SMasatake YAMATO if (respect_token & RESPECT_DATA)
6343b0c2ae1SMasatake YAMATO {
6353b0c2ae1SMasatake YAMATO if (isXtagEnabled (XTAG_GUEST))
6363b0c2ae1SMasatake YAMATO parse_only_pod_area = true;
6373b0c2ae1SMasatake YAMATO else
6383ae02089SMasatake YAMATO break;
6393b0c2ae1SMasatake YAMATO }
6403ae02089SMasatake YAMATO else
6413ae02089SMasatake YAMATO continue;
6423ae02089SMasatake YAMATO }
6433ae02089SMasatake YAMATO else if (strcmp ((const char*) line, "__END__") == 0)
6443ae02089SMasatake YAMATO {
6453ae02089SMasatake YAMATO if (respect_token & RESPECT_END)
6463b0c2ae1SMasatake YAMATO {
6473b0c2ae1SMasatake YAMATO if (isXtagEnabled (XTAG_GUEST))
6483b0c2ae1SMasatake YAMATO parse_only_pod_area = true;
6493b0c2ae1SMasatake YAMATO else
6503ae02089SMasatake YAMATO break;
6513b0c2ae1SMasatake YAMATO }
6523ae02089SMasatake YAMATO else
6533ae02089SMasatake YAMATO continue;
6543ae02089SMasatake YAMATO }
6553ae02089SMasatake YAMATO else if (line [0] == '#')
6563ae02089SMasatake YAMATO continue;
6573ae02089SMasatake YAMATO
6583b0c2ae1SMasatake YAMATO if (parse_only_pod_area)
6593b0c2ae1SMasatake YAMATO continue;
6603b0c2ae1SMasatake YAMATO
6613ae02089SMasatake YAMATO while (isspace (*cp))
6623ae02089SMasatake YAMATO cp++;
6633ae02089SMasatake YAMATO
664*08bf1b99SMasatake YAMATO collectHereDocMarkers (&hdoc_mgr, cp);
665*08bf1b99SMasatake YAMATO
6663ae02089SMasatake YAMATO if (strncmp((const char*) cp, "sub", (size_t) 3) == 0)
6673ae02089SMasatake YAMATO {
6683ae02089SMasatake YAMATO TRACE("this looks like a sub\n");
6693ae02089SMasatake YAMATO cp += 3;
670cd677fe6SMasatake YAMATO kind = KIND_PERL_SUBROUTINE;
671ce990805SThomas Braun spaceRequired = true;
672ce990805SThomas Braun qualified = true;
6733ae02089SMasatake YAMATO }
6743ae02089SMasatake YAMATO else if (strncmp((const char*) cp, "use", (size_t) 3) == 0)
6753ae02089SMasatake YAMATO {
6763ae02089SMasatake YAMATO cp += 3;
6773ae02089SMasatake YAMATO if (!isspace(*cp))
6783ae02089SMasatake YAMATO continue;
6793ae02089SMasatake YAMATO while (*cp && isspace (*cp))
6803ae02089SMasatake YAMATO ++cp;
6813ae02089SMasatake YAMATO if (strncmp((const char*) cp, "AutoLoader", (size_t) 10) == 0) {
6823ae02089SMasatake YAMATO respect_token &= ~RESPECT_END;
683b02a66cdSMasatake YAMATO makeTagForModule("AutoLoader", ROLE_PERL_MODULE_USED);
6843ae02089SMasatake YAMATO continue;
6853ae02089SMasatake YAMATO }
6863ae02089SMasatake YAMATO if (strncmp((const char*) cp, "SelfLoader", (size_t) 10) == 0) {
6873ae02089SMasatake YAMATO respect_token &= ~RESPECT_DATA;
688b02a66cdSMasatake YAMATO makeTagForModule("SelfLoader", ROLE_PERL_MODULE_USED);
6893ae02089SMasatake YAMATO continue;
6903ae02089SMasatake YAMATO }
691b02a66cdSMasatake YAMATO
692b02a66cdSMasatake YAMATO vString *module = NULL;
693b02a66cdSMasatake YAMATO while (isalnum(*cp) || *cp == ':' || *cp == '.') {
694b02a66cdSMasatake YAMATO if (!module)
695b02a66cdSMasatake YAMATO module = vStringNew();
696b02a66cdSMasatake YAMATO vStringPut(module, *cp);
697b02a66cdSMasatake YAMATO ++cp;
698b02a66cdSMasatake YAMATO }
69950c83de6SMasatake YAMATO if (!module)
70050c83de6SMasatake YAMATO continue;
70150c83de6SMasatake YAMATO
7025be4c343SMasatake YAMATO int q = makeTagForModule(vStringValue(module), ROLE_PERL_MODULE_USED);
70350c83de6SMasatake YAMATO bool isConstant = (strcmp(vStringValue(module), "constant") == 0);
704b02a66cdSMasatake YAMATO vStringDelete(module);
705b02a66cdSMasatake YAMATO if (!isConstant)
7065be4c343SMasatake YAMATO {
7075be4c343SMasatake YAMATO while (isspace(*cp))
7085be4c343SMasatake YAMATO cp++;
7095be4c343SMasatake YAMATO if (strncmp("qw", (const char *)cp, 2) != 0)
7103ae02089SMasatake YAMATO continue;
7115be4c343SMasatake YAMATO cp += 2;
7125be4c343SMasatake YAMATO while (isspace(*cp))
7135be4c343SMasatake YAMATO cp++;
7145be4c343SMasatake YAMATO if (*cp == '\0')
7155be4c343SMasatake YAMATO continue;
7165be4c343SMasatake YAMATO vStringClear (name);
7175be4c343SMasatake YAMATO
7185be4c343SMasatake YAMATO parseQuotedWords(cp, name, q);
7195be4c343SMasatake YAMATO vStringClear (name);
7205be4c343SMasatake YAMATO continue;
7215be4c343SMasatake YAMATO }
722b02a66cdSMasatake YAMATO
7233ae02089SMasatake YAMATO /* Skip up to the first non-space character, skipping empty
7243ae02089SMasatake YAMATO * and comment lines.
7253ae02089SMasatake YAMATO */
7263ae02089SMasatake YAMATO while (isspace(*cp))
7273ae02089SMasatake YAMATO cp++;
7283ae02089SMasatake YAMATO while (!*cp || '#' == *cp) {
7291b312fe7SMasatake YAMATO cp = readLineFromInputFile ();
7303ae02089SMasatake YAMATO if (!cp)
7313ae02089SMasatake YAMATO goto END_MAIN_WHILE;
7323ae02089SMasatake YAMATO while (isspace (*cp))
7333ae02089SMasatake YAMATO cp++;
7343ae02089SMasatake YAMATO }
7353ae02089SMasatake YAMATO if ('{' == *cp) {
7363ae02089SMasatake YAMATO ++cp;
7373ae02089SMasatake YAMATO if (0 == parseConstantsFromHashRef(cp, name, package)) {
7383ae02089SMasatake YAMATO vStringClear(name);
7393ae02089SMasatake YAMATO continue;
7403ae02089SMasatake YAMATO } else
7413ae02089SMasatake YAMATO goto END_MAIN_WHILE;
7423ae02089SMasatake YAMATO }
743cd677fe6SMasatake YAMATO kind = KIND_PERL_CONSTANT;
744ce990805SThomas Braun spaceRequired = false;
745ce990805SThomas Braun qualified = true;
7463ae02089SMasatake YAMATO }
74750c83de6SMasatake YAMATO else if (strncmp((const char*) cp, "no", (size_t) 2) == 0 && isspace(cp[2]))
74850c83de6SMasatake YAMATO {
74950c83de6SMasatake YAMATO cp += 3;
75050c83de6SMasatake YAMATO while (isspace (*cp))
75150c83de6SMasatake YAMATO cp++;
75250c83de6SMasatake YAMATO vString *module = NULL;
75350c83de6SMasatake YAMATO while (isalnum(*cp) || *cp == ':' || *cp == '.') {
75450c83de6SMasatake YAMATO if (!module)
75550c83de6SMasatake YAMATO module = vStringNew();
75650c83de6SMasatake YAMATO vStringPut(module, *cp);
75750c83de6SMasatake YAMATO ++cp;
75850c83de6SMasatake YAMATO }
75950c83de6SMasatake YAMATO if (module) {
76050c83de6SMasatake YAMATO makeTagForModule(vStringValue(module), ROLE_PERL_MODULE_UNUSED);
76150c83de6SMasatake YAMATO vStringDelete(module);
76250c83de6SMasatake YAMATO }
76350c83de6SMasatake YAMATO continue;
76450c83de6SMasatake YAMATO }
7653ae02089SMasatake YAMATO else if (strncmp((const char*) cp, "package", (size_t) 7) == 0 &&
7663ae02089SMasatake YAMATO ('\0' == cp[7] || isspace(cp[7])))
7673ae02089SMasatake YAMATO {
768d95a4d7cSDmitri Tikhonov cp += 7;
7693ae02089SMasatake YAMATO while (isspace (*cp))
7703ae02089SMasatake YAMATO cp++;
7713ae02089SMasatake YAMATO while (!*cp || '#' == *cp) {
7721b312fe7SMasatake YAMATO cp = readLineFromInputFile ();
7733ae02089SMasatake YAMATO if (!cp)
7743ae02089SMasatake YAMATO goto END_MAIN_WHILE;
7753ae02089SMasatake YAMATO while (isspace (*cp))
7763ae02089SMasatake YAMATO cp++;
7773ae02089SMasatake YAMATO }
7783ae02089SMasatake YAMATO if (package == NULL)
7793ae02089SMasatake YAMATO package = vStringNew ();
7803ae02089SMasatake YAMATO else
7813ae02089SMasatake YAMATO vStringClear (package);
7823ae02089SMasatake YAMATO const unsigned char *const first = cp;
7833ae02089SMasatake YAMATO while (*cp && (int) *cp != ';' && !isspace ((int) *cp))
7843ae02089SMasatake YAMATO {
7853ae02089SMasatake YAMATO vStringPut (package, (int) *cp);
7863ae02089SMasatake YAMATO cp++;
7873ae02089SMasatake YAMATO }
7883ae02089SMasatake YAMATO vStringCatS (package, "::");
7893ae02089SMasatake YAMATO
7903ae02089SMasatake YAMATO cp = first; /* Rewind */
791cd677fe6SMasatake YAMATO kind = KIND_PERL_PACKAGE;
792ce990805SThomas Braun spaceRequired = false;
793ce990805SThomas Braun qualified = true;
7943ae02089SMasatake YAMATO }
7953ae02089SMasatake YAMATO else if (strncmp((const char*) cp, "format", (size_t) 6) == 0)
7963ae02089SMasatake YAMATO {
7973ae02089SMasatake YAMATO cp += 6;
798cd677fe6SMasatake YAMATO kind = KIND_PERL_FORMAT;
799ce990805SThomas Braun spaceRequired = true;
800ce990805SThomas Braun qualified = true;
8013ae02089SMasatake YAMATO }
8023ae02089SMasatake YAMATO else
8033ae02089SMasatake YAMATO {
8043ae02089SMasatake YAMATO if (isIdentifier1 (*cp))
8053ae02089SMasatake YAMATO {
8063ae02089SMasatake YAMATO const unsigned char *p = cp;
8073ae02089SMasatake YAMATO while (isIdentifier (*p))
8083ae02089SMasatake YAMATO ++p;
8093ae02089SMasatake YAMATO while (isspace (*p))
8103ae02089SMasatake YAMATO ++p;
8113ae02089SMasatake YAMATO if ((int) *p == ':' && (int) *(p + 1) != ':')
812cd677fe6SMasatake YAMATO kind = KIND_PERL_LABEL;
8133ae02089SMasatake YAMATO }
8143ae02089SMasatake YAMATO }
815cd677fe6SMasatake YAMATO if (kind != KIND_PERL_NONE)
8163ae02089SMasatake YAMATO {
8173ae02089SMasatake YAMATO TRACE("cp0: %s\n", (const char *) cp);
8183ae02089SMasatake YAMATO if (spaceRequired && *cp && !isspace (*cp))
8193ae02089SMasatake YAMATO continue;
8203ae02089SMasatake YAMATO
8213ae02089SMasatake YAMATO TRACE("cp1: %s\n", (const char *) cp);
8223ae02089SMasatake YAMATO while (isspace (*cp))
8233ae02089SMasatake YAMATO cp++;
8243ae02089SMasatake YAMATO
8253ae02089SMasatake YAMATO while (!*cp || '#' == *cp) { /* Gobble up empty lines
8263ae02089SMasatake YAMATO and comments */
8271b312fe7SMasatake YAMATO cp = readLineFromInputFile ();
8283ae02089SMasatake YAMATO if (!cp)
8293ae02089SMasatake YAMATO goto END_MAIN_WHILE;
8303ae02089SMasatake YAMATO while (isspace (*cp))
8313ae02089SMasatake YAMATO cp++;
8323ae02089SMasatake YAMATO }
8333ae02089SMasatake YAMATO
834cd677fe6SMasatake YAMATO while (isIdentifier (*cp) || (KIND_PERL_PACKAGE == kind && ':' == *cp))
8353ae02089SMasatake YAMATO {
8363ae02089SMasatake YAMATO vStringPut (name, (int) *cp);
8373ae02089SMasatake YAMATO cp++;
8383ae02089SMasatake YAMATO }
8393ae02089SMasatake YAMATO
840cd677fe6SMasatake YAMATO if (KIND_PERL_FORMAT == kind &&
8413ae02089SMasatake YAMATO vStringLength (name) == 0 && /* cp did not advance */
8423ae02089SMasatake YAMATO '=' == *cp)
8433ae02089SMasatake YAMATO {
8443ae02089SMasatake YAMATO /* format's name is optional. If it's omitted, 'STDOUT'
8453ae02089SMasatake YAMATO is assumed. */
8463ae02089SMasatake YAMATO vStringCatS (name, "STDOUT");
8473ae02089SMasatake YAMATO }
8483ae02089SMasatake YAMATO
849e852ee0eSMasatake YAMATO TRACE("name: %s\n", vStringValue (name));
8503ae02089SMasatake YAMATO
8513ae02089SMasatake YAMATO if (0 == vStringLength(name)) {
8523ae02089SMasatake YAMATO vStringClear(name);
8533ae02089SMasatake YAMATO continue;
8543ae02089SMasatake YAMATO }
8553ae02089SMasatake YAMATO
856cd677fe6SMasatake YAMATO if (KIND_PERL_SUBROUTINE == kind)
8573ae02089SMasatake YAMATO {
8583ae02089SMasatake YAMATO /*
8593ae02089SMasatake YAMATO * isSubroutineDeclaration() may consume several lines. So
8603ae02089SMasatake YAMATO * we record line positions.
8613ae02089SMasatake YAMATO */
86216a2541cSMasatake YAMATO initTagEntry(&e, vStringValue(name), KIND_GHOST_INDEX);
8633ae02089SMasatake YAMATO
864ce990805SThomas Braun if (true == isSubroutineDeclaration(cp)) {
865cd677fe6SMasatake YAMATO if (true == PerlKinds[KIND_PERL_SUBROUTINE_DECLARATION].enabled) {
866cd677fe6SMasatake YAMATO kind = KIND_PERL_SUBROUTINE_DECLARATION;
8673ae02089SMasatake YAMATO } else {
8683ae02089SMasatake YAMATO vStringClear (name);
8693ae02089SMasatake YAMATO continue;
8703ae02089SMasatake YAMATO }
8714a95e4a5SColomban Wendling } else if (! PerlKinds[kind].enabled) {
8724a95e4a5SColomban Wendling continue;
8733ae02089SMasatake YAMATO }
8743ae02089SMasatake YAMATO
875f92e6bf2SMasatake YAMATO e.kindIndex = kind;
8763ae02089SMasatake YAMATO
8773ae02089SMasatake YAMATO makeTagEntry(&e);
8783ae02089SMasatake YAMATO
87935c59e96SMasatake YAMATO if (isXtagEnabled (XTAG_QUALIFIED_TAGS) && qualified &&
8803ae02089SMasatake YAMATO package != NULL && vStringLength (package) > 0)
8813ae02089SMasatake YAMATO {
8823ae02089SMasatake YAMATO vString *const qualifiedName = vStringNew ();
8833ae02089SMasatake YAMATO vStringCopy (qualifiedName, package);
8843ae02089SMasatake YAMATO vStringCat (qualifiedName, name);
8853ae02089SMasatake YAMATO e.name = vStringValue(qualifiedName);
8865022e63aSMasatake YAMATO markTagExtraBit (&e, XTAG_QUALIFIED_TAGS);
8873ae02089SMasatake YAMATO makeTagEntry(&e);
8883ae02089SMasatake YAMATO vStringDelete (qualifiedName);
8893ae02089SMasatake YAMATO }
8903ae02089SMasatake YAMATO } else if (vStringLength (name) > 0)
8913ae02089SMasatake YAMATO {
89216a2541cSMasatake YAMATO makeSimpleTag (name, kind);
89335c59e96SMasatake YAMATO if (isXtagEnabled(XTAG_QUALIFIED_TAGS) && qualified &&
894cd677fe6SMasatake YAMATO KIND_PERL_PACKAGE != kind &&
8953ae02089SMasatake YAMATO package != NULL && vStringLength (package) > 0)
8963ae02089SMasatake YAMATO {
8975022e63aSMasatake YAMATO tagEntryInfo fqe;
8983ae02089SMasatake YAMATO vString *const qualifiedName = vStringNew ();
8993ae02089SMasatake YAMATO vStringCopy (qualifiedName, package);
9003ae02089SMasatake YAMATO vStringCat (qualifiedName, name);
90116a2541cSMasatake YAMATO initTagEntry (&fqe, vStringValue (qualifiedName), kind);
9025022e63aSMasatake YAMATO markTagExtraBit (&fqe, XTAG_QUALIFIED_TAGS);
903ee6261abSMasatake YAMATO makeTagEntry (&fqe);
9043ae02089SMasatake YAMATO vStringDelete (qualifiedName);
9053ae02089SMasatake YAMATO }
9063ae02089SMasatake YAMATO }
9073ae02089SMasatake YAMATO vStringClear (name);
9083ae02089SMasatake YAMATO }
9093ae02089SMasatake YAMATO }
9103ae02089SMasatake YAMATO
9113ae02089SMasatake YAMATO END_MAIN_WHILE:
9123ae02089SMasatake YAMATO vStringDelete (name);
913*08bf1b99SMasatake YAMATO finiHereDocMarkerManager (&hdoc_mgr);
9143ae02089SMasatake YAMATO if (package != NULL)
9153ae02089SMasatake YAMATO vStringDelete (package);
9163ae02089SMasatake YAMATO }
9173ae02089SMasatake YAMATO
PerlParser(void)9183ae02089SMasatake YAMATO extern parserDefinition* PerlParser (void)
9193ae02089SMasatake YAMATO {
92029aa5086SYura Mikhel static const char *const extensions [] = { "pl", "pm", "ph", "plx", "perl", NULL };
921785a3ec8SMasatake YAMATO static const char *const aliases [] = {
922785a3ec8SMasatake YAMATO /* cperl is an Emacs' editing mode for Perl source code */
923785a3ec8SMasatake YAMATO "cperl",
924785a3ec8SMasatake YAMATO NULL };
9255a38b5ceSMasatake YAMATO static selectLanguage selectors [] = { selectByPickingPerlVersion,
9265a38b5ceSMasatake YAMATO NULL };
9273ae02089SMasatake YAMATO parserDefinition* def = parserNew ("Perl");
92809ae690fSMasatake YAMATO def->kindTable = PerlKinds;
9293db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (PerlKinds);
9303ae02089SMasatake YAMATO def->extensions = extensions;
9313ae02089SMasatake YAMATO def->parser = findPerlTags;
9325a38b5ceSMasatake YAMATO def->selectLanguage = selectors;
933785a3ec8SMasatake YAMATO def->aliases = aliases;
934cd677fe6SMasatake YAMATO
935cd677fe6SMasatake YAMATO /* Subparsers need this */
9366b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
937cd677fe6SMasatake YAMATO
9383ae02089SMasatake YAMATO return def;
9393ae02089SMasatake YAMATO }
940