1ce1ebc98SFrank Fesevur /*
2ce1ebc98SFrank Fesevur *
3ce1ebc98SFrank Fesevur * Copyright (c) 2007-2011, Nick Treleaven
4ce1ebc98SFrank Fesevur *
5ce1ebc98SFrank Fesevur * This source code is released for free distribution under the terms of the
60ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
7ce1ebc98SFrank Fesevur *
8ce1ebc98SFrank Fesevur * This module contains functions for generating tags for reStructuredText (reST) files.
962c89b2cSMasatake YAMATO *
1062c89b2cSMasatake YAMATO * This module was ported from geany.
11dce67d9fSMasatake YAMATO *
12dce67d9fSMasatake YAMATO * References:
13dce67d9fSMasatake YAMATO * https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html
14ce1ebc98SFrank Fesevur */
15ce1ebc98SFrank Fesevur
16ce1ebc98SFrank Fesevur /*
17ce1ebc98SFrank Fesevur * INCLUDE FILES
18ce1ebc98SFrank Fesevur */
19ce1ebc98SFrank Fesevur #include "general.h" /* must always come first */
20ce1ebc98SFrank Fesevur
21ce1ebc98SFrank Fesevur #include <ctype.h>
22ce1ebc98SFrank Fesevur #include <string.h>
23ce1ebc98SFrank Fesevur
24ce1ebc98SFrank Fesevur #include "parse.h"
25ce1ebc98SFrank Fesevur #include "read.h"
26ce1ebc98SFrank Fesevur #include "vstring.h"
27ce1ebc98SFrank Fesevur #include "nestlevel.h"
28ce1ebc98SFrank Fesevur #include "entry.h"
293db72c21SMasatake YAMATO #include "routines.h"
30ca4186ffSMasatake YAMATO #include "field.h"
31*507b32e9SMasatake YAMATO #include "htable.h"
32*507b32e9SMasatake YAMATO #include "debug.h"
33ce1ebc98SFrank Fesevur
34ce1ebc98SFrank Fesevur /*
35ce1ebc98SFrank Fesevur * DATA DEFINITIONS
36ce1ebc98SFrank Fesevur */
37ce1ebc98SFrank Fesevur typedef enum {
38abd50e08SMasatake YAMATO K_EOF = -1,
39*507b32e9SMasatake YAMATO K_TITLE = 0,
40*507b32e9SMasatake YAMATO K_SUBTITLE,
41*507b32e9SMasatake YAMATO K_CHAPTER,
42ce1ebc98SFrank Fesevur K_SECTION,
43ce1ebc98SFrank Fesevur K_SUBSECTION,
44ce1ebc98SFrank Fesevur K_SUBSUBSECTION,
4535f5544dSMasatake YAMATO SECTION_COUNT,
4635f5544dSMasatake YAMATO K_CITATION = SECTION_COUNT,
478ad104f0SMasatake YAMATO K_TARGET,
48d36d8436SMasatake YAMATO K_SUBSTDEF,
49ce1ebc98SFrank Fesevur } rstKind;
50ce1ebc98SFrank Fesevur
51e112e8abSMasatake YAMATO static kindDefinition RstKinds[] = {
52*507b32e9SMasatake YAMATO { true, 'H', "title", "titles"},
53*507b32e9SMasatake YAMATO { true, 'h', "subtitle", "sub titles" },
54ce990805SThomas Braun { true, 'c', "chapter", "chapters"},
55ce990805SThomas Braun { true, 's', "section", "sections" },
56ce990805SThomas Braun { true, 'S', "subsection", "subsections" },
578ad104f0SMasatake YAMATO { true, 't', "subsubsection", "subsubsections" },
589987a60dSMasatake YAMATO { true, 'C', "citation", "citations"},
598ad104f0SMasatake YAMATO { true, 'T', "target", "targets" },
60d36d8436SMasatake YAMATO { true, 'd', "substdef", "substitute definitions" },
61ce1ebc98SFrank Fesevur };
62ce1ebc98SFrank Fesevur
63ca4186ffSMasatake YAMATO typedef enum {
64ca4186ffSMasatake YAMATO F_SECTION_MARKER,
657d49215aSMasatake YAMATO F_SECTION_OVERLINE,
66ca4186ffSMasatake YAMATO } rstField;
67ca4186ffSMasatake YAMATO
68b56bd065SMasatake YAMATO static fieldDefinition RstFields [] = {
69ca4186ffSMasatake YAMATO {
70ca4186ffSMasatake YAMATO .name = "sectionMarker",
71ca4186ffSMasatake YAMATO .description = "character used for declaring section",
72ce990805SThomas Braun .enabled = false,
73abd50e08SMasatake YAMATO },
747d49215aSMasatake YAMATO {
757d49215aSMasatake YAMATO .name = "overline",
767d49215aSMasatake YAMATO .description = "whether using overline & underline for declaring section",
777d49215aSMasatake YAMATO .enabled = false,
787d49215aSMasatake YAMATO .dataType = FIELDTYPE_BOOL
797d49215aSMasatake YAMATO },
80ca4186ffSMasatake YAMATO };
81ca4186ffSMasatake YAMATO
82ce1ebc98SFrank Fesevur static NestingLevels *nestingLevels = NULL;
83ce1ebc98SFrank Fesevur
8483ca0998SMasatake YAMATO struct sectionTracker {
8583ca0998SMasatake YAMATO char kindchar;
86323f14dcSMasatake YAMATO bool overline;
87*507b32e9SMasatake YAMATO int count;
88323f14dcSMasatake YAMATO };
89323f14dcSMasatake YAMATO
90323f14dcSMasatake YAMATO struct olineTracker
91323f14dcSMasatake YAMATO {
92323f14dcSMasatake YAMATO char c;
93323f14dcSMasatake YAMATO size_t len;
9483ca0998SMasatake YAMATO };
9583ca0998SMasatake YAMATO
96ce1ebc98SFrank Fesevur /*
97ce1ebc98SFrank Fesevur * FUNCTION DEFINITIONS
98ce1ebc98SFrank Fesevur */
99ce1ebc98SFrank Fesevur
getNestingLevel(const int kind)100ce1ebc98SFrank Fesevur static NestingLevel *getNestingLevel(const int kind)
101ce1ebc98SFrank Fesevur {
102ce1ebc98SFrank Fesevur NestingLevel *nl;
103885fbc2cSMasatake YAMATO tagEntryInfo *e;
104ce1ebc98SFrank Fesevur
105abd50e08SMasatake YAMATO int d = 0;
106abd50e08SMasatake YAMATO
107abd50e08SMasatake YAMATO if (kind > K_EOF)
108abd50e08SMasatake YAMATO {
109abd50e08SMasatake YAMATO d++;
110abd50e08SMasatake YAMATO /* 1. we want the line before the '---' underline chars */
111abd50e08SMasatake YAMATO d++;
112abd50e08SMasatake YAMATO /* 2. we want the line before the next section/chapter title. */
113abd50e08SMasatake YAMATO }
114abd50e08SMasatake YAMATO
115ce1ebc98SFrank Fesevur while (1)
116ce1ebc98SFrank Fesevur {
117ce1ebc98SFrank Fesevur nl = nestingLevelsGetCurrent(nestingLevels);
118885fbc2cSMasatake YAMATO e = getEntryOfNestingLevel (nl);
119f92e6bf2SMasatake YAMATO if ((nl && (e == NULL)) || (e && e->kindIndex >= kind))
120abd50e08SMasatake YAMATO {
121abd50e08SMasatake YAMATO if (e)
122d82a3cd2SMasatake YAMATO e->extensionFields.endLine = (getInputLineNumber() - d);
123ce1ebc98SFrank Fesevur nestingLevelsPop(nestingLevels);
124abd50e08SMasatake YAMATO }
125ce1ebc98SFrank Fesevur else
126ce1ebc98SFrank Fesevur break;
127ce1ebc98SFrank Fesevur }
128ce1ebc98SFrank Fesevur return nl;
129ce1ebc98SFrank Fesevur }
130ce1ebc98SFrank Fesevur
makeTargetRstTag(const vString * const name,rstKind kindex)1319987a60dSMasatake YAMATO static int makeTargetRstTag(const vString* const name, rstKind kindex)
1328ad104f0SMasatake YAMATO {
1338ad104f0SMasatake YAMATO tagEntryInfo e;
1348ad104f0SMasatake YAMATO
1359987a60dSMasatake YAMATO initTagEntry (&e, vStringValue (name), kindex);
1368ad104f0SMasatake YAMATO
1378ad104f0SMasatake YAMATO const NestingLevel *nl = nestingLevelsGetCurrent(nestingLevels);
1388ad104f0SMasatake YAMATO if (nl)
1395825596bSMasatake YAMATO e.extensionFields.scopeIndex = nl->corkIndex;
1408ad104f0SMasatake YAMATO
1418ad104f0SMasatake YAMATO return makeTagEntry (&e);
1428ad104f0SMasatake YAMATO }
1438ad104f0SMasatake YAMATO
makeSectionRstTag(const vString * const name,const int kind,const MIOPos filepos,char marker,bool overline)1448ad104f0SMasatake YAMATO static void makeSectionRstTag(const vString* const name, const int kind, const MIOPos filepos,
1457d49215aSMasatake YAMATO char marker, bool overline)
146ce1ebc98SFrank Fesevur {
147ce1ebc98SFrank Fesevur const NestingLevel *const nl = getNestingLevel(kind);
148885fbc2cSMasatake YAMATO tagEntryInfo *parent;
149885fbc2cSMasatake YAMATO
150885fbc2cSMasatake YAMATO int r = CORK_NIL;
151ce1ebc98SFrank Fesevur
152ce1ebc98SFrank Fesevur if (vStringLength (name) > 0)
153ce1ebc98SFrank Fesevur {
154ce1ebc98SFrank Fesevur tagEntryInfo e;
155ca4186ffSMasatake YAMATO char m [2] = { [1] = '\0' };
156ca4186ffSMasatake YAMATO
15716a2541cSMasatake YAMATO initTagEntry (&e, vStringValue (name), kind);
158ce1ebc98SFrank Fesevur
159ce1ebc98SFrank Fesevur e.lineNumber--; /* we want the line before the '---' underline chars */
160ce1ebc98SFrank Fesevur e.filePosition = filepos;
161ce1ebc98SFrank Fesevur
162885fbc2cSMasatake YAMATO parent = getEntryOfNestingLevel (nl);
163f92e6bf2SMasatake YAMATO if (parent && (parent->kindIndex < kind))
164885fbc2cSMasatake YAMATO e.extensionFields.scopeIndex = nl->corkIndex;
165ca4186ffSMasatake YAMATO
166ca4186ffSMasatake YAMATO m[0] = marker;
167aa4def17SMasatake YAMATO attachParserField (&e, false, RstFields [F_SECTION_MARKER].ftype, m);
1687d49215aSMasatake YAMATO
1697d49215aSMasatake YAMATO if (overline)
1707d49215aSMasatake YAMATO attachParserField (&e, false, RstFields [F_SECTION_OVERLINE].ftype, "");
1717d49215aSMasatake YAMATO
172885fbc2cSMasatake YAMATO r = makeTagEntry (&e);
173ce1ebc98SFrank Fesevur }
174885fbc2cSMasatake YAMATO nestingLevelsPush(nestingLevels, r);
175ce1ebc98SFrank Fesevur }
176ce1ebc98SFrank Fesevur
177ce1ebc98SFrank Fesevur
178ce1ebc98SFrank Fesevur /* checks if str is all the same character */
issame(const char * str)179ce990805SThomas Braun static bool issame(const char *str)
180ce1ebc98SFrank Fesevur {
181ce1ebc98SFrank Fesevur char first = *str;
182ce1ebc98SFrank Fesevur
183ce1ebc98SFrank Fesevur while (*str)
184ce1ebc98SFrank Fesevur {
185ce1ebc98SFrank Fesevur char c;
186ce1ebc98SFrank Fesevur
187ce1ebc98SFrank Fesevur str++;
188ce1ebc98SFrank Fesevur c = *str;
189ce1ebc98SFrank Fesevur if (c && c != first)
190ce990805SThomas Braun return false;
191ce1ebc98SFrank Fesevur }
192ce990805SThomas Braun return true;
193ce1ebc98SFrank Fesevur }
194ce1ebc98SFrank Fesevur
195ce1ebc98SFrank Fesevur
get_kind(char c,bool overline,struct sectionTracker tracker[])196323f14dcSMasatake YAMATO static int get_kind(char c, bool overline, struct sectionTracker tracker[])
197ce1ebc98SFrank Fesevur {
198ce1ebc98SFrank Fesevur int i;
199ce1ebc98SFrank Fesevur
200ce1ebc98SFrank Fesevur for (i = 0; i < SECTION_COUNT; i++)
201ce1ebc98SFrank Fesevur {
202323f14dcSMasatake YAMATO if (tracker[i].kindchar == c && tracker[i].overline == overline)
203ce1ebc98SFrank Fesevur {
204*507b32e9SMasatake YAMATO tracker[i].count++;
205*507b32e9SMasatake YAMATO return i;
206*507b32e9SMasatake YAMATO }
207*507b32e9SMasatake YAMATO
208*507b32e9SMasatake YAMATO if (tracker[i].count == 0)
209*507b32e9SMasatake YAMATO {
210*507b32e9SMasatake YAMATO tracker[i].count = 1;
21183ca0998SMasatake YAMATO tracker[i].kindchar = c;
212323f14dcSMasatake YAMATO tracker[i].overline = overline;
213ce1ebc98SFrank Fesevur return i;
214ce1ebc98SFrank Fesevur }
215ce1ebc98SFrank Fesevur }
216ce1ebc98SFrank Fesevur return -1;
217ce1ebc98SFrank Fesevur }
218ce1ebc98SFrank Fesevur
219ce1ebc98SFrank Fesevur
220ce1ebc98SFrank Fesevur /* computes the length of an UTF-8 string
221ce1ebc98SFrank Fesevur * if the string doesn't look like UTF-8, return -1 */
utf8_strlen(const char * buf,int buf_len)222ce1ebc98SFrank Fesevur static int utf8_strlen(const char *buf, int buf_len)
223ce1ebc98SFrank Fesevur {
224ce1ebc98SFrank Fesevur int len = 0;
225ce1ebc98SFrank Fesevur const char *end = buf + buf_len;
226ce1ebc98SFrank Fesevur
227ce1ebc98SFrank Fesevur for (len = 0; buf < end; len ++)
228ce1ebc98SFrank Fesevur {
229ce1ebc98SFrank Fesevur /* perform quick and naive validation (no sub-byte checking) */
230ce1ebc98SFrank Fesevur if (! (*buf & 0x80))
231ce1ebc98SFrank Fesevur buf ++;
232ce1ebc98SFrank Fesevur else if ((*buf & 0xe0) == 0xc0)
233ce1ebc98SFrank Fesevur buf += 2;
234ce1ebc98SFrank Fesevur else if ((*buf & 0xf0) == 0xe0)
235ce1ebc98SFrank Fesevur buf += 3;
236ce1ebc98SFrank Fesevur else if ((*buf & 0xf8) == 0xf0)
237ce1ebc98SFrank Fesevur buf += 4;
238ce1ebc98SFrank Fesevur else /* not a valid leading UTF-8 byte, abort */
239ce1ebc98SFrank Fesevur return -1;
240ce1ebc98SFrank Fesevur
241ce1ebc98SFrank Fesevur if (buf > end) /* incomplete last byte */
242ce1ebc98SFrank Fesevur return -1;
243ce1ebc98SFrank Fesevur }
244ce1ebc98SFrank Fesevur
245ce1ebc98SFrank Fesevur return len;
246ce1ebc98SFrank Fesevur }
247ce1ebc98SFrank Fesevur
248ce1ebc98SFrank Fesevur
is_markup_line(const unsigned char * line,char reftype)2499987a60dSMasatake YAMATO static const unsigned char *is_markup_line (const unsigned char *line, char reftype)
2508ad104f0SMasatake YAMATO {
2518ad104f0SMasatake YAMATO if ((line [0] == '.') && (line [1] == '.') && (line [2] == ' ')
2529987a60dSMasatake YAMATO && (line [3] == reftype))
2538ad104f0SMasatake YAMATO return line + 4;
2548ad104f0SMasatake YAMATO return NULL;
2558ad104f0SMasatake YAMATO }
2568ad104f0SMasatake YAMATO
capture_markup(const unsigned char * target_line,char defaultTerminator,rstKind kindex)2579987a60dSMasatake YAMATO static int capture_markup (const unsigned char *target_line, char defaultTerminator, rstKind kindex)
2588ad104f0SMasatake YAMATO {
2598ad104f0SMasatake YAMATO vString *name = vStringNew ();
2608ad104f0SMasatake YAMATO unsigned char terminator;
2618ad104f0SMasatake YAMATO int r = CORK_NIL;
2628ad104f0SMasatake YAMATO
2638ad104f0SMasatake YAMATO if (*target_line == '`')
2648ad104f0SMasatake YAMATO terminator = '`';
2658ad104f0SMasatake YAMATO else if (!isspace (*target_line) && *target_line != '\0')
2668ad104f0SMasatake YAMATO {
2678ad104f0SMasatake YAMATO /* "Simple reference names are single words consisting of
2688ad104f0SMasatake YAMATO * alphanumerics plus isolated (no two adjacent) internal
2698ad104f0SMasatake YAMATO * hyphens, underscores, periods, colons and plus signs; no
2708ad104f0SMasatake YAMATO * whitespace or other characters are allowed."
2718ad104f0SMasatake YAMATO * -- http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#reference-names
2728ad104f0SMasatake YAMATO */
2738ad104f0SMasatake YAMATO vStringPut (name, *target_line);
2749987a60dSMasatake YAMATO terminator = defaultTerminator;
2758ad104f0SMasatake YAMATO }
2768ad104f0SMasatake YAMATO else
2778ad104f0SMasatake YAMATO goto out;
2788ad104f0SMasatake YAMATO
2798ad104f0SMasatake YAMATO target_line++;
2808ad104f0SMasatake YAMATO
2818ad104f0SMasatake YAMATO
2828ad104f0SMasatake YAMATO bool escaped = false;
2838ad104f0SMasatake YAMATO while (*target_line != '\0')
2848ad104f0SMasatake YAMATO {
2858ad104f0SMasatake YAMATO if (escaped)
2868ad104f0SMasatake YAMATO {
2878ad104f0SMasatake YAMATO vStringPut (name, *target_line);
2888ad104f0SMasatake YAMATO escaped = false;
2898ad104f0SMasatake YAMATO }
2908ad104f0SMasatake YAMATO else
2918ad104f0SMasatake YAMATO {
2928ad104f0SMasatake YAMATO if (*target_line == '\\')
2938ad104f0SMasatake YAMATO {
2948ad104f0SMasatake YAMATO vStringPut (name, *target_line);
2958ad104f0SMasatake YAMATO escaped = true;
2968ad104f0SMasatake YAMATO }
2978ad104f0SMasatake YAMATO else if (*target_line == terminator)
2988ad104f0SMasatake YAMATO break;
2998ad104f0SMasatake YAMATO else
3008ad104f0SMasatake YAMATO vStringPut (name, *target_line);
3018ad104f0SMasatake YAMATO }
3028ad104f0SMasatake YAMATO target_line++;
3038ad104f0SMasatake YAMATO }
3048ad104f0SMasatake YAMATO
3058ad104f0SMasatake YAMATO if (vStringLength (name) == 0)
3068ad104f0SMasatake YAMATO goto out;
3078ad104f0SMasatake YAMATO
3089987a60dSMasatake YAMATO r = makeTargetRstTag (name, kindex);
3098ad104f0SMasatake YAMATO
3108ad104f0SMasatake YAMATO out:
3118ad104f0SMasatake YAMATO vStringDelete (name);
3128ad104f0SMasatake YAMATO return r;
3138ad104f0SMasatake YAMATO }
3148ad104f0SMasatake YAMATO
overline_clear(struct olineTracker * ol)315323f14dcSMasatake YAMATO static void overline_clear(struct olineTracker *ol)
316323f14dcSMasatake YAMATO {
317323f14dcSMasatake YAMATO ol->c = 0;
318323f14dcSMasatake YAMATO ol->len = 0;
319323f14dcSMasatake YAMATO }
320323f14dcSMasatake YAMATO
overline_set(struct olineTracker * ol,char c,size_t len)321323f14dcSMasatake YAMATO static void overline_set(struct olineTracker *ol, char c, size_t len)
322323f14dcSMasatake YAMATO {
323323f14dcSMasatake YAMATO ol->c = c;
324323f14dcSMasatake YAMATO ol->len = len;
325323f14dcSMasatake YAMATO }
326323f14dcSMasatake YAMATO
has_overline(struct olineTracker * ol)327323f14dcSMasatake YAMATO static bool has_overline(struct olineTracker *ol)
328323f14dcSMasatake YAMATO {
329323f14dcSMasatake YAMATO return (ol->c != 0);
330323f14dcSMasatake YAMATO }
331323f14dcSMasatake YAMATO
getFosterEntry(tagEntryInfo * e,int shift)332*507b32e9SMasatake YAMATO static int getFosterEntry(tagEntryInfo *e, int shift)
333*507b32e9SMasatake YAMATO {
334*507b32e9SMasatake YAMATO int r = CORK_NIL;
335*507b32e9SMasatake YAMATO
336*507b32e9SMasatake YAMATO while (shift-- > 0)
337*507b32e9SMasatake YAMATO {
338*507b32e9SMasatake YAMATO r = e->extensionFields.scopeIndex;
339*507b32e9SMasatake YAMATO Assert(r != CORK_NIL);
340*507b32e9SMasatake YAMATO e = getEntryInCorkQueue(r);
341*507b32e9SMasatake YAMATO Assert(e);
342*507b32e9SMasatake YAMATO }
343*507b32e9SMasatake YAMATO return r;
344*507b32e9SMasatake YAMATO }
345*507b32e9SMasatake YAMATO
shiftKinds(int shift,rstKind baseKind)346*507b32e9SMasatake YAMATO static void shiftKinds(int shift, rstKind baseKind)
347*507b32e9SMasatake YAMATO {
348*507b32e9SMasatake YAMATO size_t count = countEntryInCorkQueue();
349*507b32e9SMasatake YAMATO hashTable *remapping_table = hashTableNew (count,
350*507b32e9SMasatake YAMATO hashPtrhash,
351*507b32e9SMasatake YAMATO hashPtreq, NULL, NULL);
352*507b32e9SMasatake YAMATO hashTableSetValueForUnknownKey(remapping_table, HT_INT_TO_PTR(CORK_NIL), NULL);
353*507b32e9SMasatake YAMATO
354*507b32e9SMasatake YAMATO for (int index = 0; index < count; index++)
355*507b32e9SMasatake YAMATO {
356*507b32e9SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue(index);
357*507b32e9SMasatake YAMATO if (e && (baseKind <= e->kindIndex && e->kindIndex < SECTION_COUNT))
358*507b32e9SMasatake YAMATO {
359*507b32e9SMasatake YAMATO e->kindIndex += shift;
360*507b32e9SMasatake YAMATO if (e->kindIndex >= SECTION_COUNT)
361*507b32e9SMasatake YAMATO {
362*507b32e9SMasatake YAMATO markTagPlaceholder(e, true);
363*507b32e9SMasatake YAMATO
364*507b32e9SMasatake YAMATO int foster_parent = getFosterEntry(e, shift);
365*507b32e9SMasatake YAMATO Assert (foster_parent != CORK_NIL);
366*507b32e9SMasatake YAMATO hashTablePutItem(remapping_table, HT_INT_TO_PTR(index),
367*507b32e9SMasatake YAMATO HT_INT_TO_PTR(foster_parent));
368*507b32e9SMasatake YAMATO }
369*507b32e9SMasatake YAMATO }
370*507b32e9SMasatake YAMATO }
371*507b32e9SMasatake YAMATO
372*507b32e9SMasatake YAMATO for (int index = 0; index < count; index++)
373*507b32e9SMasatake YAMATO {
374*507b32e9SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue(index);
375*507b32e9SMasatake YAMATO if (e && e->extensionFields.scopeIndex != CORK_NIL)
376*507b32e9SMasatake YAMATO {
377*507b32e9SMasatake YAMATO void *remapping_to = hashTableGetItem (remapping_table,
378*507b32e9SMasatake YAMATO HT_INT_TO_PTR(e->extensionFields.scopeIndex));
379*507b32e9SMasatake YAMATO if (HT_PTR_TO_INT(remapping_to) != CORK_NIL)
380*507b32e9SMasatake YAMATO e->extensionFields.scopeIndex = HT_PTR_TO_INT(remapping_to);
381*507b32e9SMasatake YAMATO }
382*507b32e9SMasatake YAMATO }
383*507b32e9SMasatake YAMATO hashTableDelete(remapping_table);
384*507b32e9SMasatake YAMATO }
385*507b32e9SMasatake YAMATO
adjustSectionKinds(struct sectionTracker section_tracker[])386*507b32e9SMasatake YAMATO static void adjustSectionKinds(struct sectionTracker section_tracker[])
387*507b32e9SMasatake YAMATO {
388*507b32e9SMasatake YAMATO if (section_tracker[K_TITLE].count > 1)
389*507b32e9SMasatake YAMATO {
390*507b32e9SMasatake YAMATO shiftKinds(2, K_TITLE);
391*507b32e9SMasatake YAMATO return;
392*507b32e9SMasatake YAMATO }
393*507b32e9SMasatake YAMATO
394*507b32e9SMasatake YAMATO if (section_tracker[K_TITLE].count == 1
395*507b32e9SMasatake YAMATO && section_tracker[K_SUBTITLE].count > 1)
396*507b32e9SMasatake YAMATO {
397*507b32e9SMasatake YAMATO shiftKinds(1, K_SUBTITLE);
398*507b32e9SMasatake YAMATO return;
399*507b32e9SMasatake YAMATO }
400*507b32e9SMasatake YAMATO }
401*507b32e9SMasatake YAMATO
inlineTagScope(tagEntryInfo * e,int parent_index)4025825596bSMasatake YAMATO static void inlineTagScope(tagEntryInfo *e, int parent_index)
4035825596bSMasatake YAMATO {
4045825596bSMasatake YAMATO tagEntryInfo *parent = getEntryInCorkQueue (parent_index);
4055825596bSMasatake YAMATO if (parent)
4065825596bSMasatake YAMATO {
4075825596bSMasatake YAMATO e->extensionFields.scopeKindIndex = parent->kindIndex;
4085825596bSMasatake YAMATO e->extensionFields.scopeName = eStrdup(parent->name);
4095825596bSMasatake YAMATO e->extensionFields.scopeIndex = CORK_NIL;
4105825596bSMasatake YAMATO }
4115825596bSMasatake YAMATO }
4125825596bSMasatake YAMATO
inlineScopes(void)4135825596bSMasatake YAMATO static void inlineScopes (void)
4145825596bSMasatake YAMATO {
4155825596bSMasatake YAMATO /* TODO
4165825596bSMasatake YAMATO Following code makes the scope information full qualified form.
4175825596bSMasatake YAMATO Do users want the full qualified form?
4185825596bSMasatake YAMATO --- ./Units/rst.simple.d/expected.tags 2015-12-18 01:32:35.574255617 +0900
4195825596bSMasatake YAMATO +++ /home/yamato/var/ctags-github/Units/rst.simple.d/FILTERED.tmp 2016-05-05 03:05:38.165604756 +0900
4205825596bSMasatake YAMATO @@ -5,2 +5,2 @@
4215825596bSMasatake YAMATO -Subsection 1.1.1 input.rst /^Subsection 1.1.1$/;" S section:Section 1.1
4225825596bSMasatake YAMATO -Subsubsection 1.1.1.1 input.rst /^Subsubsection 1.1.1.1$/;" t subsection:Subsection 1.1.1
4235825596bSMasatake YAMATO +Subsection 1.1.1 input.rst /^Subsection 1.1.1$/;" S section:Chapter 1.Section 1.1
4245825596bSMasatake YAMATO +Subsubsection 1.1.1.1 input.rst /^Subsubsection 1.1.1.1$/;" t subsection:Chapter 1.Section 1.1.Subsection 1.1.1
4255825596bSMasatake YAMATO */
4265825596bSMasatake YAMATO size_t count = countEntryInCorkQueue();
4275825596bSMasatake YAMATO for (int index = 0; index < count; index++)
4285825596bSMasatake YAMATO {
4295825596bSMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue(index);
4305825596bSMasatake YAMATO
4315825596bSMasatake YAMATO if (e && e->extensionFields.scopeIndex != CORK_NIL)
4325825596bSMasatake YAMATO inlineTagScope(e, e->extensionFields.scopeIndex);
4335825596bSMasatake YAMATO }
4345825596bSMasatake YAMATO }
4355825596bSMasatake YAMATO
findRstTags(void)436ce1ebc98SFrank Fesevur static void findRstTags (void)
437ce1ebc98SFrank Fesevur {
438ce1ebc98SFrank Fesevur vString *name = vStringNew ();
439509a47dbSJiří Techet MIOPos filepos;
440ce1ebc98SFrank Fesevur const unsigned char *line;
4419987a60dSMasatake YAMATO const unsigned char *markup_line;
44283ca0998SMasatake YAMATO struct sectionTracker section_tracker[SECTION_COUNT];
443323f14dcSMasatake YAMATO struct olineTracker overline;
444ce1ebc98SFrank Fesevur
445aee63e9eSMasatake YAMATO memset(&filepos, 0, sizeof(filepos));
44683ca0998SMasatake YAMATO memset(section_tracker, 0, sizeof section_tracker);
447323f14dcSMasatake YAMATO overline_clear(&overline);
448090afdd9SMasatake YAMATO nestingLevels = nestingLevelsNew(0);
449ce1ebc98SFrank Fesevur
4501b312fe7SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
451ce1ebc98SFrank Fesevur {
4529987a60dSMasatake YAMATO if ((markup_line = is_markup_line (line, '_')) != NULL)
4539987a60dSMasatake YAMATO {
454323f14dcSMasatake YAMATO overline_clear(&overline);
4558ad104f0SMasatake YAMATO /* Handle .. _target:
4568ad104f0SMasatake YAMATO * http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#hyperlink-targets
4578ad104f0SMasatake YAMATO */
4589987a60dSMasatake YAMATO if (capture_markup (markup_line, ':', K_TARGET) != CORK_NIL)
4598ad104f0SMasatake YAMATO {
4609987a60dSMasatake YAMATO vStringClear (name);
4619987a60dSMasatake YAMATO continue;
4629987a60dSMasatake YAMATO }
4639987a60dSMasatake YAMATO }
4649987a60dSMasatake YAMATO else if ((markup_line = is_markup_line (line, '[')) != NULL)
4659987a60dSMasatake YAMATO {
466323f14dcSMasatake YAMATO overline_clear(&overline);
4679987a60dSMasatake YAMATO /* Handle .. [citation]
4689987a60dSMasatake YAMATO * https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#citations
4699987a60dSMasatake YAMATO */
4709987a60dSMasatake YAMATO if (capture_markup (markup_line, ']', K_CITATION) != CORK_NIL)
4718ad104f0SMasatake YAMATO {
4728ad104f0SMasatake YAMATO vStringClear (name);
4738ad104f0SMasatake YAMATO continue;
4748ad104f0SMasatake YAMATO }
4758ad104f0SMasatake YAMATO }
476d36d8436SMasatake YAMATO else if ((markup_line = is_markup_line (line, '|')) != NULL)
477d36d8436SMasatake YAMATO {
478323f14dcSMasatake YAMATO overline_clear(&overline);
479d36d8436SMasatake YAMATO /* Hanle .. |substitute definition|
480d36d8436SMasatake YAMATO * https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#substitution-definitions
481d36d8436SMasatake YAMATO */
482d36d8436SMasatake YAMATO if (capture_markup (markup_line, '|', K_SUBSTDEF) != CORK_NIL)
483d36d8436SMasatake YAMATO {
484d36d8436SMasatake YAMATO vStringClear (name);
485d36d8436SMasatake YAMATO continue;
486d36d8436SMasatake YAMATO }
487d36d8436SMasatake YAMATO }
4888ad104f0SMasatake YAMATO
489ce1ebc98SFrank Fesevur int line_len = strlen((const char*) line);
490ce1ebc98SFrank Fesevur int name_len_bytes = vStringLength(name);
491d044ffa0SColomban Wendling /* FIXME: this isn't right, actually we need the real display width,
492d044ffa0SColomban Wendling * taking into account double-width characters and stuff like that.
493d044ffa0SColomban Wendling * But duh. */
494ce1ebc98SFrank Fesevur int name_len = utf8_strlen(vStringValue(name), name_len_bytes);
495ce1ebc98SFrank Fesevur
496ce1ebc98SFrank Fesevur /* if the name doesn't look like UTF-8, assume one-byte charset */
497ce1ebc98SFrank Fesevur if (name_len < 0)
498ce1ebc98SFrank Fesevur name_len = name_len_bytes;
499ce1ebc98SFrank Fesevur
500323f14dcSMasatake YAMATO /* overline may come after an empty line (or begging of file). */
501323f14dcSMasatake YAMATO if (name_len_bytes == 0 && line_len > 0 &&
502323f14dcSMasatake YAMATO ispunct(line[0]) && issame((const char*) line))
503323f14dcSMasatake YAMATO {
504323f14dcSMasatake YAMATO overline_set(&overline, *line, line_len);
505323f14dcSMasatake YAMATO continue;
506323f14dcSMasatake YAMATO }
507323f14dcSMasatake YAMATO
508ce1ebc98SFrank Fesevur /* underlines must be the same length or more */
509ce1ebc98SFrank Fesevur if (line_len >= name_len && name_len > 0 &&
510ce1ebc98SFrank Fesevur ispunct(line[0]) && issame((const char*) line))
511ce1ebc98SFrank Fesevur {
512ce1ebc98SFrank Fesevur char c = line[0];
513323f14dcSMasatake YAMATO bool o = (overline.c == c && overline.len == line_len);
514323f14dcSMasatake YAMATO int kind = get_kind(c, o, section_tracker);
515323f14dcSMasatake YAMATO
516323f14dcSMasatake YAMATO overline_clear(&overline);
517ce1ebc98SFrank Fesevur
518ce1ebc98SFrank Fesevur if (kind >= 0)
519ce1ebc98SFrank Fesevur {
5207d49215aSMasatake YAMATO makeSectionRstTag(name, kind, filepos, c, o);
521dca8af12SMasatake YAMATO vStringClear(name);
522ce1ebc98SFrank Fesevur continue;
523ce1ebc98SFrank Fesevur }
524ce1ebc98SFrank Fesevur }
525323f14dcSMasatake YAMATO
526323f14dcSMasatake YAMATO if (has_overline(&overline))
527323f14dcSMasatake YAMATO {
528323f14dcSMasatake YAMATO if (name_len > 0)
529323f14dcSMasatake YAMATO {
530323f14dcSMasatake YAMATO /*
531323f14dcSMasatake YAMATO * Though we saw an overline and a section title text,
532323f14dcSMasatake YAMATO * we cannot find the associated underline.
533323f14dcSMasatake YAMATO * In that case, we must reset the state of tracking
534323f14dcSMasatake YAMATO * overline.
535323f14dcSMasatake YAMATO */
536323f14dcSMasatake YAMATO overline_clear(&overline);
537323f14dcSMasatake YAMATO }
538323f14dcSMasatake YAMATO
539323f14dcSMasatake YAMATO /*
540323f14dcSMasatake YAMATO * We san an overline. The line is the candidate
541323f14dcSMasatake YAMATO * of a section title text. Skip the prefixed whitespaces.
542323f14dcSMasatake YAMATO */
543323f14dcSMasatake YAMATO while (isspace(*line))
544323f14dcSMasatake YAMATO line++;
545323f14dcSMasatake YAMATO }
546323f14dcSMasatake YAMATO
547ce1ebc98SFrank Fesevur vStringClear (name);
548ce1ebc98SFrank Fesevur if (!isspace(*line))
549ce1ebc98SFrank Fesevur {
550ce1ebc98SFrank Fesevur vStringCatS(name, (const char*)line);
551e1aed2adSMasatake YAMATO vStringStripTrailing (name);
552ce1ebc98SFrank Fesevur filepos = getInputFilePosition();
553ce1ebc98SFrank Fesevur }
554ce1ebc98SFrank Fesevur }
555abd50e08SMasatake YAMATO /* Force popping all nesting levels */
556abd50e08SMasatake YAMATO getNestingLevel (K_EOF);
557ce1ebc98SFrank Fesevur vStringDelete (name);
558ce1ebc98SFrank Fesevur nestingLevelsFree(nestingLevels);
5595825596bSMasatake YAMATO
560*507b32e9SMasatake YAMATO adjustSectionKinds(section_tracker);
5615825596bSMasatake YAMATO inlineScopes();
562ce1ebc98SFrank Fesevur }
563ce1ebc98SFrank Fesevur
RstParser(void)564ce1ebc98SFrank Fesevur extern parserDefinition* RstParser (void)
565ce1ebc98SFrank Fesevur {
56683f53f01SFrank Fesevur static const char *const extensions [] = { "rest", "reST", "rst", NULL };
56775295150SMasatake YAMATO parserDefinition* const def = parserNew ("ReStructuredText");
568a7b705c5SMasatake YAMATO static const char *const aliases[] = {
569a7b705c5SMasatake YAMATO "rst", /* The name of emacs's mode */
570a7b705c5SMasatake YAMATO NULL
571a7b705c5SMasatake YAMATO };
572ce1ebc98SFrank Fesevur
57309ae690fSMasatake YAMATO def->kindTable = RstKinds;
5743db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (RstKinds);
575ce1ebc98SFrank Fesevur def->extensions = extensions;
576a7b705c5SMasatake YAMATO def->aliases = aliases;
577ce1ebc98SFrank Fesevur def->parser = findRstTags;
578ca4186ffSMasatake YAMATO
579a739fa5fSMasatake YAMATO def->fieldTable = RstFields;
580a739fa5fSMasatake YAMATO def->fieldCount = ARRAY_SIZE (RstFields);
581ca4186ffSMasatake YAMATO
5826b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
583885fbc2cSMasatake YAMATO
584ce1ebc98SFrank Fesevur return def;
585ce1ebc98SFrank Fesevur }
586