3 * Copyright (c) 2007-2011, Nick Treleaven
5 * This source code is released for free distribution under the terms of the
6 * GNU General Public License.
8 * This module contains functions for generating tags for reStructuredText (reST) files.
14 #include "general.h" /* must always come first */
22 #include "nestlevel.h"
35 static kindOption RestKinds
[] = {
36 { TRUE
, 'n', "namespace", "chapters"},
37 { TRUE
, 'm', "member", "sections" },
38 { TRUE
, 'd', "macro", "subsections" },
39 { TRUE
, 'v', "variable", "subsubsections" }
42 static char kindchars
[SECTION_COUNT
];
44 static NestingLevels
*nestingLevels
= NULL
;
47 * FUNCTION DEFINITIONS
50 static NestingLevel
*getNestingLevel(const int kind
)
56 nl
= nestingLevelsGetCurrent(nestingLevels
);
57 if (nl
&& nl
->type
>= kind
)
58 nestingLevelsPop(nestingLevels
);
65 static void makeRestTag (const vString
* const name
, const int kind
)
67 const NestingLevel
*const nl
= getNestingLevel(kind
);
69 if (vStringLength (name
) > 0)
72 initTagEntry (&e
, vStringValue (name
));
74 e
.lineNumber
--; /* we want the line before the '---' underline chars */
75 e
.kindName
= RestKinds
[kind
].name
;
76 e
.kind
= RestKinds
[kind
].letter
;
78 if (nl
&& nl
->type
< kind
)
80 e
.extensionFields
.scope
[0] = RestKinds
[nl
->type
].name
;
81 e
.extensionFields
.scope
[1] = vStringValue (nl
->name
);
85 nestingLevelsPush(nestingLevels
, name
, kind
);
89 /* checks if str is all the same character */
90 static boolean
issame(const char *str
)
107 static int get_kind(char c
)
111 for (i
= 0; i
< SECTION_COUNT
; i
++)
113 if (kindchars
[i
] == c
)
116 if (kindchars
[i
] == 0)
126 /* computes the length of an UTF-8 string
127 * if the string doesn't look like UTF-8, return -1 */
128 static int utf8_strlen(const char *buf
, int buf_len
)
131 const char *end
= buf
+ buf_len
;
133 for (len
= 0; buf
< end
; len
++)
135 /* perform quick and naive validation (no sub-byte checking) */
138 else if ((*buf
& 0xe0) == 0xc0)
140 else if ((*buf
& 0xf0) == 0xe0)
142 else if ((*buf
& 0xf8) == 0xf0)
144 else /* not a valid leading UTF-8 byte, abort */
147 if (buf
> end
) /* incomplete last byte */
155 /* TODO: parse overlining & underlining as distinct sections. */
156 static void findRestTags (void)
158 vString
*name
= vStringNew ();
159 const unsigned char *line
;
161 memset(kindchars
, 0, sizeof kindchars
);
162 nestingLevels
= nestingLevelsNew();
164 while ((line
= fileReadLine ()) != NULL
)
166 int line_len
= strlen((const char*) line
);
167 int name_len_bytes
= vStringLength(name
);
168 int name_len
= utf8_strlen(vStringValue(name
), name_len_bytes
);
170 /* if the name doesn't look like UTF-8, assume one-byte charset */
172 name_len
= name_len_bytes
;
174 /* underlines must be the same length or more */
175 if (line_len
>= name_len
&& name_len
> 0 &&
176 ispunct(line
[0]) && issame((const char*) line
))
179 int kind
= get_kind(c
);
183 makeRestTag(name
, kind
);
188 if (! isspace(*line
))
189 vStringCatS(name
, (const char*) line
);
190 vStringTerminate(name
);
192 vStringDelete (name
);
193 nestingLevelsFree(nestingLevels
);
196 extern parserDefinition
* RestParser (void)
198 static const char *const patterns
[] = { "*.rest", "*.reST", NULL
};
199 static const char *const extensions
[] = { "rest", NULL
};
200 parserDefinition
* const def
= parserNew ("reStructuredText");
202 def
->kinds
= RestKinds
;
203 def
->kindCount
= KIND_COUNT (RestKinds
);
204 def
->patterns
= patterns
;
205 def
->extensions
= extensions
;
206 def
->parser
= findRestTags
;
210 /* vi:set tabstop=8 shiftwidth=4: */