Doxygen
vhdlcode.l
浏览该文件的文档.
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  */
15 /******************************************************************************
16  * Parser for syntax highlighting and references for vhdl subset
17  * written by M. Kreis
18  * supports VHDL-87/93/2008
19  ******************************************************************************/
20 %option never-interactive
21 %option case-insensitive
22 %option prefix="vhdlcodeYY"
23 %option reentrant
24 %option extra-type="struct vhdlcodeYY_state *"
25 %top{
26 #include <stdint.h>
27 // forward declare yyscan_t to improve type safety
28 #define YY_TYPEDEF_YY_SCANNER_T
29 struct yyguts_t;
30 typedef yyguts_t *yyscan_t;
31 }
32 
33 %{
34 
35 #include <unordered_set>
36 #include <string>
37 
38 /*
39  * includes
40  */
41 #include <stdio.h>
42 #include <assert.h>
43 #include <ctype.h>
44 
45 #include "vhdlcode.h"
46 #include "entry.h"
47 #include "doxygen.h"
48 #include "message.h"
49 #include "outputlist.h"
50 #include "util.h"
51 #include "membername.h"
52 #include "searchindex.h"
53 #include "vhdldocgen.h"
54 #include "arguments.h"
55 #include "config.h"
56 #include "classdef.h"
57 #include "filedef.h"
58 #include "tooltip.h"
59 #include "regex.h"
60 
61 #define YY_NO_INPUT 1
62 #define YY_NO_UNISTD_H 1
63 
64 #define USE_STATE2STRING 0
65 
66 // Toggle for some debugging info
67 //#define DBG_CTX(x) fprintf x
68 #define DBG_CTX(x) do { } while(0)
69 
70 
71 /* -----------------------------------------------------------------
72  * statics
73  */
74 
75 // ----------------- <vhdl> ----------------------------------
76 
77 struct vhdlcodeYY_state
78 {
79  bool isFuncProto = false;
80  bool isComponent = false;
81  bool isPackageBody = false;
82  bool isProto = false;
83  bool startCode = false;
84  QCString prevString;
85  QCString currClass;
86  std::unordered_set<std::string> vhdlKeyDict;
87  QCString tempComp;
88  QCString PortMapComp;
89  const MemberDef * vhdlMember = 0;
90  QCString funcProto;
91 
92  CodeOutputInterface * code = 0;
93  const char * inputString = 0; //!< the code fragment as text
94  yy_size_t inputPosition = 0; //!< read offset during parsing
95  int inputLines = 0; //!< number of line in the code fragment
96  int yyLineNr = 0; //!< current line number
97  bool needsTermination = false;
98  const Definition *searchCtx = 0;
99 
100  bool exampleBlock = false;
101  QCString exampleName;
102  QCString exampleFile;
103 
104  bool currArch = false;
105 
106  const FileDef * sourceFileDef = 0;
107  const Definition * currentDefinition = 0;
108  const MemberDef * currentMemberDef = 0;
109  bool includeCodeFragment = false;
110  const char * currentFontClass = 0;
111 
112  bool lexInit = false;
113  int braceCount = 0;
114  TooltipManager tooltipManager;
115 };
116 
117 
118 static void writeFont(yyscan_t yyscanner,const char *s,const QCString &text);
119 static void generateMemLink(yyscan_t yyscanner,CodeOutputInterface &ol,QCString &clName,QCString& memberName);
120 static bool writeColoredWord(yyscan_t yyscanner,QCString& word );
121 static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const QCString &clName, bool typeOnly=false, const QCString &curr_class=QCString());
122 static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor);
123 static bool checkVhdlString(yyscan_t yyscanner,QCString &name);
124 static void addToSearchIndex(yyscan_t yyscanner,const QCString &text);
125 static void startCodeLine(yyscan_t yyscanner);
126 static void endCodeLine(yyscan_t yyscanner);
127 static void nextCodeLine(yyscan_t yyscanner);
128 static void writeWord(yyscan_t yyscanner,const QCString &word,const QCString &curr_class=QCString(),bool classLink=false);
129 static void codifyLines(yyscan_t yyscanner,const QCString &text,const QCString &cl=QCString(),bool classlink=false,bool comment=false);
130 static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol,
131  const Definition *d,
132  const QCString &text);
133 static void generateFuncLink(yyscan_t yyscanner,CodeOutputInterface &ol,const MemberDef* mdef);
134 static int countLines(yyscan_t yyscanner);
135 static void endFontClass(yyscan_t yyscanner);
136 static void startFontClass(yyscan_t yyscanner,const char *s);
137 static void appStringLower(QCString& qcs,const char* text);
138 static void codifyMapLines(yyscan_t yyscanner,const QCString &text);
139 static void writeFuncProto(yyscan_t yyscanner);
140 static void writeProcessProto(yyscan_t yyscanner);
141 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size);
142 
143 #if USE_STATE2STRING
144 static const char *stateToString(int state);
145 #endif
146 //-------------------------------------------------------------------
147 
148 
149 #undef YY_INPUT
150 #define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size);
151 
152 %}
153 
154 
155 B [ \t]
156 BN [ \t\n\r]
157 STRING ["][^"\n]*["]
158 NAME [a-z_A-Z][ a-z_A-Z0-9]*
159 FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]*
160 ID "$"?[a-z_A-Z][a-z_A-Z0-9]*
161 SPECSIGN [:;, +*&\/=<>'\t]*
162 DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")*
163 ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}*
164 ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}*
165 
166 ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME}{BN}+("is")
167 PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+
168 
169 END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for")
170 END2 [^a-zA-Z_]("end"){BN}*[;]
171 END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;]
172 END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;]
173 ENDEFUNC {END3}|{END4}|{END2}
174 
175 KEYWORD ("of"|"new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in")
176 TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration")
177 FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(")
178 
179 ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":="
180 ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|="
181 LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!"
182 BITOP "&"|"|"|"^"|"<<"|">>"|"~"
183 OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}
184 
185 PORT {B}*("port"){BN}*("(")
186 GENERIC {B}*("generic"){BN}*("(")
187 
188 BRACEOPEN [(]{1}
189 BRACECLOSE [)]{1}
190 
191 TEXTT {B}*"--"[^\n]*
192 
193 MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1})
194 MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1}
195 MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1})
196 MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1})
197 
198 XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFIG"|"CONFIG_MODE"|"COOL_CLK"|"DATA_GATE"|"DCI_VALUE"|"DISABLE"|"DRIVE"|"DROP_SPEC"|"ENABLE"|"FAST"|"FEEDBACK"|"FILE"|"FLOAT"|"FROM-THRU-TO"|"FROM-TO"|"HBLKNM"|"HU_SET"|"INREG"|"IOB"|"IOBDELAY"|"IOSTANDARD"|"KEEP"|"KEEPER"|"LOC"|"LOCATE"|"LOCK_PINS"|"MAP"|"MAXDELAY"|"MAXPT"|"MAXSKEW"|"NODELAY"|"NOREDUCE"|"OFFSET"|"OPEN_DRAIN"|"OPT_EFFORT"|"OPTIMIZE"|"PERIOD"|"PIN"|"PRIORITY"|"PROHIBIT"|"PULLDOWN"|"PULLUP"|"PWR_MODE"|"REG"|"RLOC"|"RLOC_ORIGIN"|"RLOC_RANGE"|"SAVE NET"|"FLAG"|"SYSTEM_JITTER"|"TEMPERATURE"|"TIMEGRP"|"TIMESPEC"|"VOLTAGE"
199 
200 %option noyywrap
201 %option nounput
202 
203 %x Bases
204 %x ParseType
205 %x ParseFuncProto
206 %x ParseComponent
207 %x ParsePackage
208 %x ParseProcessProto
209 %x ClassesName
210 %x Map
211 %x End
212 
213 %%
214 
215 . {
216  BEGIN(Bases);
217  }
218 
219 <Map>{BRACEOPEN} {
220  yyextra->braceCount++;
221  writeFont(yyscanner,"vhdlchar",yytext);
222  BEGIN(Map);
223  }
224 
225 <Map>[^()\n,--]* { /* write and link a port map lines */
226  QCString tt(yytext);
227  VhdlDocGen::deleteAllChars(tt,',');
228  auto ql = split(tt.str(),"=>");
229  if (ql.size()>=2)
230  {
231  unsigned int index=0;
232  QCString t1(ql[0]);
233  char cc=t1.at(index);
234  while (cc==' ' || cc=='\t')
235  {
236  char c2[2];
237  c2[0]=cc;
238  c2[1]=0;
239  yyextra->code->codify(c2);
240  index++;
241  if (index>=t1.size()) break;
242  cc=t1.at(index);
243  }
244 
245  QCString s1=t1;
246  s1=s1.stripWhiteSpace();
247 
248  // if (!yyextra->PortMapComp.isEmpty())
249  generateMemLink(yyscanner,*yyextra->code,yyextra->PortMapComp,s1);
250  while (index++<t1.size())
251  {
252  cc=t1.at(index);
253  if (cc==' ' || cc=='\t')
254  {
255  char c2[2];
256  c2[0]=cc;
257  c2[1]=0;
258  yyextra->code->codify(c2);
259  }
260  }
261  codifyLines(yyscanner,"=>");
262  index=0;
263  QCString s2(ql[1]);
264  t1=s2;
265  cc=t1.at(index);
266  while (cc==' ' || cc=='\t')
267  {
268  char c2[2];
269  c2[0]=cc;
270  c2[1]=0;
271  yyextra->code->codify(c2);
272  index++;
273  if (index>=t1.size()) break;
274  cc=t1.at(index);
275  }
276  s2=s2.stripWhiteSpace();
277  if (!checkVhdlString(yyscanner,s2))
278  {
279  generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,s2);
280  }
281  while (index++<t1.size())
282  {
283  if (t1.at(index)==' ')
284  {
285  yyextra->code->codify(" ");
286  }
287  }
288  }
289  else
290  {
291  codifyLines(yyscanner,yytext,yyextra->currClass);
292  }
293  BEGIN(Map);
294  }
295 
296 <Map>"\n"|"," {
297  codifyLines(yyscanner,yytext);
298  BEGIN(Map);
299  }
300 
301 <Map>{BRACECLOSE} {
302  yyextra->braceCount--;
303  writeFont(yyscanner,"vhdlchar",yytext);
304  if (yyextra->braceCount==0)
305  {
306  BEGIN(Bases);
307  }
308  }
309 
310 <ParseFuncProto>{NAME} {
311  QCString tmp(yytext);
312  tmp=tmp.stripWhiteSpace();
313  appStringLower(yyextra->prevString,yytext);
314  yyextra->vhdlKeyDict.insert(yyextra->prevString.str());
315  if (!writeColoredWord(yyscanner,tmp))
316  {
317  generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,tmp);
318  }
319  BEGIN(Bases);
320  }
321 
322 <ParseType>{STRING} {
323  QCString qcs(yytext);
324  VhdlDocGen::deleteAllChars(qcs,'"');
325  VhdlDocGen::deleteAllChars(qcs,' ');
326  if (VhdlDocGen::isNumber(qcs.str()))
327  {
328  writeFont(yyscanner,"vhdllogic",yytext);
329  }
330  else
331  {
332  writeFont(yyscanner,"keyword",yytext);
333  }
334  }
335 
336 <ParseType>"\n" {
337  yyextra->funcProto.append(yytext);
338  if (yyextra->isProto)
339  {
340  codifyLines(yyscanner,yytext);
341  }
342  BEGIN(ParseType);
343  }
344 
345 
346 <ParseType>{TEXTT} {
347  yyextra->funcProto.append(yytext);
348  if (yyextra->isProto)
349  {
350  writeFont(yyscanner,"keyword",yytext);
351  }
352  BEGIN(ParseType);
353  }
354 
355 <ParseType>{ENDEFUNC} {
356  QCString tt(yytext);
357  codifyLines(yyscanner,yytext,yyextra->currClass);
358  tt=tt.lower();
359  VhdlDocGen::deleteAllChars(tt,';');
360  tt.stripWhiteSpace();
361  static const reg::Ex regg(R"(\s+)"); // any number of whitespace
362  auto ql = split(tt.str(),regg);
363  int index=findIndex(ql,"if")+1;
364  index+=findIndex(ql,"case")+1;
365  index+=findIndex(ql,"loop")+1;
366  index+=findIndex(ql,"generate")+1;
367  if (index==0)
368  {
369  BEGIN(Bases);
370  }
371  else
372  {
373  BEGIN(ParseType);
374  }
375  }
376 
377 <ParseType>{END1} {
378  codifyLines(yyscanner,yytext,yyextra->currClass);
379  yyextra->vhdlKeyDict.clear();
380  }
381 
382 <ParseType>^{B}*("begin "|"begin") {
383  codifyLines(yyscanner,yytext,yyextra->currClass);
384  yyextra->isFuncProto=false;
385  }
386 
387 <ParseType>{SPECSIGN} {
388  yyextra->funcProto.append(yytext);
389  if (yyextra->isProto)
390  {
391  codifyLines(yyscanner,yytext,yyextra->currClass);
392  }
393  }
394 
395 <ParseType>["_a-zA-Z0-9]* {
396  QCString val(yytext);
397  yyextra->funcProto.append(yytext);
398  appStringLower(yyextra->prevString,yytext);
399 
400  if (yyextra->isFuncProto && yyextra->braceCount==0)
401  {
402  yyextra->vhdlKeyDict.insert(yyextra->prevString.str());
403  }
404 
405  if (yyextra->isProto)
406  {
407  if (!writeColoredWord(yyscanner,val))
408  {
409  if (!yyextra->isFuncProto &&
410  yyextra->vhdlKeyDict.find(yyextra->prevString.str())==yyextra->vhdlKeyDict.end())
411  {
412  val=val.stripWhiteSpace();
413  if (VhdlDocGen::isNumber(val.str()))
414  {
415  startFontClass(yyscanner,"vhdllogic");
416  codifyLines(yyscanner,yytext,yyextra->currClass);
417  endFontClass(yyscanner);
418  }
419  else
420  {
421  generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,val);
422  }
423  }
424  else
425  {
426  codifyLines(yyscanner,yytext,yyextra->currClass);
427  }
428  }
429  }
430  BEGIN(ParseType);
431  }
432 
433 <ParseType>{BRACEOPEN} {
434  yyextra->braceCount++;
435  yyextra->funcProto+='(';
436  if (yyextra->isProto)
437  {
438  writeFont(yyscanner,"vhdlchar",yytext);
439  }
440  BEGIN(ParseType);
441  }
442 
443 <ParseType>{BRACECLOSE} {
444  yyextra->braceCount--;
445  yyextra->funcProto+=')';
446  if (yyextra->isProto)
447  {
448  writeFont(yyscanner,"vhdlchar",yytext);
449  }
450  if (yyextra->braceCount==0 && !yyextra->isProto)// && !yyextra->isPackageBody)
451  {
452  yyextra->isProto=true;
453  appStringLower(yyextra->prevString,yytext);
454  writeFuncProto(yyscanner);
455  BEGIN(Bases);
456  }
457  if (yyextra->isPackageBody)
458  {
459  BEGIN(ParseType);
460  }
461  }
462 
463 
464 <ClassesName>{FUNCNAME} {
465  appStringLower(yyextra->prevString,yytext);
466  yyextra->currClass.resize(0);
467  yyextra->currClass.append(yytext);
468  yyextra->currClass=yyextra->currClass.stripWhiteSpace();
469 
470  generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext);
471  BEGIN(Bases);
472  }
473 
474 
475 <ParseComponent>{BRACEOPEN} {
476  yyextra->braceCount++;
477  yyextra->code->codify(yytext);
478  }
479 
480 
481 <ParseComponent>{BRACECLOSE} {
482  yyextra->braceCount--;
483  yyextra->code->codify(yytext);
484  if (yyextra->braceCount==0 && !yyextra->isComponent)
485  {
486  yyextra->tempComp.resize(0);
487  BEGIN(Bases);
488  }
489  else
490  {
491  BEGIN(ParseComponent);
492  }
493  }
494 
495 <ParseComponent>{B}*"-" {
496  if (strlen(yytext)>=2) // found text ?
497  {
498  writeFont(yyscanner,"keyword",yytext);
499  }
500  else
501  {
502  writeFont(yyscanner,"vhdlchar",yytext);
503  }
504  }
505 
506 <ParseComponent>{SPECSIGN} {
507  codifyLines(yyscanner,yytext);
508  }
509 
510 
511 
512 <ParseComponent>"\n"|" " {
513  codifyLines(yyscanner,yytext);
514  }
515 
516 <ParseComponent>{DIGITSS} {
517  startFontClass(yyscanner,"vhdllogic");
518  codifyLines(yyscanner,yytext);
519  endFontClass(yyscanner);
520  }
521 
522 <ParseComponent>{PORT} {
523  codifyLines(yyscanner,yytext);
524  yyextra->braceCount=1;
525  yyextra->isComponent=false;
526  }
527 
528 <ParseComponent>{GENERIC} {
529  codifyLines(yyscanner,yytext);
530  yyextra->braceCount=1;
531  }
532 
533 <ParseComponent>[_a-zA_Z][_a-zA-Z0-9]* {
534  QCString temp(yytext);
535  appStringLower(yyextra->prevString,yytext);
536  if (!checkVhdlString(yyscanner,temp))
537  {
538  if (!writeColoredWord(yyscanner,yyextra->prevString))
539  {
540  generateMemLink(yyscanner,*yyextra->code,yyextra->tempComp,temp);
541  }
542  }
543  }
544 
545 <ParseComponent>{STRING} {
546  QCString temp(yytext);
547  if (!checkVhdlString(yyscanner,temp))
548  {
549  codifyLines(yyscanner,yytext);
550  }
551  }
552 
553 
554 <ParseProcessProto>[^()]* {
555  yyextra->funcProto.append(yytext);
556  }
557 
558 
559 
560 <ParseProcessProto>{BRACEOPEN} {
561  yyextra->funcProto.append(yytext);
562  yyextra->braceCount++;
563  }
564 
565 <ParseProcessProto>{BRACECLOSE} {
566  yyextra->funcProto.append(yytext);
567  yyextra->braceCount--;
568  if (yyextra->braceCount==0)
569  {
570  writeProcessProto(yyscanner);
571  BEGIN(Bases);
572  }
573  }
574 
575 <ParsePackage>[^:;]* { //found package
576  StringVector strl=split(yytext,".");
577  if (strl.size()>2)
578  {
579  std::string s1=strl[0];
580  std::string s2=strl[1];
581  std::string s3=strl[2];
582  s1.append(".");
583  s3.insert(0,".");
584  codifyLines(yyscanner,s1.c_str(),yyextra->currClass);
585  ClassDef *cd=VhdlDocGen::getPackageName(s2.c_str());
586  if (cd)
587  {
588  generateClassOrGlobalLink(yyscanner,*yyextra->code,s2.c_str());
589  }
590  else
591  {
592  codifyLines(yyscanner,s2.c_str());
593  }
594  codifyLines(yyscanner,s3.c_str());
595  }
596  else
597  {
598  writeFont(yyscanner,"keywordflow",yytext);
599  }
600  BEGIN(Bases);
601  }
602 
603 <Bases>{MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map
604  QCString tt(yytext);
605  int j=tt.find('.');
606 
607  if (j>0)
608  {
609  QCString left=tt.left(j+1);
610  codifyLines(yyscanner,left);
611  tt=tt.right(tt.length()-j-1);
612  left=VhdlDocGen::getIndexWord(tt,0);
613  if (!left.isEmpty())
614  {
615  j=left.find('(',false);
616  if (j>=0)
617  {
618  QCString name=left.left(j);
619  generateClassOrGlobalLink(yyscanner,*yyextra->code,name);
620  yyextra->PortMapComp=name;
621  name=tt.right(tt.length()-name.length());
622  codifyLines(yyscanner,name);
623  }
624  else
625  {
626  generateClassOrGlobalLink(yyscanner,*yyextra->code,left);
627  tt.stripPrefix(left); //=tt.right(tt.length()-left.length()-1);
628 
629  yyextra->PortMapComp=left;
630  codifyLines(yyscanner,tt);
631  }
632  }
633  }
634  else
635  {
636  if (tt.contains(':',false))
637  {
638  codifyMapLines(yyscanner,tt);
639  }
640  else
641  {
642  codifyLines(yyscanner,tt);
643  }
644  }
645  yyextra->braceCount=1;
646  BEGIN(Map);
647  }
648 
649 <Bases>^{B}*("component"){BN}+{FUNCNAME} { // found component
650  appStringLower(yyextra->prevString,yytext);
651  QCString temp=VhdlDocGen::getIndexWord(yytext,1);
652  temp=temp.stripWhiteSpace();
653  VhdlDocGen::deleteAllChars(temp,'\n');
654  yyextra->tempComp=temp;
655  codifyLines(yyscanner,yytext,temp,true);
656  yyextra->braceCount=0;
657  yyextra->isComponent=true;
658  BEGIN(ParseComponent);
659  }
660 
661 
662 
663 <Bases>{ARCHITECTURE} { // found architecture
664  yyextra->PortMapComp.resize(0);
665  QCString temp = VhdlDocGen::getIndexWord(yytext,3);
666  yyextra->currArch = true;
667  temp+="::";
668  temp+=VhdlDocGen::getIndexWord(yytext,1);
669  yyextra->currClass=temp;
670  VhdlDocGen::deleteAllChars(temp,'\n');
671  codifyLines(yyscanner,yytext,temp,true);
672  yyextra->isPackageBody=false;
673  }
674 
675 
676 <Bases>^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body
677  QCString ss(yytext);
678  QCString temp=VhdlDocGen::getIndexWord(yytext,2);
679  StringVector ql=split(yytext,temp.str());
680  std::string ll=ql[0];
681  codifyLines(yyscanner,ll.c_str(),yyextra->currClass);
682  temp=temp.stripWhiteSpace();
683  temp.prepend("_");
684  generateClassOrGlobalLink(yyscanner,*yyextra->code,temp);
685  yyextra->currClass.resize(0);
686  yyextra->currClass=temp;
687  yyextra->isProto=false;
688  yyextra->isPackageBody=true;
689  }
690 
691 <Bases>{PROCESS} { // found process
692  yyextra->isFuncProto=true;
693  yyextra->funcProto.resize(0);
694  yyextra->funcProto.append(yytext);
695  yyextra->vhdlKeyDict.clear();
696  appStringLower(yyextra->prevString,yytext);
697  if (yyextra->prevString.contains('('))
698  {
699  yyextra->braceCount=1;
700  BEGIN(ParseProcessProto);
701  }
702  else
703  {
704  writeProcessProto(yyscanner);
705  }
706  }
707 
708 <Bases>("end"){BN}+("process") { // end of process
709  yyextra->isFuncProto=false;
710  codifyLines(yyscanner,yytext);
711  BEGIN(Bases);
712  }
713 
714 
715 <Bases>^{B}*("begin "|"begin") {
716  yyextra->isFuncProto=false;
717  writeFont(yyscanner,"vhdlkeyword",yytext);
718  }
719 
720 <Bases>^{B}*("use"|"library"){BN}+ { //found package or library
721  writeFont(yyscanner,"vhdlkeyword",yytext);
722  BEGIN(ParsePackage);
723  }
724 
725 
726 <Bases>^{B}*("use"){BN}+("configuration")[^\n]* {
727  codifyLines(yyscanner,yytext);
728  }
729 
730 <Bases>{FUNC} { // found function|procedure
731  yyextra->vhdlKeyDict.clear();
732  yyextra->funcProto.resize(0);
733  yyextra->isProto=false;
734  yyextra->funcProto.append(yytext);
735  yyextra->braceCount=1;
736  BEGIN(ParseType);
737  }
738 
739 <Bases>^{B}*("entity"|"package"){BN}+ {
740  appStringLower(yyextra->prevString,yytext);
741  writeFont(yyscanner,"keywordflow",yytext);
742  yyextra->isPackageBody=false;
743  BEGIN(ClassesName);
744  }
745 
746 <Bases>"end"{BN}+"architecture"{BN}+{FUNCNAME} {
747  codifyLines(yyscanner,yytext,yyextra->currClass,true);
748  yyextra->currArch = false;
749  }
750 <Bases>"end"{BN}+{FUNCNAME} {
751  if (yyextra->currArch)
752  {
753  codifyLines(yyscanner,yytext,yyextra->currClass,true);
754  yyextra->currArch = false;
755  }
756  else
757  {
758  REJECT;
759  }
760  }
761 <Bases>"end" {
762  appStringLower(yyextra->prevString,yytext);
763  QCString temp(yytext);
764  temp=temp.stripWhiteSpace();
765 
766  writeColoredWord(yyscanner,temp);
767  BEGIN(End);
768  }
769 <End>{ID} {
770  appStringLower(yyextra->prevString,yytext);
771  QCString temp(yytext);
772  temp=temp.stripWhiteSpace();
773 
774  if (!writeColoredWord(yyscanner,temp))
775  {
776  generateClassOrGlobalLink(yyscanner,*yyextra->code,temp);
777  }
778  }
779 <End>";" {
780  codifyLines(yyscanner,yytext);
781  BEGIN(Bases);
782  }
783 <Bases>{KEYWORD} { // found keyword
784  QCString qcs(yytext);
785  if (!writeColoredWord(yyscanner,qcs))
786  {
787  startFontClass(yyscanner,"vhdlchar");
788  yyextra->code->codify(yytext);
789  endFontClass(yyscanner);
790  }
791  }
792 
793 
794 <Bases>{ID} {
795  appStringLower(yyextra->prevString,yytext);
796  QCString temp(yytext);
797  temp=temp.stripWhiteSpace();
798 
799  if (!writeColoredWord(yyscanner,temp))
800  {
801  startFontClass(yyscanner,"vhdlchar");
802  generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp);
803  endFontClass(yyscanner);
804  }
805  }
806 
807 <Bases,ParseComponent>{DIGITSS} {
808  startFontClass(yyscanner,"vhdllogic");
809  codifyLines(yyscanner,yytext);
810  endFontClass(yyscanner);
811  }
812 
813 <Bases>^{B}*("use"){BN}+("entity"|"component")[^\n]* {
814  codifyLines(yyscanner,yytext,yyextra->currClass,true);
815  }
816 
817 
818 <Bases>{TYPEKW} {
819  codifyLines(yyscanner,yytext);
820  if (yyextra->isFuncProto)
821  {
822  BEGIN(ParseFuncProto);
823  }
824  else
825  {
826  BEGIN(Bases);
827  }
828  }
829 
830 <Bases>{OPERATOR} {
831  startFontClass(yyscanner,"vhdlchar");
832  yyextra->code->codify(yytext);
833  endFontClass(yyscanner);
834  }
835 
836 <Bases>","|"."|":"|"'"|"("|")" {
837  startFontClass(yyscanner,"vhdlchar");
838  yyextra->code->codify(yytext);
839  endFontClass(yyscanner);
840  }
841 
842 <Bases>{STRING} {
843  QCString qcs(yytext);
844  VhdlDocGen::deleteAllChars(qcs,'"');
845  VhdlDocGen::deleteAllChars(qcs,' ');
846 
847  if (VhdlDocGen::isNumber(qcs.str()))
848  {
849  writeFont(yyscanner,"vhdllogic",yytext);
850  }
851  else
852  {
853  writeFont(yyscanner,"keyword",yytext);
854  }
855  }
856 
857 <Bases>{B}*"#"[^\n]* {
858  writeFont(yyscanner,"keyword",yytext);
859  }
860 
861 <Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] {
862  writeWord(yyscanner,yytext);
863  //codifyLines(yyscanner,yytext,yyextra->currClass,true);
864  }
865 
866 <Bases>^{B}*"set_"[^\n]* {
867  writeWord(yyscanner,yytext);
868  }
869 
870 <*>\n {
871  codifyLines(yyscanner,yytext);
872  BEGIN(Bases);
873  }
874 
875 <*>[\x80-\xFF]* { // keep utf8 characters together...
876  yyextra->code->codify(yytext);
877  }
878 <*>. {
879  yyextra->code->codify(yytext);
880  }
881 
882 <*>\n{TEXTT} { // found normal or special comment on its own line
883  QCString text(yytext);
884  int i=text.find("--");
885  if (text.mid(i,3)=="--!") // && // hide special comment
886  {
887  if (!Config_getBool(STRIP_CODE_COMMENTS))
888  {
889  codifyLines(yyscanner,text,0,false,true);
890  }
891  else yyextra->yyLineNr++; // skip complete line, but count line
892  }
893  else // normal comment
894  {
895  codifyLines(yyscanner,text,0,false,true);
896  }
897  }
898 <*>{TEXTT} { // found normal or special comment after something
899  QCString text(yytext);
900  int i=text.find("--");
901  if (text.mid(i,3)=="--!")
902  {
903  // hide special comment
904  if (!Config_getBool(STRIP_CODE_COMMENTS))
905  {
906  codifyLines(yyscanner,text,0,false,true);
907  }
908  }
909  else // normal comment
910  {
911  codifyLines(yyscanner,text,0,false,true);
912  }
913  }
914 
915 %%
916 
917 /*@ ----------------------------------------------------------------------------
918  */
919 
920 static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size)
921 {
922  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
923  yy_size_t inputPosition = yyextra->inputPosition;
924  const char *s = yyextra->inputString + inputPosition;
925  yy_size_t c=0;
926  while( c < max_size && *s)
927  {
928  *buf++ = *s++;
929  c++;
930  }
931  yyextra->inputPosition += c;
932  return c;
933 }
934 
935 static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor)
936 {
937  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
938  if (Doxygen::searchIndex)
939  {
940  if (yyextra->searchCtx)
941  {
942  yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false);
943  }
944  else
945  {
946  yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true);
947  }
948  }
949 }
950 
951 static bool checkVhdlString(yyscan_t yyscanner,QCString &name)
952 {
953  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
954  if (name.isEmpty()) return false;
955 
956  int len=name.length();
957  if (name.at(0)=='"' && name.at(len-1)=='"' && len > 2)
958  {
959  std::string inside = name.str().substr(1,len-2);
960  static const reg::Ex regg(R"(\s+)"); // any number of whitespace
961  auto qrl=split(inside,regg);
962  if (VhdlDocGen::isNumber(qrl[0]))
963  {
964  yyextra->code->codify("\"");
965  startFontClass(yyscanner,"vhdllogic");
966  yyextra->code->codify(inside.c_str());
967  endFontClass(yyscanner);
968  yyextra->code->codify("\"");
969  }
970  else
971  {
972  startFontClass(yyscanner,"keyword");
973  yyextra->code->codify(name);
974  endFontClass(yyscanner);
975  }
976  return true;
977  }
978 
979  if (VhdlDocGen::isNumber(name.str()))
980  {
981  startFontClass(yyscanner,"vhdllogic");
982  yyextra->code->codify(name);
983  endFontClass(yyscanner);
984  return true;
985  }
986  return false;
987 }
988 
989 static void addToSearchIndex(yyscan_t yyscanner,const QCString &text)
990 {
991  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
992  if (Doxygen::searchIndex)
993  {
994  yyextra->code->addWord(text,false);
995  }
996 }
997 
998 
999 /*! start a new line of code, inserting a line number if yyextra->sourceFileDef
1000  * is true. If a definition starts at the current line, then the line
1001  * number is linked to the documentation of that definition.
1002  */
1003 static void startCodeLine(yyscan_t yyscanner)
1004 {
1005  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1006  //if (yyextra->currentFontClass) { yyextra->code->endFontClass(); }
1007  if (yyextra->sourceFileDef)
1008  {
1009  //QCString lineNumber,lineAnchor;
1010  //lineNumber.sprintf("%05d",yyextra->yyLineNr);
1011  //lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
1012  // if ((yyextra->yyLineNr % 500) == 0)
1013  // fprintf(stderr,"\n starting Line %d:",yyextra->yyLineNr);
1014  const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr);
1015  //printf("startCodeLine %d d=%s\n", yyextra->yyLineNr,qPrint(d ? d->name()) : "<null>");
1016  if (!yyextra->includeCodeFragment && d)
1017  {
1018  yyextra->currentDefinition = d;
1019  yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr);
1020  if (!yyextra->tempComp.isEmpty() && yyextra->currentMemberDef )
1021  {
1022  //ClassDef *cf=VhdlDocGen::getClass(yyextra->tempComp);
1023  QCString nn=yyextra->currentMemberDef->name();
1024  const MemberDef* mdeff=VhdlDocGen::findMember(yyextra->tempComp,nn);
1025  if (mdeff)
1026  {
1027  yyextra->currentMemberDef=mdeff;
1028  }
1029  }
1030 
1031  QCString lineAnchor;
1032  lineAnchor.sprintf("l%05d",yyextra->yyLineNr);
1033  if (yyextra->currentMemberDef)
1034  {
1035  yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(),
1036  yyextra->currentMemberDef->getOutputFileBase(),
1037  yyextra->currentMemberDef->anchor(),yyextra->yyLineNr,
1038  !yyextra->includeCodeFragment);
1039  setCurrentDoc(yyscanner,lineAnchor);
1040  }
1041  else if (d->isLinkableInProject())
1042  {
1043  yyextra->code->writeLineNumber(d->getReference(),
1044  d->getOutputFileBase(),
1045  QCString(),yyextra->yyLineNr,
1046  !yyextra->includeCodeFragment);
1047  setCurrentDoc(yyscanner,lineAnchor);
1048  }
1049  }
1050  else
1051  {
1052  yyextra->code->writeLineNumber(QCString(),QCString(),QCString(),yyextra->yyLineNr,
1053  !yyextra->includeCodeFragment);
1054  }
1055  }
1056  yyextra->code->startCodeLine(yyextra->sourceFileDef);
1057  yyextra->startCode=true;
1058  if (yyextra->currentFontClass)
1059  {
1060  yyextra->code->startFontClass(yyextra->currentFontClass);
1061  }
1062 }
1063 
1064 static void endCodeLine(yyscan_t yyscanner)
1065 {
1066  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1067  endFontClass(yyscanner);
1068  yyextra->code->endCodeLine();
1069 }
1070 
1071 static void nextCodeLine(yyscan_t yyscanner)
1072 {
1073  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1074  if (yyextra->startCode)
1075  {
1076  endCodeLine(yyscanner); // </div>
1077  }
1078  const char *fc = yyextra->currentFontClass;
1079  if (yyextra->yyLineNr<yyextra->inputLines)
1080  {
1081  yyextra->currentFontClass = fc;
1082  startCodeLine(yyscanner); //<div>
1083  }
1084 }
1085 
1086 /*! writes a word to the output.
1087  * If curr_class is defined, the word belongs to a class
1088  * and will be linked.
1089  */
1090 
1091 static void writeWord(yyscan_t yyscanner,const QCString &word,const QCString &curr_class,bool classLink)
1092 {
1093  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1094  bool found=false;
1095  QCString temp;
1096  QCString tclass(curr_class);
1097  QCString ttt(word);
1098  if (ttt.isEmpty()) return;
1099  for (unsigned int j=0;j<ttt.length();j++)
1100  {
1101  char c=ttt.at(j);
1102  if (c==' '|| c==',' || c==';' || c==':' || c=='(' || c==')' || c=='\r' || c=='\t' || c=='.')
1103  {
1104  if (found)
1105  {
1106  if (!writeColoredWord(yyscanner,temp)) // is it a keyword ?
1107  {
1108  //if (VhdlDocGen::findKeyWord(temp))
1109  // writeFont(yyscanner,"vhdlkeyword",temp);
1110  //printf("writeWord: %s\n",qPrint(temp));
1111  if (!tclass.isEmpty())
1112  {
1113  if (!classLink)
1114  {
1115  generateMemLink(yyscanner,*yyextra->code,tclass,temp);
1116  }
1117  else
1118  {
1119  generateClassOrGlobalLink(yyscanner,*yyextra->code,temp,false,curr_class);
1120  }
1121  }
1122  else
1123  {
1124  if (!checkVhdlString(yyscanner,temp))
1125  {
1126  yyextra->code->codify(temp);
1127  }
1128  }
1129  }
1130  temp.resize(0);
1131  found=false;
1132  }
1133 
1134  char cc[2];
1135  cc[0]=c;
1136  cc[1]=0;
1137  yyextra->code->codify(cc);
1138  }
1139  else
1140  {
1141  found=true;
1142  temp+=c;
1143  }
1144  } // for
1145 
1146  if (!temp.isEmpty())
1147  {
1148  if (!writeColoredWord(yyscanner,temp))
1149  {
1150  if (!tclass.isEmpty())
1151  {
1152  if (!classLink)
1153  {
1154  generateMemLink(yyscanner,*yyextra->code,tclass,temp); // generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,left);
1155  }
1156  else
1157  {
1158  generateClassOrGlobalLink(yyscanner,*yyextra->code,temp,false,curr_class);
1159  }
1160  }
1161  else
1162  {
1163  QCString qc(temp);
1164  if (VhdlDocGen::isNumber(qc.str()))
1165  {
1166  startFontClass(yyscanner,"vhdllogic");
1167  yyextra->code->codify(temp);
1168  endFontClass(yyscanner);
1169  }
1170  else
1171  {
1172  yyextra->code->codify(temp);
1173  }
1174  }
1175  }
1176  }
1177 }// writeWord
1178 
1179 
1180 /*! write a code fragment 'text' that may span multiple lines, inserting
1181  * line numbers for each line.
1182  */
1183 static void codifyLines(yyscan_t yyscanner,const QCString &text,const QCString &cl,bool classlink,bool comment)
1184 {
1185  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1186  if (text.isEmpty()) return;
1187  //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text);
1188  const char *p=text.data(),*sp=p;
1189  char c;
1190  bool done=false;
1191  while (!done)
1192  {
1193  sp=p;
1194  while ((c=*p++) && c!='\n') {}
1195  if (c=='\n')
1196  {
1197  yyextra->yyLineNr++;
1198  QCString line = sp;
1199  line = line.left((int)(p-sp)-1);
1200  if (comment)
1201  {
1202  writeFont(yyscanner,"comment",line);
1203  }
1204  else
1205  {
1206  writeWord(yyscanner,line,cl,classlink);
1207  }
1208  nextCodeLine(yyscanner);
1209  }
1210  else
1211  {
1212  if (comment)
1213  {
1214  writeFont(yyscanner,"comment",sp);
1215  }
1216  else
1217  {
1218  writeWord(yyscanner,sp,cl,classlink);
1219  }
1220  done=true;
1221  }
1222  }
1223 }
1224 
1225 /*! writes a link to a fragment \a text that may span multiple lines, inserting
1226  * line numbers for each line. If \a text contains newlines, the link will be
1227  * split into multiple links with the same destination, one for each line.
1228  */
1229 static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol,
1230  const Definition *d,
1231  const QCString &text)
1232 {
1233  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1234  if (text.isEmpty()) return;
1235  static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
1236  yyextra->tooltipManager.addTooltip(ol,d);
1237  QCString ref = d->getReference();
1238  QCString file = d->getOutputFileBase();
1239  QCString anchor = d->anchor();
1240  QCString tooltip;
1241  if (!sourceTooltips) // fall back to simple "title" tooltips
1242  {
1243  tooltip = d->briefDescriptionAsTooltip();
1244  }
1245  bool done=false;
1246  const char *p=text.data();
1247  while (!done)
1248  {
1249  const char *sp=p;
1250  char c;
1251  while ((c=*p++) && c!='\n') {}
1252  if (c=='\n')
1253  {
1254  yyextra->yyLineNr++;
1255  // printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
1256  ol.writeCodeLink(d->codeSymbolType(),ref,file,anchor,QCString(sp,p-sp-1),tooltip);
1257  nextCodeLine(yyscanner);
1258  }
1259  else
1260  {
1261  ol.writeCodeLink(d->codeSymbolType(),ref,file,anchor,sp,tooltip);
1262  done=true;
1263  }
1264  }
1265 }
1266 
1267 /*! writes a link to a function or procedure
1268  */
1269 static void generateFuncLink(yyscan_t yyscanner,CodeOutputInterface &ol,const MemberDef* mdef)
1270 {
1271  //printf("generateFuncLink(FuncName=%s)\n",qPrint(mdef->name()));
1272  QCString memberName=mdef->name();
1273 
1274  if (mdef->isLinkable()) // is it a linkable class
1275  {
1276  writeMultiLineCodeLink(yyscanner,ol,mdef,mdef->name());
1277  addToSearchIndex(yyscanner,memberName);
1278  return;
1279  }
1280  codifyLines(yyscanner,memberName);
1281  addToSearchIndex(yyscanner,memberName);
1282 } // generateFuncLink
1283 
1284 
1285 static void generateMemLink(yyscan_t yyscanner,CodeOutputInterface &ol,QCString &clName,QCString& memberName)
1286 {
1287  if (memberName.isEmpty()) return;
1288  if (clName.isEmpty())
1289  {
1290  codifyLines(yyscanner,memberName);
1291 
1292  return;
1293  }
1294 
1295  QCString className=clName;
1296 
1297  //MemberDef *comp=0;
1298  //bool isLocal=false;
1299 
1300  const MemberDef *md=VhdlDocGen::findMember(className,memberName);
1301  ClassDef *po=VhdlDocGen::getClass(className);
1302 
1303  if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS)
1304  {
1305  QCString temp=className;//.stripPrefix("_");
1306  temp.stripPrefix("_");
1307  md=VhdlDocGen::findMember(temp,memberName);
1308  }
1309 
1310  if (md && md->isLinkable()) // is it a linkable class
1311  {
1312  writeMultiLineCodeLink(yyscanner,ol,md,memberName);
1313  addToSearchIndex(yyscanner,memberName);
1314  return;
1315  }
1316  // nothing found, just write out the word
1317  codifyLines(yyscanner,memberName);
1318  addToSearchIndex(yyscanner,memberName);
1319 }// generateMemLink
1320 
1321 
1322 static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,
1323  const QCString &clName, bool /*typeOnly*/, const QCString &curr_class)
1324 {
1325  QCString className=clName;
1326 
1327  if (className.isEmpty()) return;
1328 
1329  ClassDef *cd=0;
1330  //MemberDef *md=0;
1331  //bool isLocal=false;
1332  className.stripPrefix("_");
1333  cd = getClass(className);
1334  if (!cd && !curr_class.isEmpty())
1335  {
1336  QCString cls = curr_class;
1337  QCString suffix = "::";
1338  suffix+=clName;
1339  if (cls.right(suffix.length())==suffix)
1340  {
1341  cd = getClass(curr_class);
1342  }
1343  }
1344 
1345  while (cd)
1346  {
1347  //className.stripPrefix("_");
1348  QCString temp(clName);
1349  temp.stripPrefix("_");
1350  if (cd && cd->isLinkable()) // is it a linkable class
1351  {
1352  //if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS)
1353  //{
1354  // temp=VhdlDocGen::getClassName(cd);
1355  //}
1356  writeMultiLineCodeLink(yyscanner,ol,cd,temp);
1357  addToSearchIndex(yyscanner,className);
1358  return;
1359  }
1360  Definition *d = cd->getOuterScope();
1361  if (d && d->definitionType()==Definition::TypeClass)
1362  {
1363  cd = toClassDef(d);
1364  }
1365  else
1366  {
1367  cd = 0;
1368  }
1369  }
1370 
1371  // nothing found, just write out the word
1372  codifyLines(yyscanner,clName);
1373  addToSearchIndex(yyscanner,clName);
1374 }// generateClasss or global link
1375 
1376 
1377 /*! counts the number of lines in the input */
1378 static int countLines(yyscan_t yyscanner)
1379 {
1380  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1381  const char *p=yyextra->inputString;
1382  char c;
1383  int count=1;
1384  while ((c=*p))
1385  {
1386  p++ ;
1387  if (c=='\n') count++;
1388  }
1389  if (p>yyextra->inputString && *(p-1)!='\n')
1390  { // last line does not end with a \n, so we add an extra
1391  // line and explicitly terminate the line after parsing.
1392  count++,
1393  yyextra->needsTermination=true;
1394  }
1395  return count;
1396 }
1397 
1398 static void endFontClass(yyscan_t yyscanner)
1399 {
1400  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1401  if (yyextra->currentFontClass)
1402  {
1403  yyextra->code->endFontClass();
1404  yyextra->currentFontClass=0;
1405  }
1406 }
1407 
1408 static void startFontClass(yyscan_t yyscanner,const char *s)
1409 {
1410  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1411  if (s==0) return;
1412  endFontClass(yyscanner);
1413  yyextra->code->startFontClass(s);
1414  yyextra->currentFontClass=s;
1415 }
1416 
1417 static void writeFont(yyscan_t yyscanner,const char *s,const QCString &text)
1418 {
1419  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1420  if (s==0 || text.isEmpty()) return;
1421  //printf("writeFont(yyscanner,%d,\"%s\")\n",yyextra->yyLineNr,text);
1422  yyextra->code->startFontClass(s);
1423  yyextra->code->codify(text);
1424  yyextra->code->endFontClass();
1425 }
1426 
1427 //----------------------------------------------------------------------------
1428 
1429 static void appStringLower(QCString& qcs,const char* text)
1430 {
1431  qcs.resize(0);
1432  qcs.append(text);
1433  qcs=qcs.stripWhiteSpace();
1434 }
1435 
1436 /* writes and links a port map statement */
1437 static void codifyMapLines(yyscan_t yyscanner,const QCString &text)
1438 {
1439  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1440  if (text.isEmpty()) return;
1441  QCString temp;
1442  //bool dot=false;
1443  int wordCounter=0;
1444  QCString ctemp;
1445  //printf("codifyMapLines(%d,\"%s\")\n",yyextra->yyLineNr,qPrint(text));
1446  const char *p=text.data();
1447  char c;
1448  bool done=false;
1449  while (!done)
1450  {
1451  //sp=p;
1452  while ((c=*p++) && c!='\n' && c!=':' && c != ' ' && c != '(' && c!='\0' && c!='\t')
1453  {
1454  if (c!=0x9)
1455  temp+=c;
1456  }
1457  if (c=='\0') return;
1458  if (!temp.isEmpty()) wordCounter++;
1459 
1460  if (!temp.isEmpty())
1461  {
1462  // different kinds of component instantiations
1463  // xxx:yyy (generic/port) map(
1464  // xxx:(entity/component/configuration) yyy (generic/port) map(
1465  // xxx: entity yyy(zzz) (generic/port) map(
1466  if (wordCounter==2 || wordCounter==3)
1467  {
1468  QCString q=temp.lower(); // consider (upper/lower) cases
1469  if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic")
1470  {
1471  generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp);
1472  }
1473  else
1474  {
1475  yyextra->PortMapComp=temp;
1476  generateClassOrGlobalLink(yyscanner,*yyextra->code,temp);
1477  }
1478  }
1479  else
1480  {
1481  generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp);
1482  }
1483  }
1484  ctemp.fill(c,1);
1485  codifyLines(yyscanner,ctemp);
1486  ctemp.resize(0);
1487  temp.resize(0);
1488  }//while
1489 }//codifyMapLines
1490 
1491 /*
1492 * writes a function|procedure prototype and links the function|procedure name
1493 */
1494 
1495 static void writeFuncProto(yyscan_t yyscanner)
1496 {
1497  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1498  QCString name,ret;
1499  VhdlDocGen::parseFuncProto(yyextra->funcProto,name,ret,false);
1500 
1501  if (name.isEmpty())
1502  {
1503  codifyLines(yyscanner,yyextra->funcProto,yyextra->currClass);
1504  return;
1505  }
1506  StringVector qlist=split(yyextra->funcProto.str(),name.str());
1507  QCString temp(qlist[0]);
1508  codifyLines(yyscanner,temp,yyextra->currClass);
1509  yyextra->funcProto.stripPrefix(temp);
1510  temp.resize(0);
1511  temp=yyextra->currClass;
1512  if (yyextra->isPackageBody)
1513  {
1514  temp.stripPrefix("_");// _{package body name}
1515  }
1516  const MemberDef *mdef=VhdlDocGen::findFunction(name,temp);
1517 
1518  if (mdef)
1519  {
1520  generateFuncLink(yyscanner,*yyextra->code,mdef);
1521  yyextra->funcProto.stripPrefix(name);
1522  codifyLines(yyscanner,yyextra->funcProto,yyextra->currClass);
1523  }
1524  else
1525  {
1526  codifyLines(yyscanner,yyextra->funcProto,yyextra->currClass);
1527  }
1528 }// writeFuncProto
1529 
1530 /* writes a process prototype to the output */
1531 
1532 static void writeProcessProto(yyscan_t yyscanner)
1533 {
1534  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1535  codifyLines(yyscanner,yyextra->funcProto,yyextra->currClass);
1536  yyextra->vhdlKeyDict.clear();
1537 }// writeProcessProto
1538 
1539 /* writes a keyword */
1540 
1541 static bool writeColoredWord(yyscan_t yyscanner,QCString& word )
1542 {
1543  QCString qcs=word.lower();
1544  const char *ss=VhdlDocGen::findKeyWord(qcs);
1545  if (ss)
1546  {
1547  writeFont(yyscanner,ss,word);
1548  return true;
1549  }
1550  return false;
1551 }
1552 
1553 //-----------------------------------------------------------------------------------
1554 
1555 struct VHDLCodeParser::Private
1556 {
1557  yyscan_t yyscanner;
1558  vhdlcodeYY_state state;
1559 };
1560 
1561 VHDLCodeParser::VHDLCodeParser() : p(std::make_unique<Private>())
1562 {
1563  vhdlcodeYYlex_init_extra(&p->state,&p->yyscanner);
1564 #ifdef FLEX_DEBUG
1565  vhdlcodeYYset_debug(1,p->yyscanner);
1566 #endif
1567  resetCodeParserState();
1568 }
1569 
1570 VHDLCodeParser::~VHDLCodeParser()
1571 {
1572  vhdlcodeYYlex_destroy(p->yyscanner);
1573 }
1574 
1575 void VHDLCodeParser::resetCodeParserState()
1576 {
1577  p->state.vhdlKeyDict.clear();
1578 }
1579 
1580 void VHDLCodeParser::parseCode(CodeOutputInterface &od,
1581  const QCString &className,
1582  const QCString &s,
1583  SrcLangExt,
1584  bool exBlock,
1585  const QCString &exName,
1586  const FileDef *fd,
1587  int startLine,
1588  int endLine,
1589  bool inlineFragment,
1590  const MemberDef *memberDef,
1591  bool,
1592  const Definition *searchCtx,
1593  bool /* collectXRefs */)
1594 {
1595  yyscan_t yyscanner = p->yyscanner;
1596  struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1597  //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
1598  if (s.isEmpty()) return;
1599  printlex(yy_flex_debug, true, __FILE__, fd ? qPrint(fd->fileName()): NULL);
1600  if (memberDef)
1601  {
1602  const ClassDef *dd=memberDef->getClassDef();
1603  if (dd) yyextra->currClass=dd->name();
1604  }
1605  resetCodeParserState();
1606  yyextra->code = &od;
1607  yyextra->inputString = s.data();
1608  yyextra->inputPosition = 0;
1609  yyextra->currentFontClass = 0;
1610  yyextra->needsTermination = false;
1611  yyextra->searchCtx = searchCtx;
1612 
1613  if (startLine!=-1)
1614  yyextra->yyLineNr = startLine;
1615  else
1616  yyextra->yyLineNr = 1;
1617 
1618  if (endLine!=-1)
1619  yyextra->inputLines = endLine+1;
1620  else
1621  yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1;
1622 
1623 
1624  // yyextra->theCallContext.clear();
1625  yyextra->exampleBlock = exBlock;
1626  yyextra->exampleName = exName;
1627  yyextra->sourceFileDef = fd;
1628  bool cleanupSourceDef = false;
1629  if (exBlock && fd==0)
1630  {
1631  // create a dummy filedef for the example
1632  yyextra->sourceFileDef = createFileDef("",exName);
1633  cleanupSourceDef = true;
1634  }
1635  if (yyextra->sourceFileDef)
1636  {
1637  setCurrentDoc(yyscanner,"l00001");
1638  }
1639  yyextra->currentDefinition = 0;
1640  yyextra->currentMemberDef = 0;
1641  yyextra->vhdlMember=0;
1642  if (!yyextra->exampleName.isEmpty())
1643  {
1644  yyextra->exampleFile = convertNameToFile(yyextra->exampleName+"-example");
1645  }
1646  yyextra->includeCodeFragment = inlineFragment;
1647  startCodeLine(yyscanner);
1648  if (!yyextra->lexInit)
1649  {
1650  VhdlDocGen::init();
1651  yyextra->lexInit=true;
1652  }
1653  /*int iLine=*/countLines(yyscanner);
1654  vhdlcodeYYrestart( 0, yyscanner );
1655  BEGIN( Bases );
1656  vhdlcodeYYlex(yyscanner);
1657  if (yyextra->needsTermination)
1658  {
1659  endCodeLine(yyscanner);
1660  }
1661  if (cleanupSourceDef)
1662  {
1663  // delete the temporary file definition used for this example
1664  delete yyextra->sourceFileDef;
1665  yyextra->sourceFileDef=0;
1666  }
1667  yyextra->startCode=false;
1668 
1669  // write the tooltips
1670  yyextra->tooltipManager.writeTooltips(od);
1671 
1672  printlex(yy_flex_debug, false, __FILE__, fd ? qPrint(fd->fileName()): NULL);
1673 }
1674 
1675 #if USE_STATE2STRING
1676 #include "vhdlcode.l.h"
1677 #endif
1678