geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

entry.c
Go to the documentation of this file.
1/*
2* Copyright (c) 1996-2002, Darren Hiebert
3*
4* This source code is released for free distribution under the terms of the
5* GNU General Public License version 2 or (at your option) any later version.
6*
7* This module contains functions for creating tag entries.
8*/
9
10/*
11* INCLUDE FILES
12*/
13#include "general.h" /* must always come first */
14
15#include <string.h>
16#include <ctype.h> /* to define isspace () */
17#include <errno.h>
18
19#if defined (HAVE_SYS_TYPES_H)
20# include <sys/types.h> /* to declare off_t on some hosts */
21#endif
22#if defined (HAVE_TYPES_H)
23# include <types.h> /* to declare off_t on some hosts */
24#endif
25#if defined (HAVE_UNISTD_H)
26# include <unistd.h> /* to declare close (), ftruncate (), truncate () */
27#endif
28
29/* These header files provide for the functions necessary to do file
30 * truncation.
31 */
32#ifdef HAVE_FCNTL_H
33# include <fcntl.h>
34#endif
35#ifdef HAVE_IO_H
36# include <io.h>
37#endif
38
39#include <stdint.h>
40#include <limits.h> /* to define INT_MAX */
41
42#include "debug.h"
43#include "entry_p.h"
44#include "field.h"
45#include "fmt_p.h"
46#include "kind.h"
47#include "nestlevel.h"
48#include "options_p.h"
49#include "ptag_p.h"
50#include "rbtree.h"
51#include "read.h"
52#include "read_p.h"
53#include "routines.h"
54#include "routines_p.h"
55#include "parse_p.h"
56#include "ptrarray.h"
57#include "sort_p.h"
58#include "strlist.h"
59#include "subparser_p.h"
60#include "trashbox.h"
61#include "writer_p.h"
62#include "xtag_p.h"
63
64/*
65* MACROS
66*/
67
68/*
69 * Portability defines
70 */
71#if !defined(HAVE_TRUNCATE) && !defined(HAVE_FTRUNCATE) && !defined(HAVE_CHSIZE)
72# define USE_REPLACEMENT_TRUNCATE
73#endif
74
75/* Hack for ridiculous practice of Microsoft Visual C++.
76 */
77#if defined (WIN32) && defined (_MSC_VER)
78# define chsize _chsize
79# define open _open
80# define close _close
81# define O_RDWR _O_RDWR
82#endif
83
84
85/* Maintains the state of the tag file.
86 */
87typedef struct eTagFile {
88 char *name;
89 char *directory;
91 struct sNumTags { unsigned long added, prev; } numTags;
92 struct sMax { size_t line, tag; } max;
94
95 int cork;
96 unsigned int corkFlags;
98
101
102typedef struct sTagEntryInfoX {
108
109/*
110* DATA DEFINITIONS
111*/
112
113static tagFile TagFile = {
114 NULL, /* tag file name */
115 NULL, /* tag file directory (absolute) */
116 NULL, /* file pointer */
117 { 0, 0 }, /* numTags */
118 { 0, 0 }, /* max */
119 NULL, /* vLine */
120 .cork = false,
121 .corkQueue = NULL,
122 .patternCacheValid = false,
123};
124
125static bool TagsToStdout = false;
126
127/*
128* FUNCTION PROTOTYPES
129*/
130#ifdef NEED_PROTO_TRUNCATE
131extern int truncate (const char *path, off_t length);
132#endif
133
134#ifdef NEED_PROTO_FTRUNCATE
135extern int ftruncate (int fd, off_t length);
136#endif
137
138/*
139* FUNCTION DEFINITIONS
140*/
141
142extern void freeTagFileResources (void)
143{
144 if (TagFile.directory != NULL)
147}
148
149extern const char *tagFileName (void)
150{
151 return TagFile.name;
152}
153
154/*
155* Pseudo tag support
156*/
157
158extern void abort_if_ferror(MIO *const mio)
159{
160 if (mio != NULL && mio_error (mio))
161 error (FATAL | PERROR, "cannot write tag file");
162}
163
164static void rememberMaxLengths (const size_t nameLength, const size_t lineLength)
165{
166 if (nameLength > TagFile.max.tag)
167 TagFile.max.tag = nameLength;
168
169 if (lineLength > TagFile.max.line)
170 TagFile.max.line = lineLength;
171}
172
173static void addCommonPseudoTags (void)
174{
175 for (int i = 0; i < PTAG_COUNT; i++)
176 {
177 if (isPtagCommonInParsers (i))
179 }
180}
181
182extern void makeFileTag (const char *const fileName)
183{
184 tagEntryInfo tag;
185
187 return;
188
189 initTagEntry (&tag, baseFilename (fileName), KIND_FILE_INDEX);
190
191 tag.isFileEntry = true;
192 tag.lineNumberEntry = true;
194
195 tag.lineNumber = 1;
197 {
198 /* isFieldEnabled is called again in the rendering
199 stage. However, it is called here for avoiding
200 unnecessary read line loop. */
201 while (readLineFromInputFile () != NULL)
202 ; /* Do nothing */
204 }
205
206 makeTagEntry (&tag);
207}
208
209static void updateSortedFlag (
210 const char *const line, MIO *const mio, MIOPos startOfLine)
211{
212 const char *const tab = strchr (line, '\t');
213
214 if (tab != NULL)
215 {
216 const long boolOffset = tab - line + 1; /* where it should be */
217
218 if (line [boolOffset] == '0' || line [boolOffset] == '1')
219 {
221
222 if (mio_getpos (mio, &nextLine) == -1 || mio_setpos (mio, &startOfLine) == -1)
223 error (WARNING, "Failed to update 'sorted' pseudo-tag");
224 else
225 {
226 MIOPos flagLocation;
227 int c, d;
228
229 do
230 c = mio_getc (mio);
231 while (c != '\t' && c != '\n');
232 mio_getpos (mio, &flagLocation);
233 d = mio_getc (mio);
234 if (c == '\t' && (d == '0' || d == '1') &&
235 d != (int) Option.sorted)
236 {
237 mio_setpos (mio, &flagLocation);
238 mio_putc (mio, Option.sorted == SO_FOLDSORTED ? '2' :
239 (Option.sorted == SO_SORTED ? '1' : '0'));
240 }
241 mio_setpos (mio, &nextLine);
242 }
243 }
244 }
245}
246
247/* Look through all line beginning with "!_TAG_FILE", and update those which
248 * require it.
249 */
250static long unsigned int updatePseudoTags (MIO *const mio)
251{
252 enum { maxEntryLength = 20 };
253 char entry [maxEntryLength + 1];
254 unsigned long linesRead = 0;
255 MIOPos startOfLine;
256 size_t entryLength;
257 const char *line;
258
259 sprintf (entry, "%sTAG_FILE", PSEUDO_TAG_PREFIX);
260 entryLength = strlen (entry);
261 Assert (entryLength < maxEntryLength);
262
263 mio_getpos (mio, &startOfLine);
264 line = readLineRaw (TagFile.vLine, mio);
265 while (line != NULL && line [0] == entry [0])
266 {
267 ++linesRead;
268 if (strncmp (line, entry, entryLength) == 0)
269 {
270 char tab, classType [16];
271
272 if (sscanf (line + entryLength, "%15s%c", classType, &tab) == 2 &&
273 tab == '\t')
274 {
275 if (strcmp (classType, "_SORTED") == 0)
276 updateSortedFlag (line, mio, startOfLine);
277 }
278 mio_getpos (mio, &startOfLine);
279 }
280 line = readLineRaw (TagFile.vLine, mio);
281 }
282 while (line != NULL) /* skip to end of file */
283 {
284 ++linesRead;
285 line = readLineRaw (TagFile.vLine, mio);
286 }
287 return linesRead;
288}
289
290/*
291 * Tag file management
292 */
293
294static bool isValidTagAddress (const char *const excmd)
295{
296 bool isValid = false;
297
298 if (strchr ("/?", excmd [0]) != NULL)
299 isValid = true;
300 else
301 {
302 char *address = xMalloc (strlen (excmd) + 1, char);
303 if (sscanf (excmd, "%[^;\n]", address) == 1 &&
304 strspn (address,"0123456789") == strlen (address))
305 isValid = true;
306 eFree (address);
307 }
308 return isValid;
309}
310
311static bool isCtagsLine (const char *const line)
312{
313 enum fieldList { TAG, TAB1, SRC_FILE, TAB2, EXCMD, NUM_FIELDS };
314 bool ok = false; /* we assume not unless confirmed */
315 const size_t fieldLength = strlen (line) + 1;
316 char *const fields = xMalloc (NUM_FIELDS * fieldLength, char);
317
318 if (fields == NULL)
319 error (FATAL, "Cannot analyze tag file");
320 else
321 {
322#define field(x) (fields + ((size_t) (x) * fieldLength))
323
324 const int numFields = sscanf (
325 line, "%[^\t]%[\t]%[^\t]%[\t]%[^\r\n]",
326 field (TAG), field (TAB1), field (SRC_FILE),
327 field (TAB2), field (EXCMD));
328
329 /* There must be exactly five fields: two tab fields containing
330 * exactly one tab each, the tag must not begin with "#", and the
331 * file name should not end with ";", and the excmd must be
332 * acceptable.
333 *
334 * These conditions will reject tag-looking lines like:
335 * int a; <C-comment>
336 * #define LABEL <C-comment>
337 */
338 if (numFields == NUM_FIELDS &&
339 strlen (field (TAB1)) == 1 &&
340 strlen (field (TAB2)) == 1 &&
341 field (TAG) [0] != '#' &&
342 field (SRC_FILE) [strlen (field (SRC_FILE)) - 1] != ';' &&
343 isValidTagAddress (field (EXCMD)))
344 ok = true;
345
346 eFree (fields);
347 }
348 return ok;
349}
350
351static bool isEtagsLine (const char *const line)
352{
353 bool result = false;
354 if (line [0] == '\f')
355 result = (bool) (line [1] == '\n' || line [1] == '\r');
356 return result;
357}
358
359static bool isTagFile (const char *const filename)
360{
361 bool ok = false; /* we assume not unless confirmed */
362 MIO *const mio = mio_new_file (filename, "rb");
363
364 if (mio == NULL && errno == ENOENT)
365 ok = true;
366 else if (mio != NULL)
367 {
368 const char *line = readLineRaw (TagFile.vLine, mio);
369
370 if (line == NULL)
371 ok = true;
372 else
373 ok = (bool) (isCtagsLine (line) || isEtagsLine (line));
374 mio_unref (mio);
375 }
376 return ok;
377}
378
379extern void openTagFile (void)
380{
383
384 if (TagFile.vLine == NULL)
386
387 /* Open the tags file.
388 */
389 if (TagsToStdout)
390 {
391 if (Option.interactive == INTERACTIVE_SANDBOX)
392 {
394 TagFile.name = NULL;
395 }
396 else
397 TagFile.mio = tempFile ("w+", &TagFile.name);
400 }
401 else
402 {
403 bool fileExists;
404
406 fileExists = doesFileExist (TagFile.name);
407 if (fileExists && ! isTagFile (TagFile.name))
408 error (FATAL,
409 "\"%s\" doesn't look like a tag file; I refuse to overwrite it.",
410 TagFile.name);
411
412 if (Option.etags)
413 {
414 if (Option.append && fileExists)
416 else
418 }
419 else
420 {
421 if (Option.append && fileExists)
422 {
424 if (TagFile.mio != NULL)
425 {
429 }
430 }
431 else
432 {
436 }
437 }
438 if (TagFile.mio == NULL)
439 error (FATAL | PERROR, "cannot open tag file");
440 }
441
442 if (TagFile.directory == NULL)
443 {
444 if (TagsToStdout)
446 else
448 }
449}
450
451#ifdef USE_REPLACEMENT_TRUNCATE
452
453static void copyBytes (MIO* const fromMio, MIO* const toMio, const long size)
454{
455 enum { BufferSize = 1000 };
456 long toRead, numRead;
457 char* buffer = xMalloc (BufferSize, char);
458 long remaining = size;
459 do
460 {
461 toRead = (0 < remaining && remaining < BufferSize) ?
462 remaining : (long) BufferSize;
463 numRead = mio_read (fromMio, buffer, (size_t) 1, (size_t) toRead);
464 if (mio_write (toMio, buffer, (size_t)1, (size_t)numRead) < (size_t)numRead)
465 error (FATAL | PERROR, "cannot complete write");
466 if (remaining > 0)
467 remaining -= numRead;
468 } while (numRead == toRead && remaining != 0);
469 eFree (buffer);
470}
471
472static void copyFile (const char *const from, const char *const to, const long size)
473{
474 MIO* const fromMio = mio_new_file (from, "rb");
475 if (fromMio == NULL)
476 error (FATAL | PERROR, "cannot open file to copy");
477 else
478 {
479 MIO* const toMio = mio_new_file (to, "wb");
480 if (toMio == NULL)
481 error (FATAL | PERROR, "cannot open copy destination");
482 else
483 {
484 copyBytes (fromMio, toMio, size);
485 mio_unref (toMio);
486 }
487 mio_unref (fromMio);
488 }
489}
490
491/* Replacement for missing library function.
492 */
493static int replacementTruncate (const char *const name, const long size)
494{
495#define WHOLE_FILE -1L
496 char *tempName = NULL;
497 MIO *mio = tempFile ("w", &tempName);
498 mio_unref (mio);
499 copyFile (name, tempName, size);
501 remove (tempName);
502 eFree (tempName);
503
504 return 0;
505}
506
507#endif
508
509#ifndef EXTERNAL_SORT
510static void internalSortTagFile (void)
511{
512 MIO *mio;
513
514 /* Open/Prepare the tag file and place its lines into allocated buffers.
515 */
516 if (TagsToStdout)
517 {
518 mio = TagFile.mio;
519 mio_seek (mio, 0, SEEK_SET);
520 }
521 else
522 {
523 mio = mio_new_file (tagFileName (), "r");
524 if (mio == NULL)
525 failedSort (mio, NULL);
526 }
527
529 mio,
531
532 if (! TagsToStdout)
533 mio_unref (mio);
534}
535#endif
536
537static void sortTagFile (void)
538{
539 if (TagFile.numTags.added > 0L)
540 {
542 {
543 verbose ("sorting tag file\n");
544#ifdef EXTERNAL_SORT
545 externalSortTags (TagsToStdout, TagFile.mio);
546#else
548#endif
549 }
550 else if (TagsToStdout)
552 }
553}
554
555static void resizeTagFile (const long newSize)
556{
557 int result;
558
559 if (!TagFile.name)
560 {
561 mio_try_resize (TagFile.mio, newSize);
562 return;
563 }
564
565#ifdef USE_REPLACEMENT_TRUNCATE
566 result = replacementTruncate (TagFile.name, newSize);
567#else
568# ifdef HAVE_TRUNCATE
569 result = truncate (TagFile.name, (off_t) newSize);
570# else
571 const int fd = open (TagFile.name, O_RDWR);
572
573 if (fd == -1)
574 result = -1;
575 else
576 {
577# ifdef HAVE_FTRUNCATE
578 result = ftruncate (fd, (off_t) newSize);
579# else
580# ifdef HAVE_CHSIZE
581 result = chsize (fd, newSize);
582# endif
583# endif
584 close (fd);
585 }
586# endif
587#endif
588 if (result == -1)
589 fprintf (stderr, "Cannot shorten tag file: errno = %d\n", errno);
590}
591
592static void writeEtagsIncludes (MIO *const mio)
593{
595 {
596 unsigned int i;
597 for (i = 0 ; i < stringListCount (Option.etagsInclude) ; ++i)
598 {
600 mio_printf (mio, "\f\n%s,include\n", vStringValue (item));
601 }
602 }
603}
604
605extern void closeTagFile (const bool resize)
606{
607 long desiredSize, size;
608
609 if (Option.etags)
612
614 desiredSize = mio_tell (TagFile.mio);
615 mio_seek (TagFile.mio, 0L, SEEK_END);
616 size = mio_tell (TagFile.mio);
617 if (! TagsToStdout)
618 /* The tag file should be closed before resizing. */
619 if (mio_unref (TagFile.mio) != 0)
620 error (FATAL | PERROR, "cannot close tag file");
621
622 if (resize && desiredSize < size)
623 {
625 debugPrintf (DEBUG_STATUS, "shrinking %s from %ld to %ld bytes\n",
626 TagFile.name? TagFile.name: "<mio>", size, desiredSize); )
627 resizeTagFile (desiredSize);
628 }
629 sortTagFile ();
630 if (TagsToStdout)
631 {
632 if (mio_unref (TagFile.mio) != 0)
633 error (FATAL | PERROR, "cannot close tag file");
634 if (TagFile.name)
635 remove (TagFile.name); /* remove temporary file */
636 }
637
638 TagFile.mio = NULL;
639 if (TagFile.name)
641 TagFile.name = NULL;
642}
643
644/*
645 * Tag entry management
646 */
647
648/* This function copies the current line out to a specified file. It has no
649 * effect on the fileGetc () function. During copying, any '\' characters
650 * are doubled and a leading '^' or trailing '$' is also quoted. End of line
651 * characters (line feed or carriage return) are dropped.
652 */
653static size_t appendInputLine (int putc_func (char , void *), const char *const line,
654 unsigned int patternLengthLimit,
655 void * data, bool *omitted)
656{
657 size_t length = 0;
658 const char *p;
659 int extraLength = 0;
660
661 /* Write everything up to, but not including, a line end character.
662 */
663 *omitted = false;
664 for (p = line ; *p != '\0' ; ++p)
665 {
666 const int next = *(p + 1);
667 const int c = *p;
668
669 if (c == CRETURN || c == NEWLINE)
670 break;
671
672 if (patternLengthLimit != 0 && length >= patternLengthLimit &&
673 /* Do not cut inside a multi-byte UTF-8 character, but safe-guard it not to
674 * allow more than one extra valid UTF-8 character in case it's not actually
675 * UTF-8. To do that, limit to an extra 3 UTF-8 sub-bytes (0b10xxxxxx). */
676 ((((unsigned char) c) & 0xc0) != 0x80 || ++extraLength > 3))
677 {
678 *omitted = true;
679 break;
680 }
681 /* If character is '\', or a terminal '$', then quote it.
682 */
683 if (c == BACKSLASH || c == (Option.backward ? '?' : '/') ||
684 (c == '$' && (next == NEWLINE || next == CRETURN)))
685 {
686 putc_func (BACKSLASH, data);
687 ++length;
688 }
689 putc_func (c, data);
690 ++length;
691 }
692
693 return length;
694}
695
696static int vstring_putc (char c, void *data)
697{
698 vString *str = data;
699 vStringPut (str, c);
700 return 1;
701}
702
703static int vstring_puts (const char* s, void *data)
704{
705 vString *str = data;
706 size_t len = vStringLength (str);
707 vStringCatS (str, s);
708 return (int) (vStringLength (str) - len);
709}
710
711#ifdef DEBUG
712static bool isPosSet(MIOPos pos)
713{
714 char * p = (char *)&pos;
715 bool r = false;
716 unsigned int i;
717
718 for (i = 0; i < sizeof(pos); i++)
719 r |= p[i];
720 return r;
721}
722#endif
723
724extern char *readLineFromBypassForTag (vString *const vLine, const tagEntryInfo *const tag,
725 long *const pSeekValue)
726{
727 Assert (isPosSet (tag->filePosition) || (tag->pattern == NULL));
728 return readLineFromBypass (vLine, tag->filePosition, pSeekValue);
729}
730
731/* Truncates the text line containing the tag at the character following the
732 * tag, providing a character which designates the end of the tag.
733 * Returns the length of the truncated line (or 0 if it doesn't truncate).
734 */
736 char *const line, const char *const token, const bool discardNewline)
737{
738 size_t len = 0;
739 char *p = strstr (line, token);
740
741 if (p != NULL)
742 {
743 p += strlen (token);
744 if (*p != '\0' && ! (*p == '\n' && discardNewline))
745 ++p; /* skip past character terminating character */
746 *p = '\0';
747 len = p - line;
748 }
749
750 return len;
751}
752
753static char* getFullQualifiedScopeNameFromCorkQueue (const tagEntryInfo * inner_scope)
754{
755
756 int kindIndex = KIND_GHOST_INDEX;
757 langType lang;
758 const tagEntryInfo *scope = inner_scope;
759 const tagEntryInfo *root_scope = NULL;
760 stringList *queue = stringListNew ();
761 vString *v;
762 vString *n;
763 unsigned int c;
764 const char *sep;
765
766 while (scope)
767 {
768 if (!scope->placeholder)
769 {
770 if (kindIndex != KIND_GHOST_INDEX)
771 {
772 sep = scopeSeparatorFor (lang, kindIndex, scope->kindIndex);
773 v = vStringNewInit (sep);
774 stringListAdd (queue, v);
775 }
776 /* TODO: scope field of SCOPE can be used for optimization. */
777 v = vStringNewInit (scope->name);
778 stringListAdd (queue, v);
779 kindIndex = scope->kindIndex;
780 lang = scope->langType;
781 root_scope = scope;
782 }
783 scope = getEntryInCorkQueue (scope->extensionFields.scopeIndex);
784 }
785
786 n = vStringNew ();
787 sep = root_scope? scopeSeparatorFor (root_scope->langType, root_scope->kindIndex, KIND_GHOST_INDEX): NULL;
788 if (sep)
789 vStringCatS(n, sep);
790
791 while ((c = stringListCount (queue)) > 0)
792 {
793 v = stringListLast (queue);
794 vStringCat (n, v);
795 vStringDelete (v);
796 stringListRemoveLast (queue);
797 }
798 stringListDelete (queue);
799
800 return vStringDeleteUnwrap (n);
801}
802
803extern void getTagScopeInformation (tagEntryInfo *const tag,
804 const char **kind, const char **name)
805{
806 if (kind)
807 *kind = NULL;
808 if (name)
809 *name = NULL;
810
814 && scope
816 {
817 char *full_qualified_scope_name = getFullQualifiedScopeNameFromCorkQueue(scope);
818 Assert (full_qualified_scope_name);
819
820 /* Make the information reusable to generate full qualified entry, and xformat output*/
821 tag->extensionFields.scopeLangType = scope->langType;
822 tag->extensionFields.scopeKindIndex = scope->kindIndex;
823 tag->extensionFields.scopeName = full_qualified_scope_name;
824 }
825
828 {
829 if (kind)
830 {
832 ? tag->langType
834 kindDefinition *kdef = getLanguageKind (lang,
836 *kind = kdef->name;
837 }
838 if (name)
840 }
841}
842
843
844static int makePatternStringCommon (const tagEntryInfo *const tag,
845 int (* putc_func) (char , void *),
846 int (* puts_func) (const char* , void *),
847 void *output)
848{
849 int length = 0;
850
851 char *line;
852 int searchChar;
853 const char *terminator;
854 bool omitted;
855 size_t line_len;
856
857 bool making_cache = false;
858 int (* puts_o_func)(const char* , void *);
859 void * o_output;
860
861 static vString *cached_pattern;
862 static MIOPos cached_location;
864 && (! tag->truncateLineAfterTag)
865 && (memcmp (&tag->filePosition, &cached_location, sizeof(MIOPos)) == 0))
866 return puts_func (vStringValue (cached_pattern), output);
867
869 if (line == NULL)
870 {
871 /* This can be occurs if the size of input file is zero, and
872 an empty regex pattern (//) matches to the input. */
873 line = "";
874 line_len = 0;
875 }
876 else
877 line_len = vStringLength (TagFile.vLine);
878
879 if (tag->truncateLineAfterTag)
880 {
881 size_t truncted_len;
882
883 truncted_len = truncateTagLineAfterTag (line, tag->name, false);
884 if (truncted_len > 0)
885 line_len = truncted_len;
886 }
887
888 searchChar = Option.backward ? '?' : '/';
889 terminator = (line_len > 0 && (line [line_len - 1] == '\n')) ? "$": "";
890
891 if (!tag->truncateLineAfterTag)
892 {
893 making_cache = true;
894 cached_pattern = vStringNewOrClearWithAutoRelease (cached_pattern);
895
896 puts_o_func = puts_func;
897 o_output = output;
898 putc_func = vstring_putc;
899 puts_func = vstring_puts;
900 output = cached_pattern;
901 }
902
903 length += putc_func(searchChar, output);
904 if ((tag->boundaryInfo & BOUNDARY_START) == 0)
905 length += putc_func('^', output);
906 length += appendInputLine (putc_func, line, Option.patternLengthLimit,
907 output, &omitted);
908 length += puts_func (omitted? "": terminator, output);
909 length += putc_func (searchChar, output);
910
911 if (making_cache)
912 {
913 puts_o_func (vStringValue (cached_pattern), o_output);
914 cached_location = tag->filePosition;
916 }
917
918 return length;
919}
920
921extern char* makePatternString (const tagEntryInfo *const tag)
922{
923 vString* pattern = vStringNew ();
925 return vStringDeleteUnwrap (pattern);
926}
927
928static tagField * tagFieldNew(fieldType ftype, const char *value, bool valueOwner)
929{
930 tagField *f = xMalloc (1, tagField);
931
932 f->ftype = ftype;
933 f->value = value;
934 f->valueOwner = valueOwner;
935 return f;
936}
937
938static void tagFieldDelete (tagField * f)
939{
940 if (f->valueOwner)
941 eFree((void *)f->value);
942 eFree (f);
943}
944
945static void attachParserFieldGeneric (tagEntryInfo *const tag, fieldType ftype, const char * value,
946 bool valueOwner)
947{
949 {
950 tag->parserFields [tag->usedParserFields].ftype = ftype;
951 tag->parserFields [tag->usedParserFields].value = value;
952 tag->parserFields [tag->usedParserFields].valueOwner = valueOwner;
953 tag->usedParserFields++;
954 }
955 else if (tag->parserFieldsDynamic == NULL)
956 {
959 attachParserFieldGeneric (tag, ftype, value, valueOwner);
960 }
961 else
962 {
963 tagField *f = tagFieldNew (ftype, value, valueOwner);
965 tag->usedParserFields++;
966 }
967}
968
969extern void attachParserField (tagEntryInfo *const tag, bool inCorkQueue, fieldType ftype, const char * value)
970{
971 Assert (tag != NULL);
972
973 if (inCorkQueue)
974 {
975 const char * v;
976 v = eStrdup (value);
977
978 bool dynfields_allocated = tag->parserFieldsDynamic? true: false;
979 attachParserFieldGeneric (tag, ftype, v, true);
980 if (!dynfields_allocated && tag->parserFieldsDynamic)
982 }
983 else
984 attachParserFieldGeneric (tag, ftype, value, false);
985}
986
988 fieldType ftype,
989 const char *value)
990{
992 if (tag)
993 attachParserField (tag, true, ftype, value);
994}
995
996extern const tagField* getParserFieldForIndex (const tagEntryInfo * tag, int index)
997{
998 if (index < 0
999 || tag->usedParserFields <= ((unsigned int)index) )
1000 return NULL;
1002 return tag->parserFields + index;
1003 else
1004 {
1005 unsigned int n = index - PRE_ALLOCATED_PARSER_FIELDS;
1006 return ptrArrayItem(tag->parserFieldsDynamic, n);
1007 }
1008}
1009
1010extern const char* getParserFieldValueForType (tagEntryInfo *const tag, fieldType ftype)
1011{
1012 for (int i = 0; i < tag->usedParserFields; i++)
1013 {
1014 const tagField *f = getParserFieldForIndex (tag, i);
1015 if (f && f->ftype == ftype)
1016 return f->value;
1017 }
1018 return NULL;
1019}
1020
1021static void copyParserFields (const tagEntryInfo *const tag, tagEntryInfo* slot)
1022{
1023 unsigned int i;
1024 const char* value;
1025
1026 for (i = 0; i < tag->usedParserFields; i++)
1027 {
1028 const tagField *f = getParserFieldForIndex (tag, i);
1029 Assert(f);
1030
1031 value = f->value;
1032 if (value)
1033 value = eStrdup (value);
1034
1036 f->ftype,
1037 value,
1038 true);
1039 }
1040
1041}
1042
1043static tagEntryInfo *newNilTagEntry (unsigned int corkFlags)
1044{
1046 x->corkIndex = CORK_NIL;
1047 x->symtab = RB_ROOT;
1049 return &(x->slot);
1050}
1051
1052static tagEntryInfoX *copyTagEntry (const tagEntryInfo *const tag,
1053 unsigned int corkFlags)
1054{
1056 x->symtab = RB_ROOT;
1057 x->corkIndex = CORK_NIL;
1058 tagEntryInfo *slot = (tagEntryInfo *)x;
1059
1060 *slot = *tag;
1061
1062 if (slot->pattern)
1063 slot->pattern = eStrdup (slot->pattern);
1064
1065 slot->inputFileName = eStrdup (slot->inputFileName);
1066 slot->name = eStrdup (slot->name);
1067 if (slot->extensionFields.access)
1069 if (slot->extensionFields.fileScope)
1073 if (slot->extensionFields.inheritance)
1075 if (slot->extensionFields.scopeName)
1077 if (slot->extensionFields.signature)
1079 if (slot->extensionFields.typeRef[0])
1081 if (slot->extensionFields.typeRef[1])
1083#ifdef HAVE_LIBXML
1084 if (slot->extensionFields.xpath)
1085 slot->extensionFields.xpath = eStrdup (slot->extensionFields.xpath);
1086#endif
1087
1088 if (slot->extraDynamic)
1089 {
1090 int n = countXtags () - XTAG_COUNT;
1091 slot->extraDynamic = xCalloc ((n / 8) + 1, uint8_t);
1092 memcpy (slot->extraDynamic, tag->extraDynamic, (n / 8) + 1);
1093 }
1094
1095 if (slot->sourceFileName)
1096 slot->sourceFileName = eStrdup (slot->sourceFileName);
1097
1098
1099 slot->usedParserFields = 0;
1100 slot->parserFieldsDynamic = NULL;
1101 copyParserFields (tag, slot);
1102 if (slot->parserFieldsDynamic)
1104
1105 return x;
1106}
1107
1108static void clearParserFields (tagEntryInfo *const tag)
1109{
1110 unsigned int i, n;
1111 const char* value;
1112
1114 n = tag->usedParserFields;
1115 else
1117
1118 for (i = 0; i < n; i++)
1119 {
1120 value = tag->parserFields[i].value;
1121 if (value && tag->parserFields[i].valueOwner)
1122 eFree ((char *)value);
1123 tag->parserFields[i].value = NULL;
1125 }
1126 if (tag->parserFieldsDynamic)
1127 {
1130 }
1131}
1132
1133static void deleteTagEnry (void *data)
1134{
1135 tagEntryInfo *slot = data;
1136
1137 if (slot->kindIndex == KIND_FILE_INDEX)
1138 goto out;
1139
1140 if (slot->pattern)
1141 eFree ((char *)slot->pattern);
1142 eFree ((char *)slot->inputFileName);
1143 eFree ((char *)slot->name);
1144
1145 if (slot->extensionFields.access)
1146 eFree ((char *)slot->extensionFields.access);
1147 if (slot->extensionFields.fileScope)
1148 eFree ((char *)slot->extensionFields.fileScope);
1150 eFree ((char *)slot->extensionFields.implementation);
1151 if (slot->extensionFields.inheritance)
1152 eFree ((char *)slot->extensionFields.inheritance);
1153 if (slot->extensionFields.scopeName)
1154 eFree ((char *)slot->extensionFields.scopeName);
1155 if (slot->extensionFields.signature)
1156 eFree ((char *)slot->extensionFields.signature);
1157 if (slot->extensionFields.typeRef[0])
1158 eFree ((char *)slot->extensionFields.typeRef[0]);
1159 if (slot->extensionFields.typeRef[1])
1160 eFree ((char *)slot->extensionFields.typeRef[1]);
1161#ifdef HAVE_LIBXML
1162 if (slot->extensionFields.xpath)
1163 eFree ((char *)slot->extensionFields.xpath);
1164#endif
1165
1166 if (slot->extraDynamic)
1167 eFree (slot->extraDynamic);
1168
1169 if (slot->sourceFileName)
1170 eFree ((char *)slot->sourceFileName);
1171
1172 clearParserFields (slot);
1173
1174 out:
1175 eFree (slot);
1176}
1177
1178static void corkSymtabPut (tagEntryInfoX *scope, const char* name, tagEntryInfoX *item)
1179{
1180 struct rb_root *root = &scope->symtab;
1181
1182 struct rb_node **new = &(root->rb_node), *parent = NULL;
1183
1184 while (*new)
1185 {
1186 tagEntryInfoX *this = container_of(*new, tagEntryInfoX, symnode);
1187 int result = strcmp(item->slot.name, this->slot.name);
1188
1189 parent = *new;
1190
1191 if (result < 0)
1192 new = &((*new)->rb_left);
1193 else if (result > 0)
1194 new = &((*new)->rb_right);
1195 else
1196 {
1197 unsigned long lthis = this->slot.lineNumber;
1198 unsigned long litem = item->slot.lineNumber;
1199
1200 /* Comparing lineNumber */
1201 if (litem < lthis)
1202 new = &((*new)->rb_left);
1203 else if (litem > lthis)
1204 new = &((*new)->rb_right);
1205 else
1206 {
1207 /* Comparing memory address */
1208 if (item < this)
1209 new = &((*new)->rb_left);
1210 else if (item > this)
1211 new = &((*new)->rb_right);
1212 else
1213 {
1214 AssertNotReached(); /* registering the same object twice. */
1215 return;
1216 }
1217 }
1218 }
1219 }
1220
1221 verbose ("symtbl[:=] %s<-%s/%p (line: %lu)\n",
1222 *new? container_of(*new, tagEntryInfoX, symnode)->slot.name: "*root*",
1223 item->slot.name, &item->slot, item->slot.lineNumber);
1224 /* Add new node and rebalance tree. */
1225 rb_link_node(&item->symnode, parent, new);
1226 rb_insert_color(&item->symnode, root);
1227}
1228
1229extern bool foreachEntriesInScope (int corkIndex,
1230 const char *name,
1231 entryForeachFunc func,
1232 void *data)
1233{
1234 tagEntryInfoX *x = ptrArrayItem (TagFile.corkQueue, corkIndex);
1235
1236 struct rb_root *root = &x->symtab;
1237 tagEntryInfoX *rep = NULL;
1238
1239 /* More than one tag can have a same name.
1240 * Visit them from the last.
1241 *
1242 * 1. find one of them as the representative,
1243 * 2. find the last one of them from the representative with rb_next,
1244 * 3. call FUNC iteratively from the last to the first.
1245 */
1246 if (name)
1247 {
1248 struct rb_node *node = root->rb_node;
1249 while (node)
1250 {
1251 tagEntryInfoX *entry = container_of(node, tagEntryInfoX, symnode);
1252 int result;
1253
1254 result = strcmp(name, entry->slot.name);
1255
1256 if (result < 0)
1257 node = node->rb_left;
1258 else if (result > 0)
1259 node = node->rb_right;
1260 else
1261 {
1262 rep = entry;
1263 break;
1264 }
1265 }
1266 if (rep == NULL)
1267 return true;
1268
1269 verbose("symtbl[<>] %s->%p\n", name, &rep->slot);
1270 }
1271
1272 struct rb_node *last;
1273
1274 if (name)
1275 {
1276 struct rb_node *tmp = &rep->symnode;
1277 last = tmp;
1278
1279 while ((tmp = rb_next (tmp)))
1280 {
1282 if (strcmp(name, entry->slot.name) == 0)
1283 {
1284 verbose ("symtbl[ >] %s->%p\n", name, &container_of(tmp, tagEntryInfoX, symnode)->slot);
1285 last = tmp;
1286 }
1287 else
1288 break;
1289 }
1290 }
1291 else
1292 {
1293 last = rb_last(root);
1294 verbose ("last for %d<%p>: %p\n", corkIndex, root, last);
1295 }
1296
1297 if (!last)
1298 {
1299 verbose ("symtbl[>V] %s->%p\n", name? name: "(null)", NULL);
1300 return true; /* Nothing here in this node. */
1301 }
1302
1303 verbose ("symtbl[>|] %s->%p\n", name, &container_of(last, tagEntryInfoX, symnode)->slot);
1304
1305 struct rb_node *cursor = last;
1306 bool revisited_rep = false;
1307 do
1308 {
1309 tagEntryInfoX *entry = container_of(cursor, tagEntryInfoX, symnode);
1310 if (!revisited_rep || !name || strcmp(name, entry->slot.name))
1311 {
1312 verbose ("symtbl[< ] %s->%p\n", name, &entry->slot);
1313 if (!func (entry->corkIndex, &entry->slot, data))
1314 return false;
1315 if (cursor == &rep->symnode)
1316 revisited_rep = true;
1317 }
1318 else if (name)
1319 break;
1320 }
1321 while ((cursor = rb_prev(cursor)));
1322
1323 return true;
1324}
1325
1326static bool findName (int corkIndex, tagEntryInfo *entry, void *data)
1327{
1328 int *index = data;
1329
1330 *index = corkIndex;
1331 return false;
1332}
1333
1334int anyEntryInScope (int corkIndex, const char *name)
1335{
1336 int index = CORK_NIL;
1337
1338 if (foreachEntriesInScope (corkIndex, name, findName, &index) == false)
1339 return index;
1340
1341 return CORK_NIL;
1342}
1343
1346 const int *kinds;
1348};
1349
1350static bool findNameOfKinds (int corkIndex, tagEntryInfo *entry, void *data)
1351{
1352 struct anyKindsEntryInScopeData * kdata = data;
1353
1354 for (int i = 0; i < kdata->count; i++)
1355 {
1356 int k = kdata->kinds [i];
1357 if (entry->kindIndex == k)
1358 {
1359 kdata->index = corkIndex;
1360 return false;
1361 }
1362 }
1363 return true;
1364}
1365
1366int anyKindEntryInScope (int corkIndex,
1367 const char *name, int kind)
1368{
1369 return anyKindsEntryInScope (corkIndex, name, &kind, 1);
1370}
1371
1372int anyKindsEntryInScope (int corkIndex,
1373 const char *name,
1374 const int *kinds, int count)
1375{
1376 struct anyKindsEntryInScopeData data = {
1377 .index = CORK_NIL,
1378 .kinds = kinds,
1379 .count = count,
1380 };
1381
1382 if (foreachEntriesInScope (corkIndex, name, findNameOfKinds, &data) == false)
1383 return data.index;
1384
1385 return CORK_NIL;
1386}
1387
1389 const char *name,
1390 const int *kinds, int count)
1391{
1392 struct anyKindsEntryInScopeData data = {
1393 .index = CORK_NIL,
1394 .kinds = kinds,
1395 .count = count,
1396 };
1397
1398 tagEntryInfo *e;
1399 do
1400 {
1401 if (foreachEntriesInScope (corkIndex, name, findNameOfKinds, &data) == false)
1402 return data.index;
1403
1404 if (corkIndex == CORK_NIL)
1405 break;
1406
1407 e = getEntryInCorkQueue (corkIndex);
1408 if (!e)
1409 break;
1410 corkIndex = e->extensionFields.scopeIndex;
1411 }
1412 while (1);
1413
1414 return CORK_NIL;
1415}
1416
1417extern void registerEntry (int corkIndex)
1418{
1420 Assert (corkIndex != CORK_NIL);
1421
1422 tagEntryInfoX *e = ptrArrayItem (TagFile.corkQueue, corkIndex);
1423 {
1425 corkSymtabPut (scope, e->slot.name, e);
1426 }
1427}
1428
1429static int queueTagEntry(const tagEntryInfo *const tag)
1430{
1431 static bool warned;
1432
1433 int corkIndex;
1436
1437 if (ptrArrayCount (TagFile.corkQueue) == (size_t)INT_MAX)
1438 {
1439 if (!warned)
1440 {
1441 warned = true;
1442 error (WARNING,
1443 "The tag entry queue overflows; drop the tag entry at %lu in %s",
1444 tag->lineNumber,
1445 tag->inputFileName);
1446 }
1447 return CORK_NIL;
1448 }
1449 warned = false;
1450
1451 corkIndex = (int)ptrArrayAdd (TagFile.corkQueue, entry);
1452 entry->corkIndex = corkIndex;
1453
1454 return corkIndex;
1455}
1456
1457extern void setupWriter (void *writerClientData)
1458{
1459 writerSetup (TagFile.mio, writerClientData);
1460}
1461
1462extern bool teardownWriter (const char *filename)
1463{
1465}
1466
1467static bool isTagWritable(const tagEntryInfo *const tag)
1468{
1469 if (tag->placeholder)
1470 return false;
1471
1472 if (! isLanguageKindEnabled(tag->langType, tag->kindIndex))
1473 return false;
1474
1475 if (tag->extensionFields.roleBits)
1476 {
1477 size_t available_roles;
1478
1480 return false;
1481
1482 available_roles = countLanguageRoles(tag->langType,
1483 tag->kindIndex);
1484 if (tag->extensionFields.roleBits >=
1485 (makeRoleBit(available_roles)))
1486 return false;
1487
1488 /* TODO: optimization
1489 A Bitmasks representing all enabled roles can be calculated at the
1490 end of initializing the parser. Calculating each time when checking
1491 a tag entry is not needed. */
1492 for (unsigned int roleIndex = 0; roleIndex < available_roles; roleIndex++)
1493 {
1494 if (isRoleAssigned(tag, roleIndex))
1495 {
1497 roleIndex))
1498 return true;
1499 }
1500
1501 }
1502 return false;
1503 }
1504 else if (isLanguageKindRefOnly(tag->langType, tag->kindIndex))
1505 {
1506 error (WARNING, "definition tag for refonly kind(%s) is made: %s",
1508 tag->name);
1509 /* This one is not so critical. */
1510 }
1511
1514 return false;
1515
1516 return true;
1517}
1518
1519static void buildFqTagCache (tagEntryInfo *const tag)
1520{
1522}
1523
1524static void writeTagEntry (const tagEntryInfo *const tag)
1525{
1526 int length = 0;
1527
1529
1530 DebugStatement ( debugEntry (tag); )
1531
1532#ifdef WIN32
1533 if (getFilenameSeparator(Option.useSlashAsFilenameSeparator) == FILENAME_SEP_USE_SLASH)
1534 {
1535 Assert (((const tagEntryInfo *)tag)->inputFileName);
1536 char *c = (char *)(((tagEntryInfo *const)tag)->inputFileName);
1537 while (*c)
1538 {
1539 if (*c == PATH_SEPARATOR)
1541 c++;
1542 }
1543 }
1544#endif
1545
1550 && !tag->skipAutoFQEmission)
1551 {
1552 /* const is discarded to update the cache field of TAG. */
1553 buildFqTagCache ( (tagEntryInfo *const)tag);
1554 }
1555
1556 length = writerWriteTag (TagFile.mio, tag);
1557
1558 if (length > 0)
1559 {
1561 rememberMaxLengths (strlen (tag->name), (size_t) length);
1562 }
1564
1566}
1567
1568extern bool writePseudoTag (const ptagDesc *desc,
1569 const char *const fileName,
1570 const char *const pattern,
1571 const char *const parserName)
1572{
1573 int length;
1574
1575 length = writerWritePtag (TagFile.mio, desc, fileName,
1576 pattern, parserName);
1577 if (length < 0)
1578 return false;
1579
1581
1583 rememberMaxLengths (strlen (desc->name), (size_t) length);
1584
1585 return true;
1586}
1587
1588extern void corkTagFile(unsigned int corkFlags)
1589{
1590 TagFile.cork++;
1591 if (TagFile.cork == 1)
1592 {
1593 TagFile.corkFlags = corkFlags;
1595 tagEntryInfo *nil = newNilTagEntry (corkFlags);
1597 }
1598}
1599
1600extern void uncorkTagFile(void)
1601{
1602 unsigned int i;
1603
1604 TagFile.cork--;
1605
1606 if (TagFile.cork > 0)
1607 return ;
1608
1609 for (i = 1; i < ptrArrayCount (TagFile.corkQueue); i++)
1610 {
1612
1613 if (!isTagWritable(tag))
1614 continue;
1615
1616 writeTagEntry (tag);
1617
1621 && !tag->skipAutoFQEmission
1623 && tag->extensionFields.scopeName != NULL
1626 && tag->extensionFields.scopeName == NULL
1627 && tag->extensionFields.scopeIndex == CORK_NIL)))
1629 }
1630
1633}
1634
1636{
1637 if ((CORK_NIL < n) && (((size_t)n) < ptrArrayCount (TagFile.corkQueue)))
1638 return ptrArrayItem (TagFile.corkQueue, n);
1639 else
1640 return NULL;
1641}
1642
1644{
1645 if (nl == NULL)
1646 return NULL;
1647 return getEntryInCorkQueue (nl->corkIndex);
1648}
1649
1650extern size_t countEntryInCorkQueue (void)
1651{
1653}
1654
1655extern int makePlaceholder (const char *const name)
1656{
1657 tagEntryInfo e;
1658
1660 e.placeholder = 1;
1661
1662 /*
1663 * makePlaceholder may be called even before reading any bytes
1664 * from the input stream. In such case, initTagEntry fills
1665 * the lineNumber field of the placeholder tag with 0.
1666 * This breaks an assertion in makeTagEntry. Following adjustment
1667 * is for avoiding it.
1668 */
1669 if (e.lineNumber == 0)
1670 e.lineNumber = 1;
1671
1672 return makeTagEntry (&e);
1673}
1674
1675extern int makeTagEntry (const tagEntryInfo *const tag)
1676{
1677 int r = CORK_NIL;
1678 Assert (tag->name != NULL);
1679 Assert(tag->lineNumber > 0);
1680
1681 if (!TagFile.cork)
1682 if (!isTagWritable (tag))
1683 goto out;
1684
1685 if (tag->name [0] == '\0' && (!tag->placeholder))
1686 {
1688 error (WARNING, "ignoring null tag in %s(line: %lu)",
1689 getInputFileName (), tag->lineNumber);
1690 goto out;
1691 }
1692
1693 if (TagFile.cork)
1694 r = queueTagEntry (tag);
1695 else
1696 writeTagEntry (tag);
1697
1698 if (r != CORK_NIL)
1699 notifyMakeTagEntry (tag, r);
1700
1701out:
1702 return r;
1703}
1704
1705extern int makeQualifiedTagEntry (const tagEntryInfo *const e)
1706{
1707 int r = CORK_NIL;
1708 tagEntryInfo x;
1709 int xk;
1710 const char *sep;
1711 static vString *fqn;
1712
1714 {
1715 x = *e;
1717
1719
1721 {
1724 sep = scopeSeparatorFor (e->langType, e->kindIndex, xk);
1725 vStringCatS (fqn, sep);
1726 }
1727 else
1728 {
1729 /* This is an top level item. prepend a root separator
1730 if the kind of the item has. */
1732 if (sep == NULL)
1733 {
1734 /* No root separator. The name of the
1735 optional tag and that of full qualified tag
1736 are the same; recording the full qualified tag
1737 is meaningless. */
1738 return r;
1739 }
1740 else
1741 vStringCatS (fqn, sep);
1742 }
1743 vStringCatS (fqn, e->name);
1744
1745 x.name = vStringValue (fqn);
1746 /* makeExtraTagEntry of c.c doesn't clear scope
1747 related fields. */
1748#if 0
1749 x.extensionFields.scopeKind = NULL;
1752#endif
1753
1754 bool in_subparser
1755 = isTagExtraBitMarked (&x,
1757
1758 if (in_subparser)
1760
1761 r = makeTagEntry (&x);
1762
1763 if (in_subparser)
1764 popLanguage();
1765 }
1766 return r;
1767}
1768
1769static void initTagEntryFull (tagEntryInfo *const e, const char *const name,
1770 unsigned long lineNumber,
1771 langType langType_,
1773 const char *inputFileName,
1774 int kindIndex,
1775 roleBitsType roleBits,
1776 const char *sourceFileName,
1777 langType sourceLangType,
1778 long sourceLineNumberDifference)
1779{
1780 int i;
1781
1783
1784 memset (e, 0, sizeof (tagEntryInfo));
1785 e->lineNumberEntry = (bool) (Option.locate == EX_LINENUM);
1788 e->langType = langType_;
1790 e->inputFileName = inputFileName;
1791 e->name = name;
1795
1796 Assert (kindIndex < 0 || kindIndex < (int)countLanguageKinds(langType_));
1797 e->kindIndex = kindIndex;
1798
1799 Assert (roleBits == 0
1800 || (roleBits < (makeRoleBit(countLanguageRoles(langType_, kindIndex)))));
1801 e->extensionFields.roleBits = roleBits;
1802 if (roleBits)
1804
1805 if (doesParserRunAsGuest ())
1807 if (doesSubparserRun ())
1809
1810 e->sourceLangType = sourceLangType;
1811 e->sourceFileName = sourceFileName;
1812 e->sourceLineNumberDifference = sourceLineNumberDifference;
1813
1814 e->usedParserFields = 0;
1815
1816 for ( i = 0; i < PRE_ALLOCATED_PARSER_FIELDS; i++ )
1818
1820 e->placeholder = 1;
1821}
1822
1823extern void initTagEntry (tagEntryInfo *const e, const char *const name,
1824 int kindIndex)
1825{
1831 kindIndex,
1832 0,
1836}
1837
1838extern void initRefTagEntry (tagEntryInfo *const e, const char *const name,
1839 int kindIndex, int roleIndex)
1840{
1841 initForeignRefTagEntry (e, name, getInputLanguage (), kindIndex, roleIndex);
1842}
1843
1844extern void initForeignRefTagEntry (tagEntryInfo *const e, const char *const name,
1846 int kindIndex, int roleIndex)
1847{
1850 langType,
1853 kindIndex,
1854 makeRoleBit(roleIndex),
1858}
1859
1860static void markTagExtraBitFull (tagEntryInfo *const tag, xtagType extra, bool mark)
1861{
1862 unsigned int index;
1863 unsigned int offset;
1864 uint8_t *slot;
1865
1866 Assert (extra != XTAG_UNKNOWN);
1867
1868 if (extra < XTAG_COUNT)
1869 {
1870 index = (extra / 8);
1871 offset = (extra % 8);
1872 slot = tag->extra;
1873 }
1874 else if (tag->extraDynamic)
1875 {
1876 Assert (extra < countXtags ());
1877
1878 index = ((extra - XTAG_COUNT) / 8);
1879 offset = ((extra - XTAG_COUNT) % 8);
1880 slot = tag->extraDynamic;
1881 }
1882 else
1883 {
1884 Assert (extra < countXtags ());
1885
1886 int n = countXtags () - XTAG_COUNT;
1887 tag->extraDynamic = xCalloc ((n / 8) + 1, uint8_t);
1889 markTagExtraBit (tag, extra);
1890 return;
1891 }
1892
1893 if (mark)
1894 slot [ index ] |= (1 << offset);
1895 else
1896 slot [ index ] &= ~(1 << offset);
1897}
1898
1899extern void markTagExtraBit (tagEntryInfo *const tag, xtagType extra)
1900{
1901 markTagExtraBitFull (tag, extra, true);
1902}
1903
1904extern bool isTagExtraBitMarked (const tagEntryInfo *const tag, xtagType extra)
1905{
1906 unsigned int index;
1907 unsigned int offset;
1908 const uint8_t *slot;
1909
1910 Assert (extra != XTAG_UNKNOWN);
1911
1912 if (extra < XTAG_COUNT)
1913 {
1914 index = (extra / 8);
1915 offset = (extra % 8);
1916 slot = tag->extra;
1917
1918 }
1919 else if (!tag->extraDynamic)
1920 return false;
1921 else
1922 {
1923 Assert (extra < countXtags ());
1924 index = ((extra - XTAG_COUNT) / 8);
1925 offset = ((extra - XTAG_COUNT) % 8);
1926 slot = tag->extraDynamic;
1927
1928 }
1929 return !! ((slot [ index ]) & (1 << offset));
1930}
1931
1932extern bool isTagExtra (const tagEntryInfo *const tag)
1933{
1934 for (unsigned int i = 0; i < XTAG_COUNT; i++)
1935 if (isTagExtraBitMarked (tag, i))
1936 return true;
1937 return false;
1938}
1939
1940static void assignRoleFull(tagEntryInfo *const e, int roleIndex, bool assign)
1941{
1942 if (roleIndex == ROLE_DEFINITION_INDEX)
1943 {
1944 if (assign)
1945 {
1948 }
1949 }
1950 else if (roleIndex > ROLE_DEFINITION_INDEX)
1951 {
1952 Assert (roleIndex < (int)countLanguageRoles(e->langType, e->kindIndex));
1953
1954 if (assign)
1955 e->extensionFields.roleBits |= (makeRoleBit(roleIndex));
1956 else
1957 e->extensionFields.roleBits &= ~(makeRoleBit(roleIndex));
1959 }
1960 else
1962}
1963
1964extern void assignRole(tagEntryInfo *const e, int roleIndex)
1965{
1966 assignRoleFull(e, roleIndex, true);
1967}
1968
1969extern bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex)
1970{
1971 if (roleIndex == ROLE_DEFINITION_INDEX)
1972 return (!e->extensionFields.roleBits);
1973 else
1974 return (e->extensionFields.roleBits & makeRoleBit(roleIndex));
1975}
1976
1977extern unsigned long numTagsAdded(void)
1978{
1979 return TagFile.numTags.added;
1980}
1981
1982extern void setNumTagsAdded (unsigned long nadded)
1983{
1984 TagFile.numTags.added = nadded;
1985}
1986
1987extern unsigned long numTagsTotal(void)
1988{
1990}
1991
1992extern unsigned long maxTagsLine (void)
1993{
1994 return (unsigned long)TagFile.max.line;
1995}
1996
1997extern void invalidatePatternCache(void)
1998{
1999 TagFile.patternCacheValid = false;
2000}
2001
2002extern void tagFilePosition (MIOPos *p)
2003{
2004 /* mini-geany doesn't set TagFile.mio. */
2005 if (TagFile.mio == NULL)
2006 return;
2007
2008 if (mio_getpos (TagFile.mio, p) == -1)
2010 "failed to get file position of the tag file\n");
2011}
2012
2014{
2015 /* mini-geany doesn't set TagFile.mio. */
2016 if (TagFile.mio == NULL)
2017 return;
2018
2019 if (mio_setpos (TagFile.mio, p) == -1)
2021 "failed to set file position of the tag file\n");
2022}
2023
2024extern const char* getTagFileDirectory (void)
2025{
2026 return TagFile.directory;
2027}
2028
2030{
2031 e->placeholder = 1;
2033 return true;
2034}
2035
2037{
2039}
gint index
Definition: build.c:2680
#define Assert(c)
Definition: debug.h:47
#define DebugStatement(x)
Definition: debug.h:45
@ DEBUG_STATUS
Definition: debug.h:67
#define AssertNotReached()
Definition: debug.h:48
void debugPrintf(const enum eDebugLevels level, const char *const format,...)
void debugEntry(const tagEntryInfo *const tag)
void notifyMakeTagEntry(const tagEntryInfo *tag, int corkIndex)
Definition: dependency.c:180
bool doesSubparserRun(void)
Definition: dependency.c:281
const gchar * name
Definition: document.c:3219
gint pos
Definition: editor.c:87
void tagFilePosition(MIOPos *p)
Definition: entry.c:2002
int makeTagEntry(const tagEntryInfo *const tag)
Definition: entry.c:1675
static bool isTagFile(const char *const filename)
Definition: entry.c:359
static void deleteTagEnry(void *data)
Definition: entry.c:1133
static void addCommonPseudoTags(void)
Definition: entry.c:173
tagEntryInfo * getEntryOfNestingLevel(const NestingLevel *nl)
Definition: entry.c:1643
static tagEntryInfoX * copyTagEntry(const tagEntryInfo *const tag, unsigned int corkFlags)
Definition: entry.c:1052
static tagField * tagFieldNew(fieldType ftype, const char *value, bool valueOwner)
Definition: entry.c:928
void assignRole(tagEntryInfo *const e, int roleIndex)
Definition: entry.c:1964
void freeTagFileResources(void)
Definition: entry.c:142
void markTagExtraBit(tagEntryInfo *const tag, xtagType extra)
Definition: entry.c:1899
static void internalSortTagFile(void)
Definition: entry.c:510
void attachParserFieldToCorkEntry(int index, fieldType ftype, const char *value)
Definition: entry.c:987
static char * getFullQualifiedScopeNameFromCorkQueue(const tagEntryInfo *inner_scope)
Definition: entry.c:753
unsigned long numTagsAdded(void)
Definition: entry.c:1977
void getTagScopeInformation(tagEntryInfo *const tag, const char **kind, const char **name)
Definition: entry.c:803
bool isTagExtra(const tagEntryInfo *const tag)
Definition: entry.c:1932
static void clearParserFields(tagEntryInfo *const tag)
Definition: entry.c:1108
bool isTagExtraBitMarked(const tagEntryInfo *const tag, xtagType extra)
Definition: entry.c:1904
void makeFileTag(const char *const fileName)
Definition: entry.c:182
const char * tagFileName(void)
Definition: entry.c:149
const tagField * getParserFieldForIndex(const tagEntryInfo *tag, int index)
Definition: entry.c:996
bool writePseudoTag(const ptagDesc *desc, const char *const fileName, const char *const pattern, const char *const parserName)
Definition: entry.c:1568
void corkTagFile(unsigned int corkFlags)
Definition: entry.c:1588
void setupWriter(void *writerClientData)
Definition: entry.c:1457
static void sortTagFile(void)
Definition: entry.c:537
static int makePatternStringCommon(const tagEntryInfo *const tag, int(*putc_func)(char, void *), int(*puts_func)(const char *, void *), void *output)
Definition: entry.c:844
void setTagFilePosition(MIOPos *p)
Definition: entry.c:2013
size_t truncateTagLineAfterTag(char *const line, const char *const token, const bool discardNewline)
Definition: entry.c:735
static void copyFile(const char *const from, const char *const to, const long size)
Definition: entry.c:472
static void resizeTagFile(const long newSize)
Definition: entry.c:555
#define field(x)
static bool isEtagsLine(const char *const line)
Definition: entry.c:351
static void writeEtagsIncludes(MIO *const mio)
Definition: entry.c:592
static void markTagExtraBitFull(tagEntryInfo *const tag, xtagType extra, bool mark)
Definition: entry.c:1860
void invalidatePatternCache(void)
Definition: entry.c:1997
char * readLineFromBypassForTag(vString *const vLine, const tagEntryInfo *const tag, long *const pSeekValue)
Definition: entry.c:724
static void assignRoleFull(tagEntryInfo *const e, int roleIndex, bool assign)
Definition: entry.c:1940
int makeQualifiedTagEntry(const tagEntryInfo *const e)
Definition: entry.c:1705
static tagEntryInfo * newNilTagEntry(unsigned int corkFlags)
Definition: entry.c:1043
void abort_if_ferror(MIO *const mio)
Definition: entry.c:158
void initRefTagEntry(tagEntryInfo *const e, const char *const name, int kindIndex, int roleIndex)
Definition: entry.c:1838
static void initTagEntryFull(tagEntryInfo *const e, const char *const name, unsigned long lineNumber, langType langType_, MIOPos filePosition, const char *inputFileName, int kindIndex, roleBitsType roleBits, const char *sourceFileName, langType sourceLangType, long sourceLineNumberDifference)
Definition: entry.c:1769
static void writeTagEntry(const tagEntryInfo *const tag)
Definition: entry.c:1524
static bool findName(int corkIndex, tagEntryInfo *entry, void *data)
Definition: entry.c:1326
tagEntryInfo * getEntryInCorkQueue(int n)
Definition: entry.c:1635
void registerEntry(int corkIndex)
Definition: entry.c:1417
int anyKindsEntryInScopeRecursive(int corkIndex, const char *name, const int *kinds, int count)
Definition: entry.c:1388
static void rememberMaxLengths(const size_t nameLength, const size_t lineLength)
Definition: entry.c:164
static void corkSymtabPut(tagEntryInfoX *scope, const char *name, tagEntryInfoX *item)
Definition: entry.c:1178
static void tagFieldDelete(tagField *f)
Definition: entry.c:938
static void buildFqTagCache(tagEntryInfo *const tag)
Definition: entry.c:1519
void setNumTagsAdded(unsigned long nadded)
Definition: entry.c:1982
int anyKindsEntryInScope(int corkIndex, const char *name, const int *kinds, int count)
Definition: entry.c:1372
struct sTagEntryInfoX tagEntryInfoX
void closeTagFile(const bool resize)
Definition: entry.c:605
void initTagEntry(tagEntryInfo *const e, const char *const name, int kindIndex)
Definition: entry.c:1823
void openTagFile(void)
Definition: entry.c:379
static size_t appendInputLine(int putc_func(char, void *), const char *const line, unsigned int patternLengthLimit, void *data, bool *omitted)
Definition: entry.c:653
static bool TagsToStdout
Definition: entry.c:125
void markAllEntriesInScopeAsPlaceholder(int index)
Definition: entry.c:2036
#define WHOLE_FILE
size_t countEntryInCorkQueue(void)
Definition: entry.c:1650
bool foreachEntriesInScope(int corkIndex, const char *name, entryForeachFunc func, void *data)
Definition: entry.c:1229
struct eTagFile tagFile
static long unsigned int updatePseudoTags(MIO *const mio)
Definition: entry.c:250
char * makePatternString(const tagEntryInfo *const tag)
Definition: entry.c:921
unsigned long maxTagsLine(void)
Definition: entry.c:1992
static bool findNameOfKinds(int corkIndex, tagEntryInfo *entry, void *data)
Definition: entry.c:1350
int anyEntryInScope(int corkIndex, const char *name)
Definition: entry.c:1334
static bool markAsPlaceholder(int index, tagEntryInfo *e, void *data)
Definition: entry.c:2029
void attachParserField(tagEntryInfo *const tag, bool inCorkQueue, fieldType ftype, const char *value)
Definition: entry.c:969
bool isRoleAssigned(const tagEntryInfo *const e, int roleIndex)
Definition: entry.c:1969
static bool isTagWritable(const tagEntryInfo *const tag)
Definition: entry.c:1467
int anyKindEntryInScope(int corkIndex, const char *name, int kind)
Definition: entry.c:1366
static int vstring_puts(const char *s, void *data)
Definition: entry.c:703
const char * getTagFileDirectory(void)
Definition: entry.c:2024
void uncorkTagFile(void)
Definition: entry.c:1600
static void attachParserFieldGeneric(tagEntryInfo *const tag, fieldType ftype, const char *value, bool valueOwner)
Definition: entry.c:945
static tagFile TagFile
Definition: entry.c:113
const char * getParserFieldValueForType(tagEntryInfo *const tag, fieldType ftype)
Definition: entry.c:1010
static void copyParserFields(const tagEntryInfo *const tag, tagEntryInfo *slot)
Definition: entry.c:1021
static void updateSortedFlag(const char *const line, MIO *const mio, MIOPos startOfLine)
Definition: entry.c:209
int makePlaceholder(const char *const name)
Definition: entry.c:1655
bool teardownWriter(const char *filename)
Definition: entry.c:1462
static int vstring_putc(char c, void *data)
Definition: entry.c:696
static bool isValidTagAddress(const char *const excmd)
Definition: entry.c:294
unsigned long numTagsTotal(void)
Definition: entry.c:1987
static int replacementTruncate(const char *const name, const long size)
Definition: entry.c:493
static bool isCtagsLine(const char *const line)
Definition: entry.c:311
static int queueTagEntry(const tagEntryInfo *const tag)
Definition: entry.c:1429
void initForeignRefTagEntry(tagEntryInfo *const e, const char *const name, langType langType, int kindIndex, int roleIndex)
Definition: entry.c:1844
static void copyBytes(MIO *const fromMio, MIO *const toMio, const long size)
Definition: entry.c:453
uint64_t roleBitsType
Definition: entry.h:39
#define PRE_ALLOCATED_PARSER_FIELDS
Definition: entry.h:107
bool(* entryForeachFunc)(int corkIndex, tagEntryInfo *entry, void *data)
Definition: entry.h:119
#define ROLE_DEFINITION_INDEX
Definition: entry.h:90
#define CORK_NIL
Definition: entry.h:145
static roleBitsType makeRoleBit(int roleIndex)
Definition: entry_p.h:69
void error(const errorSelection selection, const char *const format,...)
Definition: error.c:53
bool isFieldEnabled(fieldType type)
Definition: field.c:945
enum eFieldType fieldType
@ FIELD_UNKNOWN
Definition: field.h:29
@ FIELD_END_LINE
Definition: field.h:59
GtkWidget * open
Definition: filebrowser.c:96
int errno
#define CTAGS_ATTR_UNUSED
Definition: gcc-attr.h:22
unsigned long int lineNumber
Definition: geany_cobol.c:134
vString * line
Definition: geany_cobol.c:133
MIOPos filePosition
Definition: geany_cobol.c:135
const char * nextLine
Definition: geany_cobol.c:136
unsigned int count
static vString * scope
Definition: geany_go.c:78
static vString * tempName
Definition: geany_objc.c:419
#define KIND_GHOST_INDEX
Definition: kind.h:55
const char * scopeSeparatorFor(langType lang, int kindIndex, int parentKindIndex)
Definition: parse.c:531
#define KIND_FILE_INDEX
Definition: kind.h:59
size_t mio_write(MIO *mio, const void *ptr, size_t size, size_t nmemb)
mio_write: @mio: A MIO object @ptr: Pointer to the memory to write on the stream @size: Size of each ...
Definition: mio.c:689
int mio_getc(MIO *mio)
mio_getc: @mio: A MIO object
Definition: mio.c:884
long mio_tell(MIO *mio)
mio_tell: @mio: A MIO object
Definition: mio.c:1174
MIO * mio_new_file(const char *filename, const char *mode)
mio_new_file: @filename: Filename to open, same as the fopen()'s first argument @mode: Mode in which ...
Definition: mio.c:234
size_t mio_read(MIO *mio, void *ptr_, size_t size, size_t nmemb)
mio_read: @mio: A MIO object @ptr: Pointer to the memory to fill with the read data @size: Size of ea...
Definition: mio.c:536
int mio_seek(MIO *mio, long offset, int whence)
mio_seek: @mio: A MIO object @offset: Offset of the new place, from @whence @whence: Move origin.
Definition: mio.c:1101
int mio_try_resize(MIO *mio, size_t new_size)
Definition: mio.c:652
int mio_getpos(MIO *mio, MIOPos *pos)
mio_getpos: @mio: A MIO stream @pos: (out): A MIOPos object to fill-in
Definition: mio.c:1235
int mio_flush(MIO *mio)
mio_flush: @mio: A MIO object
Definition: mio.c:1335
int mio_error(MIO *mio)
mio_error: @mio: A MIO object
Definition: mio.c:1074
MIO * mio_new_memory(unsigned char *data, size_t size, MIOReallocFunc realloc_func, MIODestroyNotify free_func)
mio_new_memory: @data: Initial data (may be NULL) @size: Length of @data in bytes @realloc_func: A fu...
Definition: mio.c:316
int mio_printf(MIO *mio, const char *format,...)
mio_printf: @mio: A MIO object @format: A print format string ...: Arguments of the format
Definition: mio.c:863
int mio_putc(MIO *mio, int c)
mio_putc: @mio: A MIO object : The character to write
Definition: mio.c:729
int mio_unref(MIO *mio)
mio_unref: @mio: A MIO object
Definition: mio.c:480
int mio_setpos(MIO *mio, MIOPos *pos)
mio_setpos: @mio: A MIO object @pos: (in): A MIOPos object filled-in by a previous call of mio_getpos...
Definition: mio.c:1287
void verbose(const char *const format,...)
Definition: options.c:655
void setDefaultTagFileName(void)
Definition: options.c:706
bool isDestinationStdout(void)
Definition: options.c:3918
optionValues Option
Definition: options.c:137
@ EX_LINENUM
Definition: options_p.h:55
@ SO_SORTED
Definition: options_p.h:62
@ SO_FOLDSORTED
Definition: options_p.h:63
@ SO_UNSORTED
Definition: options_p.h:61
#define includeExtensionFlags()
Definition: options_p.h:34
kindDefinition * getLanguageKind(const langType language, int kindIndex)
Definition: parse.c:317
bool isLanguageKindRefOnly(const langType language, int kindIndex)
Definition: parse.c:2235
bool isLanguageKindEnabled(const langType language, int kindIndex)
Definition: parse.c:2223
bool isLanguageRoleEnabled(const langType language, int kindIndex, int roleIndex)
Definition: parse.c:2229
bool isParserMarkedNoEmission(void)
Definition: parse.c:4851
unsigned int countLanguageRoles(const langType language, int kindIndex)
Definition: parse.c:312
unsigned int countLanguageKinds(const langType language)
Definition: parse.c:307
#define LANG_IGNORE
Definition: parse.h:27
@ CORK_SYMTAB
Definition: parse.h:70
#define LANG_AUTO
Definition: parse.h:26
bool isPtagCommonInParsers(ptagType type)
Definition: ptag.c:258
bool makePtagIfEnabled(ptagType type, langType language, const void *data)
Definition: ptag.c:201
#define PSEUDO_TAG_PREFIX
Definition: ptag_p.h:18
@ PTAG_COUNT
Definition: ptag_p.h:45
unsigned int ptrArrayCount(const ptrArray *const current)
Definition: ptrarray.c:80
void * ptrArrayItem(const ptrArray *const current, const unsigned int indx)
Definition: ptrarray.c:86
ptrArray * ptrArrayNew(ptrArrayDeleteFunc deleteFunc)
Definition: ptrarray.c:37
void ptrArrayDelete(ptrArray *const current)
Definition: ptrarray.c:111
unsigned int ptrArrayAdd(ptrArray *const current, void *ptr)
Definition: ptrarray.c:47
void(* ptrArrayDeleteFunc)(void *data)
Definition: ptrarray.h:24
struct rb_node * rb_prev(const struct rb_node *node)
Definition: rbtree.c:423
struct rb_node * rb_next(const struct rb_node *node)
Definition: rbtree.c:395
void rb_insert_color(struct rb_node *node, struct rb_root *root)
Definition: rbtree.c:88
struct rb_node * rb_last(const struct rb_root *root)
Definition: rbtree.c:383
#define NULL
Definition: rbtree.h:150
#define RB_ROOT
Definition: rbtree.h:185
static void rb_link_node(struct rb_node *node, struct rb_node *parent, struct rb_node **rb_link)
Definition: rbtree.h:221
#define container_of(ptr, type, member)
Definition: rbtree.h:134
char * readLineFromBypass(vString *const vLine, MIOPos location, long *const pSeekValue)
Definition: read.c:1035
char * readLineRaw(vString *const vLine, MIO *const mio)
Definition: read.c:1016
langType getSourceLanguage(void)
Definition: read.c:257
unsigned long getSourceLineNumber(void)
Definition: read.c:262
const char * getInputFileTagPath(void)
Definition: read.c:206
const unsigned char * readLineFromInputFile(void)
Definition: read.c:1000
unsigned long getInputLineNumber(void)
Definition: read.c:142
langType getInputLanguage(void)
Definition: read.c:196
MIOPos getInputFilePosition(void)
Definition: read.c:161
const char * getSourceFileTagPath(void)
Definition: read.c:252
bool doesInputLanguageRequestAutomaticFQTag(void)
Definition: read.c:247
langType popLanguage(void)
Definition: read.c:1159
const char * getInputFileName(void)
Definition: read.c:154
unsigned int getNestedInputBoundaryInfo(unsigned long lineNumber)
Definition: read.c:1123
void pushLanguage(const langType language)
Definition: read.c:1154
bool doesInputLanguageAllowNullTag(void)
Definition: read.c:242
bool doesParserRunAsGuest(void)
Definition: read.c:1115
@ BACKSLASH
Definition: read.h:44
@ NEWLINE
Definition: read.h:35
@ CRETURN
Definition: read.h:36
@ BOUNDARY_START
Definition: read_p.h:26
bool doesFileExist(const char *const fileName)
Definition: routines.c:495
char * CurrentDirectory
Definition: routines.c:152
void eFreeNoNullCheck(void *const ptr)
Definition: routines.c:258
char * absoluteDirname(char *file)
Definition: routines.c:833
char * strstr(const char *str, const char *substr)
Definition: routines.c:304
void * eRealloc(void *const ptr, const size_t size)
Definition: routines.c:238
char * eStrdup(const char *str)
Definition: routines.c:327
void eFree(void *const ptr)
Definition: routines.c:252
MIO * tempFile(const char *const mode, char **const pName)
Definition: routines.c:896
const char * baseFilename(const char *const filePath)
Definition: routines.c:608
#define xMalloc(n, Type)
Definition: routines.h:23
@ PERROR
Definition: routines.h:37
@ FATAL
Definition: routines.h:37
@ WARNING
Definition: routines.h:37
#define xCalloc(n, Type)
Definition: routines.h:24
#define PATH_SEPARATOR
Definition: routines_p.h:26
#define OUTPUT_PATH_SEPARATOR
Definition: routines_p.h:33
GtkWidget * entry
Definition: search.c:118
GtkWidget * close
Definition: sidebar.c:56
void catFile(MIO *mio)
Definition: sort.c:36
void failedSort(MIO *const mio, const char *msg)
Definition: sort.c:166
void internalSortTags(const bool toStdout, MIO *mio, size_t numTags)
Definition: sort.c:227
const gchar filename[]
Definition: stash-example.c:4
if(!stash_group_load_from_file(group, filename)) g_warning(_("Could not load keyfile %s!")
stringList * stringListNew(void)
Definition: strlist.c:27
void stringListDelete(stringList *const current)
Definition: strlist.c:102
void stringListRemoveLast(stringList *const current)
Definition: strlist.c:37
vString * stringListItem(const stringList *const current, const unsigned int indx)
Definition: strlist.c:86
vString * stringListLast(const stringList *const current)
Definition: strlist.c:92
unsigned int stringListCount(const stringList *const current)
Definition: strlist.c:81
void stringListAdd(stringList *const current, vString *string)
Definition: strlist.c:32
int corkIndex
Definition: nestlevel.h:28
MIOPos:
Definition: mio.h:101
MIO:
Definition: mio.c:136
const int * kinds
Definition: entry.c:1346
size_t tag
Definition: entry.c:92
size_t line
Definition: entry.c:92
unsigned long added
Definition: entry.c:91
unsigned long prev
Definition: entry.c:91
Definition: entry.c:87
char * directory
Definition: entry.c:89
struct eTagFile::sMax max
char * name
Definition: entry.c:88
unsigned int corkFlags
Definition: entry.c:96
struct eTagFile::sNumTags numTags
vString * vLine
Definition: entry.c:93
MIO * mio
Definition: entry.c:90
bool patternCacheValid
Definition: entry.c:99
ptrArray * corkQueue
Definition: entry.c:97
int cork
Definition: entry.c:95
struct rb_node * rb_left
Definition: rbtree.h:159
struct rb_node * rb_right
Definition: rbtree.h:158
struct rb_node * rb_node
Definition: rbtree.h:165
char * name
Definition: kind.h:74
sortType sorted
Definition: options_p.h:95
bool backward
Definition: options_p.h:91
unsigned int patternLengthLimit
Definition: options_p.h:118
stringList * etagsInclude
Definition: options_p.h:101
enum sOptionValues::interactiveMode interactive
exCmd locate
Definition: options_p.h:93
char * tagFileName
Definition: options_p.h:99
const char * name
Definition: ptag_p.h:58
struct rb_node symnode
Definition: entry.c:106
struct rb_root symtab
Definition: entry.c:105
tagEntryInfo slot
Definition: entry.c:103
int corkIndex
Definition: entry.c:104
struct sTagEntryInfo::@3 extensionFields
roleBitsType roleBits
Definition: entry.h:93
const char * implementation
Definition: entry.h:71
MIOPos filePosition
Definition: entry.h:60
const char * fileScope
Definition: entry.h:70
unsigned int lineNumberEntry
Definition: entry.h:44
unsigned int boundaryInfo
Definition: entry.h:59
const char * name
Definition: entry.h:63
langType sourceLangType
Definition: entry.h:114
const char * inputFileName
Definition: entry.h:62
const char * access
Definition: entry.h:69
uint8_t * extraDynamic
Definition: entry.h:66
unsigned long lineNumber
Definition: entry.h:56
ptrArray * parserFieldsDynamic
Definition: entry.h:110
tagField parserFields[5]
Definition: entry.h:109
unsigned int skipAutoFQEmission
Definition: entry.h:51
int kindIndex
Definition: entry.h:64
langType langType
Definition: entry.h:61
unsigned long sourceLineNumberDifference
Definition: entry.h:116
unsigned int truncateLineAfterTag
Definition: entry.h:47
unsigned int usedParserFields
Definition: entry.h:106
langType scopeLangType
Definition: entry.h:77
const char * typeRef[2]
Definition: entry.h:88
const char * pattern
Definition: entry.h:57
unsigned long endLine
Definition: entry.h:98
uint8_t extra[((XTAG_COUNT)/8)+1]
Definition: entry.h:65
const char * sourceFileName
Definition: entry.h:115
int scopeIndex
Definition: entry.h:80
int scopeKindIndex
Definition: entry.h:78
unsigned int placeholder
Definition: entry.h:48
const char * inheritance
Definition: entry.h:72
const char * signature
Definition: entry.h:85
unsigned int isFileEntry
Definition: entry.h:46
const char * scopeName
Definition: entry.h:79
const char * value
Definition: entry.h:35
bool valueOwner
Definition: entry.h:36
fieldType ftype
Definition: entry.h:34
#define PARSER_TRASH_BOX_TAKE_BACK(PTR)
Definition: trashbox.h:38
#define PARSER_TRASH_BOX(PTR, PROC)
Definition: trashbox.h:37
int langType
Definition: types.h:13
vString * vStringNew(void)
Definition: vstring.c:70
void vStringDelete(vString *const string)
Definition: vstring.c:60
vString * vStringNewOrClearWithAutoRelease(vString *const string)
Definition: vstring.c:379
void vStringCatS(vString *const string, const char *const s)
Definition: vstring.c:146
vString * vStringNewInit(const char *const s)
Definition: vstring.c:90
char * vStringDeleteUnwrap(vString *const string)
Definition: vstring.c:267
void vStringCat(vString *const string, const vString *const s)
Definition: vstring.c:139
#define vStringLength(vs)
Definition: vstring.h:31
#define vStringValue(vs)
Definition: vstring.h:28
static void vStringPut(vString *const string, const int c)
Definition: vstring.h:101
int writerWritePtag(MIO *mio, const ptagDesc *desc, const char *const fileName, const char *const pattern, const char *const parserName)
Definition: writer.c:73
void writerSetup(MIO *mio, void *clientData)
Definition: writer.c:43
bool writerTeardown(MIO *mio, const char *filename)
Definition: writer.c:54
int writerWriteTag(MIO *mio, const tagEntryInfo *const tag)
Definition: writer.c:67
int countXtags(void)
Definition: xtag.c:327
bool isXtagEnabled(xtagType type)
Definition: xtag.c:235
@ XTAG_UNKNOWN
Definition: xtag.h:26
@ XTAG_SUBPARSER
Definition: xtag.h:35
@ XTAG_ANONYMOUS
Definition: xtag.h:36
@ XTAG_PSEUDO_TAGS
Definition: xtag.h:30
@ XTAG_GUEST
Definition: xtag.h:33
@ XTAG_QUALIFIED_TAGS
Definition: xtag.h:31
@ XTAG_REFERENCE_TAGS
Definition: xtag.h:32
@ XTAG_FILE_NAMES
Definition: xtag.h:29
@ XTAG_COUNT
Definition: xtag.h:38
enum eXtagType xtagType