47 {
true,
"copied",
"copied in source file" },
51 {
true,
'f',
"fd",
"file descriptions (FD, SD, RD)" },
52 {
true,
'g',
"group",
"group items" },
53 {
true,
'P',
"program",
"program ids" },
54 {
true,
's',
"section",
"sections" },
55 {
true,
'D',
"division",
"divisions" },
56 {
true,
'p',
"paragraph",
"paragraphs" },
57 {
true,
'd',
"data",
"data items" },
58 {
true,
'S',
"sourcefile",
"source code file",
90#define DEFINE_KEYWORD(n) { #n, KEYWORD_##n }
117#define INDICATOR_COLUMN 7
118#define PROGRAM_NAME_AREA_COLUMN 73
120#define isIdentifierChar(c) (isalnum(c) || (c) == '-')
121#define isQuote(c) ((c) == '\'' || (c) == '"')
124 /* Fixed: program starts at column 8, ends at column 72 */
126 /* Free: program starts at column 1, no specific end */
128 /* Variable: program starts at column 8, no specific end */
129 FORMAT_VARIABLE = FORMAT_FIXED | FORMAT_FREE
134 unsigned long int lineNumber;
136 const char *nextLine;
140static void cblppInit (const CobolFormat format)
142 CblInputState.line = vStringNew ();
143 CblInputState.lineNumber = 0;
144 CblInputState.nextLine = NULL;
145 CblInputState.format = format;
148static void cblppDeinit (void)
150 vStringDelete (CblInputState.line);
153static const char *cblppGetColumn (const char *line,
154 const unsigned int column)
156 unsigned int col = 0;
158 for (; *line; line++)
160 col += (*line == '\t') ? 8 : 1;
168static void cblppAppendLine (vString *buffer,
171 if (CblInputState.format & FORMAT_FIXED)
173 const char *indicator = cblppGetColumn (line, INDICATOR_COLUMN);
175 if (indicator && *indicator && *indicator != '*' && *indicator != '/')
177 const char *lineStart = indicator + 1;
178 const char *lineEnd = cblppGetColumn (line, PROGRAM_NAME_AREA_COLUMN);
180 if (*indicator == '-')
182 vStringStripTrailing (buffer);
183 while (isspace (*lineStart))
187 if (CblInputState.format == FORMAT_FIXED)
188 vStringNCatS (buffer, lineStart, lineEnd - lineStart);
190 vStringCatS (buffer, lineStart);
193 else if (line[0] != '*' && line[0] != '/')
194 vStringCatS (buffer, line);
197/* TODO: skip *> comments */
198static const char *cblppGetLine (void)
202 if (CblInputState.nextLine)
204 line = CblInputState.nextLine;
205 CblInputState.nextLine = NULL;
208 line = (const char *) readLineFromInputFile ();
210 CblInputState.lineNumber = getInputLineNumber ();
211 CblInputState.filePosition = getInputFilePosition ();
216 vStringClear (CblInputState.line);
217 cblppAppendLine (CblInputState.line, line);
219 /* check for continuation lines */
220 if (CblInputState.format & FORMAT_FIXED)
224 const char *indicator;
225 line = (const char *) readLineFromInputFile ();
228 indicator = cblppGetColumn (line, INDICATOR_COLUMN);
229 if (indicator && *indicator == '-')
230 cblppAppendLine (CblInputState.line, line);
235 CblInputState.nextLine = line;
238 return vStringValue (CblInputState.line);
241static void initCOBOLRefTagEntry (tagEntryInfo *e, const char *name,
242 const cobolKind kind, const int role)
244 initRefTagEntry (e, name, kind, role);
245 e->lineNumber = CblInputState.lineNumber;
246 e->filePosition = CblInputState.filePosition;
249static void initCOBOLTagEntry (tagEntryInfo *e, const char *name, const cobolKind kind)
251 initCOBOLRefTagEntry (e, name, kind, ROLE_DEFINITION_INDEX);
254static int makeCOBOLRefTag (const char *name, const cobolKind kind, const int role)
256 if (CobolKinds[kind].enabled)
260 initCOBOLRefTagEntry (&e, name, kind, role);
262 return makeTagEntry (&e);
268static int makeCOBOLTag (const char *name, const cobolKind kind)
270 return makeCOBOLRefTag (name, kind, ROLE_DEFINITION_INDEX);
273#define CBL_NL(nl) (*((unsigned int *) (nestingLevelGetUserData (nl))))
275static NestingLevel *popNestingLevelsToLevelNumber (NestingLevels *levels, const unsigned int levelNumber)
281 nl = nestingLevelsGetCurrent (levels);
282 if (! nl || CBL_NL (nl) < levelNumber)
284 nestingLevelsPop (levels);
290static bool isNumeric (const char *nptr, unsigned long int *num)
295 v = strtoul (nptr, &endptr, 10);
296 if (nptr != endptr && *endptr == 0)
305static void findCOBOLTags (const CobolFormat format)
307 NestingLevels *levels;
312 levels = nestingLevelsNew (sizeof (unsigned int));
314 while ((line = cblppGetLine ()) != NULL)
318 unsigned long int levelNumber;
320#define READ_WHILE(word, cond) \
323 for (i = 0; i < (ARRAY_SIZE (word) - 1) && *line && (cond); line++) \
327#define READ_LITERAL(word) \
329 const char READ_LITERAL__q = isQuote (*line) ? *line++ : 0; \
330 READ_WHILE (word, (READ_LITERAL__q && READ_LITERAL__q != *line) || \
331 isIdentifierChar (*line)); \
332 if (READ_LITERAL__q && READ_LITERAL__q == *line) \
334 keyword = lookupCaseKeyword (word, Lang_cobol); \
336#define READ_WORD(word, keyword) \
338 READ_WHILE (word, isIdentifierChar (*line)); \
339 keyword = lookupCaseKeyword (word, Lang_cobol); \
341#define READ_KEYWORD(keyword) \
343 char READ_KEYWORD__word[64]; \
344 READ_WORD (READ_KEYWORD__word, keyword); \
346#define SKIP_SPACES() do { while (isspace (*line)) line++; } while (0)
349 READ_WORD (word, keyword);
357 READ_WORD (word, keyword);
359 if (*word && *line == '.')
360 makeCOBOLTag (word, K_FILE);
363 case KEYWORD_PROGRAM_ID:
371 makeCOBOLTag (word, K_PROGRAM);
375 READ_WORD (word, keyword); // FIXME: also allow LITERAL
377 makeCOBOLRefTag (word, K_SOURCEFILE, COBOL_SOURCEFILE_COPIED);
380 case KEYWORD_CONTINUE:
381 case KEYWORD_END_EXEC:
384 /* nothing, just ignore those in following cases */;
388 if (isNumeric (word, &levelNumber))
390 READ_WORD (word, keyword);
393 if (*word && keyword != KEYWORD_FILLER)
395 int kind = KIND_GHOST_INDEX;
403 READ_KEYWORD (keyword2);
411 case KEYWORD_REDEFINES:
412 case KEYWORD_RENAMES:
421 if (kind != KIND_GHOST_INDEX)
426 unsigned int nestingLevelNumber;
428 /* for nesting purposes, level 77 is identical to 1,
432 default: nestingLevelNumber = levelNumber; break;
433 case 77: nestingLevelNumber = 1; break;
434 case 66: nestingLevelNumber = 2; break;
437 nl = popNestingLevelsToLevelNumber (levels, nestingLevelNumber);
438 initCOBOLTagEntry (&entry, word, kind);
439 if (nl && CBL_NL (nl) < nestingLevelNumber)
440 entry.extensionFields.scopeIndex = nl->corkIndex;
441 r = makeTagEntry (&entry);
442 if (levelNumber < 50 /* exclude special levels */)
444 nl = nestingLevelsPush (levels, r);
445 CBL_NL (nl) = levelNumber;
450 else if (*word && *line == '.')
451 makeCOBOLTag (word, K_PARAGRAPH);
456 READ_KEYWORD (keyword2);
459 if (keyword2 == KEYWORD_DIVISION && *line == '.')
460 makeCOBOLTag (word, K_DIVISION);
461 else if (keyword2 == KEYWORD_SECTION && *line == '.')
462 makeCOBOLTag (word, K_SECTION);
467 nestingLevelsFree (levels);
471static void findCOBOLFixedTags (void)
473 findCOBOLTags (FORMAT_FIXED);
476static void findCOBOLFreeTags (void)
478 findCOBOLTags (FORMAT_FREE);
481static void findCOBOLVariableTags (void)
483 findCOBOLTags (FORMAT_VARIABLE);
486static void initializeCobolParser (langType language)
488 Lang_cobol = language;
491static parserDefinition* commonCobolParserDefinition (const char *name,
494 parserDefinition* def = parserNew (name);
495 def->initialize = initializeCobolParser;
496 def->parser = parser;
497 def->kindTable = CobolKinds;
498 def->kindCount = ARRAY_SIZE(CobolKinds);
499 def->keywordTable = cobolKeywordTable;
500 def->keywordCount = ARRAY_SIZE(cobolKeywordTable);
501 def->useCork = CORK_QUEUE;
505extern parserDefinition* CobolParser (void)
507 static const char *const extensions [] = {
508 "cbl", "cob", "CBL", "COB", NULL };
509 parserDefinition* def = commonCobolParserDefinition ("Cobol",
511 def->extensions = extensions;
515extern parserDefinition* CobolFreeParser (void)
517 return commonCobolParserDefinition ("CobolFree", findCOBOLFreeTags);
520extern parserDefinition* CobolVariableParser (void)
522 return commonCobolParserDefinition ("CobolVariable", findCOBOLVariableTags);
static roleDefinition CobolSourcefileRoles[]
static langType Lang_cobol
static const keywordTable cobolKeywordTable[]
@ COBOL_SOURCEFILE_COPIED
static kindDefinition CobolKinds[]
#define DEFINE_KEYWORD(n)