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"
36 static kindOption RestKinds
[] = {
37 { TRUE
, 'n', "namespace", "chapters"},
38 { TRUE
, 'm', "member", "sections" },
39 { TRUE
, 'd', "macro", "subsections" },
40 { TRUE
, 'v', "variable", "subsubsections" }
43 static char kindchars
[SECTION_COUNT
];
45 static NestingLevels
*nestingLevels
= NULL
;
48 * FUNCTION DEFINITIONS
51 static NestingLevel
*getNestingLevel(const int kind
)
57 nl
= nestingLevelsGetCurrent(nestingLevels
);
58 if (nl
&& nl
->type
>= kind
)
59 nestingLevelsPop(nestingLevels
);
66 static void makeRestTag (const vString
* const name
, const int kind
)
68 const NestingLevel
*const nl
= getNestingLevel(kind
);
70 if (vStringLength (name
) > 0)
73 initTagEntry (&e
, vStringValue (name
));
75 e
.lineNumber
--; /* we want the line before the '---' underline chars */
76 e
.kindName
= RestKinds
[kind
].name
;
77 e
.kind
= RestKinds
[kind
].letter
;
79 if (nl
&& nl
->type
< kind
)
81 e
.extensionFields
.scopeKind
= &(RestKinds
[nl
->type
]);
82 e
.extensionFields
.scopeName
= vStringValue (nl
->name
);
86 nestingLevelsPush(nestingLevels
, name
, kind
);
90 /* checks if str is all the same character */
91 static boolean
issame(const char *str
)
108 static int get_kind(char c
)
112 for (i
= 0; i
< SECTION_COUNT
; i
++)
114 if (kindchars
[i
] == c
)
117 if (kindchars
[i
] == 0)
127 /* computes the length of an UTF-8 string
128 * if the string doesn't look like UTF-8, return -1 */
129 static int utf8_strlen(const char *buf
, int buf_len
)
132 const char *end
= buf
+ buf_len
;
134 for (len
= 0; buf
< end
; len
++)
136 /* perform quick and naive validation (no sub-byte checking) */
139 else if ((*buf
& 0xe0) == 0xc0)
141 else if ((*buf
& 0xf0) == 0xe0)
143 else if ((*buf
& 0xf8) == 0xf0)
145 else /* not a valid leading UTF-8 byte, abort */
148 if (buf
> end
) /* incomplete last byte */
156 /* TODO: parse overlining & underlining as distinct sections. */
157 static void findRestTags (void)
159 vString
*name
= vStringNew ();
160 const unsigned char *line
;
162 memset(kindchars
, 0, sizeof kindchars
);
163 nestingLevels
= nestingLevelsNew();
165 while ((line
= readLineFromInputFile ()) != NULL
)
167 int line_len
= strlen((const char*) line
);
168 int name_len_bytes
= vStringLength(name
);
169 int name_len
= utf8_strlen(vStringValue(name
), name_len_bytes
);
171 /* if the name doesn't look like UTF-8, assume one-byte charset */
173 name_len
= name_len_bytes
;
175 /* underlines must be the same length or more */
176 if (line_len
>= name_len
&& name_len
> 0 &&
177 ispunct(line
[0]) && issame((const char*) line
))
180 int kind
= get_kind(c
);
184 makeRestTag(name
, kind
);
189 if (! isspace(*line
))
190 vStringCatS(name
, (const char*) line
);
191 vStringTerminate(name
);
193 vStringDelete (name
);
194 nestingLevelsFree(nestingLevels
);
197 extern parserDefinition
* RestParser (void)
199 static const char *const patterns
[] = { "*.rest", "*.reST", NULL
};
200 static const char *const extensions
[] = { "rest", NULL
};
201 parserDefinition
* const def
= parserNew ("reStructuredText");
203 def
->kinds
= RestKinds
;
204 def
->kindCount
= ARRAY_SIZE (RestKinds
);
205 def
->patterns
= patterns
;
206 def
->extensions
= extensions
;
207 def
->parser
= findRestTags
;
211 /* vi:set tabstop=4 shiftwidth=4: */