Doxygen
Loading...
Searching...
No Matches
xmlcode.l
Go to the documentation of this file.
-1/******************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
13/******************************************************************************
14 * Parser for syntax highlighting and references for XML
15 * written by Weston Thayer
16 ******************************************************************************/
17
18%option never-interactive
19%option prefix="xmlcodeYY"
20%option reentrant
21%option extra-type="struct xmlcodeYY_state *"
22%option noyy_top_state
23%option nounput
24%option noyywrap
25%top{
26#include <stdint.h>
27// forward declare yyscan_t to improve type safety
28#define YY_TYPEDEF_YY_SCANNER_T
29struct yyguts_t;
30typedef yyguts_t *yyscan_t;
yyguts_t * yyscan_t
Definition code.l:24
31}
33%{
34
35#include <stdio.h>
36
37#include "xmlcode.h"
38
39#include "entry.h"
40#include "doxygen.h"
41#include "outputlist.h"
42#include "util.h"
43#include "membername.h"
44#include "searchindex.h"
45#include "config.h"
46#include "filedef.h"
47#include "tooltip.h"
48#include "message.h"
49#include "debug.h"
50
51#define YY_NEVER_INTERACTIVE 1
52#define YY_NO_INPUT 1
53#define YY_NO_UNISTD_H 1
56{
61 const char * inputString = nullptr; //!< the code fragment as text
62 int inputPosition = 0; //!< read offset during parsing
64 int inputLines = 0; //!< number of line in the code fragment
65 int yyLineNr = 0; //!< current line number
66 bool insideCodeLine = false;
67 const Definition *searchCtx = nullptr;
69 bool stripCodeComments = true;
70 bool exampleBlock = false;
80
81 std::unique_ptr<FileDef> exampleFileDef;
82 const FileDef * sourceFileDef = nullptr;
84 const Definition * currentDefinition = nullptr;
85 const MemberDef * currentMemberDef = nullptr;
86 bool includeCodeFragment = false;
87 const char * currentFontClass = nullptr;
88};
90[[maybe_unused]] static const char *stateToString(int state);
91
92static void codify(yyscan_t yyscanner,const char* text);
93static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor);
94static void startCodeLine(yyscan_t yyscanner);
95static void endFontClass(yyscan_t yyscanner);
96static void endCodeLine(yyscan_t yyscanner);
97static void nextCodeLine(yyscan_t yyscanner);
98static void codifyLines(yyscan_t yyscanner,const char *text);
99static void startFontClass(yyscan_t yyscanner,const char *s);
100static int countLines(yyscan_t yyscanner);
101static int yyread(yyscan_t yyscanner,char *buf,int max_size);
102
103#undef YY_INPUT
104#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
105
106// otherwise the filename would be the name of the converted file (*.cpp instead of *.l)
107static inline const char *getLexerFILE() {return __FILE__;}
108#include "doxygen_lex.h"
The common base class of all entity definitions found in the sources.
Definition definition.h:77
A model of a file symbol.
Definition filedef.h:99
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
Class representing a list of different code generators.
Definition outputlist.h:165
This is an alternative implementation of QCString.
Definition qcstring.h:101
static void endCodeLine(yyscan_t yyscanner)
Definition code.l:2489
static void nextCodeLine(yyscan_t yyscanner)
Definition code.l:2498
static void startCodeLine(yyscan_t yyscanner)
Definition code.l:2420
static void codifyLines(yyscan_t yyscanner, const QCString &text)
Definition code.l:2516
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition code.l:3982
static int countLines(yyscan_t yyscanner)
Definition code.l:3473
static const char * stateToString(int state)
static void startFontClass(yyscan_t yyscanner, const char *s, bool specialComment=false)
Definition code.l:3506
static void endFontClass(yyscan_t yyscanner, bool specialComment=false)
Definition code.l:3491
static const char * getLexerFILE()
Definition code.l:263
static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor)
Definition code.l:2288
static void codify(yyscan_t yyscanner, const QCString &text)
Definition pycode.l:1017
#define FALSE
Definition qcstring.h:34
Web server based search engine.
QCString exampleName
Definition xmlcode.l:73
bool lineNumbers
Definition xmlcode.l:85
QCString fileName
Definition xmlcode.l:65
QCString args
Definition xmlcode.l:78
const char * currentFontClass
Definition xmlcode.l:89
OutputCodeList * code
Definition xmlcode.l:59
QCString name
Definition xmlcode.l:77
QCString CurrScope
Definition xmlcode.l:81
const Definition * currentDefinition
Definition xmlcode.l:86
const FileDef * sourceFileDef
Definition xmlcode.l:84
const MemberDef * currentMemberDef
Definition xmlcode.l:87
int yyLineNr
current line number
Definition xmlcode.l:67
int inputPosition
read offset during parsing
Definition xmlcode.l:64
std::unique_ptr< FileDef > exampleFileDef
Definition xmlcode.l:83
QCString parmType
Definition xmlcode.l:61
QCString exampleFile
Definition xmlcode.l:74
const char * inputString
the code fragment as text
Definition xmlcode.l:63
QCString classScope
Definition xmlcode.l:79
QCString parmName
Definition xmlcode.l:62
int inputLines
number of line in the code fragment
Definition xmlcode.l:66
QCString type
Definition xmlcode.l:76
bool includeCodeFragment
Definition xmlcode.l:88
bool stripCodeComments
Definition xmlcode.l:71
QCString curClassName
Definition xmlcode.l:60
const Definition * searchCtx
Definition xmlcode.l:69
bool exampleBlock
Definition xmlcode.l:72
bool insideCodeLine
Definition xmlcode.l:68
A bunch of utility functions.
110%}
111
112nl (\r\n|\r|\n)
113ws [ \t]+
114open "<"
115close ">"
116namestart [A-Za-z\200-\377_]
117namechar [:A-Za-z\200-\377_0-9.-]
118esc "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";"
119name {namestart}{namechar}*
120comment {open}"!--"([^-]|"-"[^-])*"--"{close}
121cdata {open}"![CDATA["([^\‍]]|"\‍]"[^\‍]])*"]]"{close}
122string \"([^\"&]|{esc})*\"|\'([^'&]|{esc})*\'
123
124%option noyywrap
125%option nounput
126
127%%
128
129<INITIAL>{ws} {
130 codifyLines(yyscanner,yytext);
131 }
132<INITIAL>"/" {
133 endFontClass(yyscanner);
134 codify(yyscanner,yytext);
135 }
136<INITIAL>"=" {
137 endFontClass(yyscanner);
138 codify(yyscanner,yytext);
139 }
140<INITIAL>{close} {
141 endFontClass(yyscanner);
142 codify(yyscanner,yytext);
143 }
144<INITIAL>{name} {
145 startFontClass(yyscanner,"keyword");
146 codify(yyscanner,yytext);
147 endFontClass(yyscanner);
148 }
149<INITIAL>{string} {
150 startFontClass(yyscanner,"stringliteral");
151 codifyLines(yyscanner,yytext);
152 endFontClass(yyscanner);
153 }
154{cdata} {
155 startFontClass(yyscanner,"xmlcdata");
156 codifyLines(yyscanner,yytext);
157 endFontClass(yyscanner);
158 }
159
160{open}{ws}?{name} {
161 // Write the < in a different color
162 char openBracket[] = { yytext[0], '\0' };
163 codify(yyscanner,openBracket);
164
165 // Then write the rest
166 yytext++;
167 startFontClass(yyscanner,"keywordtype");
168 codify(yyscanner,yytext);
169 endFontClass(yyscanner);
170
171 BEGIN(INITIAL);
172 }
173{open}{ws}?"/"{name} {
174 // Write the "</" in a different color
175 char closeBracket[] = { yytext[0], yytext[1], '\0' };
176 endFontClass(yyscanner);
177 codify(yyscanner,closeBracket);
178
179 // Then write the rest
180 yytext++; // skip the '<'
181 yytext++; // skip the '/'
182 startFontClass(yyscanner,"keywordtype");
183 codify(yyscanner,yytext);
184 endFontClass(yyscanner);
185
186 BEGIN(INITIAL);
187 }
188{comment} {
189 // Strip off the extra '!'
190 // yytext++; // <
191 // *yytext = '<'; // replace '!' with '<'
192
193 startFontClass(yyscanner,"comment");
194 codifyLines(yyscanner,yytext);
195 endFontClass(yyscanner);
196 }
197{nl} {
198 codifyLines(yyscanner,yytext);
199 }
200
201. {
202 //printf("!ERROR(%c)\n", *yytext);
203 codifyLines(yyscanner,yytext);
204 }
205
206%%
207
208//----------------------------------------------------------------------------------------
209
210static int yyread(yyscan_t yyscanner,char *buf,int max_size)
211{
212 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
213 int inputPosition = yyextra->inputPosition;
214 const char *s = yyextra->inputString + inputPosition;
215 int c=0;
216 while( c < max_size && *s)
217 {
218 *buf++ = *s++;
219 c++;
220 }
221 yyextra->inputPosition += c;
222 return c;
223}
224
225static void codify(yyscan_t yyscanner,const char* text)
226{
227 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
228 yyextra->code->codify(text);
229}
230
231static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor)
232{
233 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
234 if (Doxygen::searchIndex.enabled())
235 {
236 if (yyextra->searchCtx)
237 {
238 Doxygen::searchIndex.setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false);
239 }
240 else
241 {
242 Doxygen::searchIndex.setCurrentDoc(yyextra->sourceFileDef,anchor,true);
243 }
244 }
245}
246
247/*! start a new line of code, inserting a line number if yyextra->sourceFileDef
248 * is true. If a definition starts at the current line, then the line
249 * number is linked to the documentation of that definition.
250 */
251static void startCodeLine(yyscan_t yyscanner)
252{
253 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
254 if (yyextra->sourceFileDef && yyextra->lineNumbers)
255 {
256 const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
257
258 if (!yyextra->includeCodeFragment && d && d->isLinkableInProject())
259 {
260 yyextra->currentDefinition = d;
261 yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
262 //yyextra->insideBody = false;
263 yyextra->classScope = d->name();
264 QCString lineAnchor;
265 lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
266 if (yyextra->currentMemberDef)
267 {
268 yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
269 yyextra->currentMemberDef->getOutputFileBase(),
270 yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
271 !yyextra->includeCodeFragment);
272 setCurrentDoc(yyscanner,lineAnchor);
273 }
274 else
275 {
276 yyextra->code->writeLineNumber(d->getReference(),
278 QCString(),yyextra->yyLineNr,
279 !yyextra->includeCodeFragment);
280 setCurrentDoc(yyscanner,lineAnchor);
281 }
282 }
283 else
284 {
285 yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
286 !yyextra->includeCodeFragment);
287 }
288 }
289
290 yyextra->code->startCodeLine(yyextra->yyLineNr);
291 yyextra->insideCodeLine = true;
292
293 if (yyextra->currentFontClass)
294 {
295 yyextra->code->startFontClass(yyextra->currentFontClass);
296 }
297}
298
299static void endFontClass(yyscan_t yyscanner)
300{
301 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
302 if (yyextra->currentFontClass)
303 {
304 yyextra->code->endFontClass();
305 yyextra->currentFontClass=0;
306 }
307}
308
309static void endCodeLine(yyscan_t yyscanner)
310{
311 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
312 endFontClass(yyscanner);
313 yyextra->code->endCodeLine();
314 yyextra->insideCodeLine = false;
315}
316
317static void nextCodeLine(yyscan_t yyscanner)
318{
319 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
320 const char *fc = yyextra->currentFontClass;
321 if (yyextra->insideCodeLine)
322 {
323 endCodeLine(yyscanner);
324 }
325 if (yyextra->yyLineNr<yyextra->inputLines)
326 {
327 yyextra->currentFontClass = fc;
328 startCodeLine(yyscanner);
329 }
330}
331
332static void codifyLines(yyscan_t yyscanner,const char *text)
333{
334 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
335 const char *p=text,*sp=p;
336 char c;
337 bool done=false;
338 while (!done)
339 {
340 sp=p;
341 while ((c=*p++) && c!='\n') { }
342 if (c=='\n')
343 {
344 yyextra->yyLineNr++;
345 size_t l = static_cast<size_t>(p-sp-1);
346 yyextra->code->codify(QCString(sp,l));
347 nextCodeLine(yyscanner);
348 }
349 else
350 {
351 yyextra->code->codify(sp);
352 done=true;
353 }
354 }
355}
356
357static void startFontClass(yyscan_t yyscanner,const char *s)
358{
359 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
360 endFontClass(yyscanner);
361 yyextra->code->startFontClass(s);
362 yyextra->currentFontClass=s;
363}
364
365/*! counts the number of lines in the input */
366static int countLines(yyscan_t yyscanner)
367{
368 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
369 const char *p=yyextra->inputString;
370 char c;
371 int count=1;
372 while ((c=*p))
373 {
374 p++ ;
375 if (c=='\n') count++;
376 }
377 if (p>yyextra->inputString && *(p-1)!='\n')
378 { // last line does not end with a \n, so we add an extra
379 // line and explicitly terminate the line after parsing.
380 count++;
381 }
382 return count;
383}
384
385//----------------------------------------------------------------------------------------
386
388{
394{
395 xmlcodeYYlex_init_extra(&p->state,&p->yyscanner);
396#ifdef FLEX_DEBUG
397 xmlcodeYYset_debug(Debug::isFlagSet(Debug::Lex_xmlcode)?1:0,p->yyscanner);
398#endif
400}
401
403{
404 xmlcodeYYlex_destroy(p->yyscanner);
405}
406
408{
409 struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner;
410 yyextra->currentDefinition = nullptr;
411 yyextra->currentMemberDef = nullptr;
412}
413
415 const QCString &/* scopeName */,
416 const QCString &input,
418 bool stripCodeComments,
419 const CodeParserOptions &options
420 )
421{
422 yyscan_t yyscanner = p->yyscanner;
423 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
424
425 if (input.isEmpty()) return;
426
427 DebugLex debugLex(Debug::Lex_xmlcode, __FILE__, options.fileDef() ? qPrint(options.fileDef()->fileName()): nullptr);
428 yyextra->fileName = options.fileDef() ? options.fileDef()->fileName():"";
429 yyextra->code = &codeOutIntf;
430 yyextra->inputString = input.data();
431 yyextra->inputPosition = 0;
432 yyextra->currentFontClass = nullptr;
433 yyextra->insideCodeLine = false;
434 yyextra->searchCtx = options.searchCtx();
435 yyextra->yyLineNr = options.startLine()!=-1 ? options.startLine() : 1;
436 yyextra->inputLines = options.endLine()!=-1 ? options.endLine()+1 : yyextra->yyLineNr + countLines(yyscanner) - 1;
437 yyextra->stripCodeComments = stripCodeComments;
438 yyextra->exampleBlock = options.isExample();
439 yyextra->exampleName = options.exampleName();
440 yyextra->sourceFileDef = options.fileDef();
441 yyextra->lineNumbers = options.fileDef() && options.showLineNumbers();
442
443 if (options.isExample() && options.fileDef()==nullptr)
444 {
445 // create a dummy filedef for the example
446 yyextra->exampleFileDef = createFileDef("",(!options.exampleName().isEmpty()?options.exampleName():QCString("generated")));
447 yyextra->sourceFileDef = yyextra->exampleFileDef.get();
448 }
449
450 if (yyextra->sourceFileDef)
451 {
452 setCurrentDoc(yyscanner,"l00001");
453 }
454
455 yyextra->includeCodeFragment = options.inlineFragment();
456 // Starts line 1 on the output
457 startCodeLine(yyscanner);
458
459 xmlcodeYYrestart( nullptr, yyscanner );
460
461 xmlcodeYYlex(yyscanner);
462
463 if (yyextra->insideCodeLine)
464 {
465 endCodeLine(yyscanner);
466 }
467 if (yyextra->exampleFileDef)
468 {
469 // delete the temporary file definition used for this example
470 yyextra->exampleFileDef.reset();
471 yyextra->sourceFileDef=nullptr;
472 }
473}
474
475
476#include "xmlcode.l.h"
@ Lex_xmlcode
Definition debug.h:71
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
virtual bool isLinkableInProject() const =0
virtual QCString getReference() const =0
virtual QCString getOutputFileBase() const =0
virtual const QCString & name() const =0
static SearchIndexIntf searchIndex
Definition doxygen.h:123
virtual QCString fileName() const =0
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
std::unique_ptr< Private > p
Definition xmlcode.h:48
~XMLCodeParser() override
Definition xmlcode.l:404
void resetCodeParserState() override
Resets the state of the code parser.
Definition xmlcode.l:409
void parseCode(OutputCodeList &codeOutIntf, const QCString &scopeName, const QCString &input, SrcLangExt, bool stripCodeComments, const CodeParserOptions &options) override
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
Definition xmlcode.l:416
std::unique_ptr< FileDef > createFileDef(const QCString &p, const QCString &n, const QCString &ref, const QCString &dn)
Definition filedef.cpp:269
const char * qPrint(const char *s)
Definition qcstring.h:687
Options to configure the code parser.
Definition parserintf.h:78
bool isExample() const
Definition parserintf.h:81
const Definition * searchCtx() const
Definition parserintf.h:89
const FileDef * fileDef() const
Definition parserintf.h:83
int endLine() const
Definition parserintf.h:85
bool showLineNumbers() const
Definition parserintf.h:88
bool inlineFragment() const
Definition parserintf.h:86
QCString exampleName() const
Definition parserintf.h:82
int startLine() const
Definition parserintf.h:84
xmlcodeYY_state state
Definition xmlcode.l:392
SrcLangExt
Definition types.h:207