Imported Upstream version 1.8.15
[platform/upstream/doxygen.git] / src / fortrancode.l
1 /******************************************************************************
2  *
3  * Parser for syntax highlighting and references for Fortran90 F subset
4  *
5  * Copyright (C) by Anke Visser
6  * based on the work of Dimitri van Heesch.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation under the terms of the GNU General Public License is hereby 
10  * granted. No representations are made about the suitability of this software 
11  * for any purpose. It is provided "as is" without express or implied warranty.
12  * See the GNU General Public License for more details.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18
19 /**
20  @todo - continutation lines not always recognized
21        - merging of use-statements with same module name and different only-names
22        - rename part of use-statement
23        - links to interface functions 
24        - references to variables
25 **/
26 %option never-interactive
27 %option case-insensitive
28 %option prefix="fortrancodeYY"
29
30 %{
31
32 /*
33  *      includes
34  */
35 #include <stdio.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <qregexp.h>
39 #include <qdir.h>
40 #include <qcstringlist.h>
41 #include "entry.h"
42 #include "doxygen.h"
43 #include "message.h"
44 #include "outputlist.h"
45 #include "util.h"
46 #include "membername.h"
47 #include "searchindex.h"
48 #include "defargs.h"
49 #include "memberlist.h"
50 #include "config.h"
51 #include "groupdef.h"
52 #include "classlist.h"
53 #include "filedef.h"
54 #include "namespacedef.h"
55 #include "tooltip.h"
56 #include "fortrancode.h"
57
58 // Toggle for some debugging info
59 //#define DBG_CTX(x) fprintf x
60 #define DBG_CTX(x) do { } while(0)
61
62 #define YY_NO_TOP_STATE 1
63 #define YY_NO_INPUT 1
64 #define YY_NO_UNISTD_H 1
65
66 /*
67  * For fixed formatted code position 6 is of importance (continuation character).
68  * The following variables and macros keep track of the column number
69  * YY_USER_ACTION is always called for each scan action
70  * YY_FTN_RESET   is used to handle end of lines and reset the column counter
71  * YY_FTN_REJECT  resets the column counters when a pattern is rejected and thus rescanned.
72  */
73 int yy_old_start = 0;
74 int yy_my_start  = 0;
75 int yy_end       = 1;
76 #define YY_USER_ACTION {yy_old_start = yy_my_start; yy_my_start = yy_end; yy_end += yyleng;}
77 #define YY_FTN_RESET   {yy_old_start = 0; yy_my_start = 0; yy_end = 1;}
78 #define YY_FTN_REJECT  {yy_end = yy_my_start; yy_my_start = yy_old_start; REJECT;}
79    
80 //--------------------------------------------------------------------------------
81
82 /**
83   data of an use-statement
84 */
85 class UseEntry 
86 {
87  public: 
88    QCString module; // just for debug
89    QCStringList onlyNames;   /* entries of the ONLY-part */
90 };
91
92 /**
93   module name -> list of ONLY/remote entries
94   (module name = name of the module, which can be accessed via use-directive)
95 */
96 class UseSDict : public SDict<UseEntry> 
97 {
98   public:
99     UseSDict() : SDict<UseEntry>(17) {}
100 };
101
102 /**
103   Contains names of used modules and names of local variables.
104 */
105 class Scope 
106 {
107   public:
108     QCStringList useNames; //!< contains names of used modules
109     QDict<void> localVars; //!< contains names of local variables
110     QDict<void> externalVars; //!< contains names of external entities
111
112     Scope() : localVars(7, FALSE /*caseSensitive*/), externalVars(7, FALSE /*caseSensitive*/) {}
113 };
114
115 /*===================================================================*/
116 /* 
117  *      statics
118  */
119   
120 static QCString  docBlock;                   //!< contents of all lines of a documentation block
121 static QCString  currentModule=0;            //!< name of the current enclosing module
122 static QCString  currentClass=0;             //!< name of the current enclosing class
123 static UseSDict  *useMembers= new UseSDict;  //!< info about used modules
124 static UseEntry  *useEntry = 0;              //!< current use statement info
125 static QList<Scope> scopeStack;
126 static bool      g_isExternal = false;
127 // static QCStringList *currentUseNames= new QCStringList; //! contains names of used modules of current program unit
128 static QCString str="";         //!> contents of fortran string
129
130 static CodeOutputInterface * g_code;
131
132 // TODO: is this still needed? if so, make it work
133 static QCString      g_parmType;
134 static QCString      g_parmName;
135
136 static const char *  g_inputString;     //!< the code fragment as text
137 static int           g_inputPosition;   //!< read offset during parsing 
138 static int           g_inputLines;      //!< number of line in the code fragment
139 static int           g_yyLineNr;        //!< current line number
140 static int           g_contLineNr;      //!< current, local, line number for continuation determination
141 static int          *g_hasContLine = NULL;     //!< signals whether or not a line has a continuation line (fixed source form)
142 static bool          g_needsTermination;
143 static Definition   *g_searchCtx;
144 static bool          g_collectXRefs;
145 static bool          g_isFixedForm;
146
147 static bool          g_insideBody;      //!< inside subprog/program body? => create links
148 static const char *  g_currentFontClass;
149
150 static bool          g_exampleBlock;
151 static QCString      g_exampleName;
152 static QCString      g_exampleFile;
153
154 static FileDef *     g_sourceFileDef;
155 static Definition *  g_currentDefinition;
156 static MemberDef *   g_currentMemberDef;
157 static bool          g_includeCodeFragment;
158
159 static char          stringStartSymbol; // single or double quote
160 // count in variable declaration to filter out
161 //  declared from referenced names
162 static int           bracketCount = 0;
163
164 // signal when in type / class /procedure declaration
165 static int           inTypeDecl = 0;
166
167 static bool      g_endComment;
168
169 static void endFontClass()
170 {
171   if (g_currentFontClass)
172   {
173     g_code->endFontClass();
174     g_currentFontClass=0;
175   }
176 }
177
178 static void startFontClass(const char *s)
179 {
180   // if font class is already set don't stop and start it.
181   // strcmp does not like null pointers as input.
182   if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s))
183   {
184     endFontClass();
185     g_code->startFontClass(s);
186     g_currentFontClass=s;
187   }
188 }
189
190 static void setCurrentDoc(const QCString &anchor)
191 {
192   if (Doxygen::searchIndex)
193   {
194     if (g_searchCtx)
195     {
196       Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE);
197     }
198     else
199     {
200       Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE);
201     }
202   }
203 }
204
205 static void addToSearchIndex(const char *text)
206 {
207   if (Doxygen::searchIndex)
208   {
209     Doxygen::searchIndex->addWord(text,FALSE);
210   }
211 }
212
213 /*! start a new line of code, inserting a line number if g_sourceFileDef
214  * is TRUE. If a definition starts at the current line, then the line
215  * number is linked to the documentation of that definition.
216  */
217 static void startCodeLine()
218 {
219   if (g_sourceFileDef)
220   {
221     //QCString lineNumber,lineAnchor;
222     //lineNumber.sprintf("%05d",g_yyLineNr);
223     //lineAnchor.sprintf("l%05d",g_yyLineNr);
224    
225     Definition *d   = g_sourceFileDef->getSourceDefinition(g_yyLineNr);
226     //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>");
227     if (!g_includeCodeFragment && d)
228     {
229       g_currentDefinition = d;
230       g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr);
231       g_insideBody = FALSE;
232       g_endComment = FALSE;
233       g_parmType.resize(0);
234       g_parmName.resize(0);
235       QCString lineAnchor;
236       lineAnchor.sprintf("l%05d",g_yyLineNr);
237       if (g_currentMemberDef)
238       {
239         g_code->writeLineNumber(g_currentMemberDef->getReference(),
240                                 g_currentMemberDef->getOutputFileBase(),
241                                 g_currentMemberDef->anchor(),g_yyLineNr);
242         setCurrentDoc(lineAnchor);
243       }
244       else if (d->isLinkableInProject())
245       {
246         g_code->writeLineNumber(d->getReference(),
247                                 d->getOutputFileBase(),
248                                 0,g_yyLineNr);
249         setCurrentDoc(lineAnchor);
250       }
251     }
252     else
253     {
254       g_code->writeLineNumber(0,0,0,g_yyLineNr);
255     }
256   }
257   g_code->startCodeLine(g_sourceFileDef); 
258   if (g_currentFontClass)
259   {
260     g_code->startFontClass(g_currentFontClass);
261   }
262 }
263
264
265 static void endFontClass();
266 static void endCodeLine()
267 {
268   endFontClass();
269   g_code->endCodeLine();
270 }
271
272 /*! write a code fragment `text' that may span multiple lines, inserting
273  * line numbers for each line.
274  */
275 static void codifyLines(char *text)
276 {
277   //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text);
278   char *p=text,*sp=p;
279   char c;
280   bool done=FALSE;
281   const char *  tmp_currentFontClass = g_currentFontClass;
282   while (!done)
283   {
284     sp=p;
285     while ((c=*p++) && c!='\n') { }
286     if (c=='\n')
287     {
288       g_yyLineNr++;
289       *(p-1)='\0';
290       g_code->codify(sp);
291       endCodeLine();
292       if (g_yyLineNr<g_inputLines) 
293       {
294         startCodeLine();
295       }
296       if (tmp_currentFontClass)
297       {
298         startFontClass(tmp_currentFontClass);
299       }
300     }
301     else
302     {
303       g_code->codify(sp);
304       done=TRUE;
305     }
306   }
307 }
308
309 static void codifyLines(QCString str)
310 {
311   char *tmp= (char *) malloc(str.length()+1);
312   strcpy(tmp, str);
313   codifyLines(tmp);
314   free(tmp);
315 }
316
317 /*! writes a link to a fragment \a text that may span multiple lines, inserting
318  * line numbers for each line. If \a text contains newlines, the link will be 
319  * split into multiple links with the same destination, one for each line.
320  */
321 static void writeMultiLineCodeLink(CodeOutputInterface &ol,
322                   Definition *d,const char *text)
323 {
324   static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS);
325   TooltipManager::instance()->addTooltip(d);
326   QCString ref  = d->getReference();
327   QCString file = d->getOutputFileBase();
328   QCString anchor = d->anchor();
329   QCString tooltip; 
330   if (!sourceTooltips) // fall back to simple "title" tooltips
331   {
332     tooltip = d->briefDescriptionAsTooltip();
333   }
334   bool done=FALSE;
335   char *p=(char *)text;
336   while (!done)
337   {
338     char *sp=p;
339     char c;
340     while ((c=*p++) && c!='\n') { }
341     if (c=='\n')
342     {
343       g_yyLineNr++;
344       *(p-1)='\0';
345       //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
346       ol.writeCodeLink(ref,file,anchor,sp,tooltip);
347       endCodeLine();
348       if (g_yyLineNr<g_inputLines) 
349       {
350         startCodeLine();
351       }
352     }
353     else
354     {
355       //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp);
356       ol.writeCodeLink(ref,file,anchor,sp,tooltip);
357       done=TRUE;
358     }
359   }
360 }
361 //-------------------------------------------------------------------------------
362 /**
363   searches for definition of a module (Namespace)
364   @param mname the name of the module
365   @param cd the entry, if found or null
366   @returns true, if module is found
367 */
368 static bool getFortranNamespaceDefs(const QCString &mname,
369                                NamespaceDef *&cd)
370 {
371   if (mname.isEmpty()) return FALSE; /* empty name => nothing to link */
372
373   // search for module
374   if ((cd=Doxygen::namespaceSDict->find(mname))) return TRUE;
375
376   return FALSE;
377 }
378 //-------------------------------------------------------------------------------
379 /**
380   searches for definition of a type
381   @param tname the name of the type
382   @param moduleName name of enclosing module or null, if global entry
383   @param cd the entry, if found or null
384   @param useDict dictionary of data of USE-statement
385   @returns true, if type is found 
386 */
387 static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, 
388                                ClassDef *&cd, UseSDict *usedict=0)
389 {
390   if (tname.isEmpty()) return FALSE; /* empty name => nothing to link */
391
392   //cout << "=== search for type: " << tname << endl;
393
394   // search for type  
395   if ((cd=Doxygen::classSDict->find(tname))) 
396   {
397     //cout << "=== type found in global module" << endl;
398     return TRUE;
399   }
400   else if (moduleName && (cd= Doxygen::classSDict->find(moduleName+"::"+tname))) 
401   {
402     //cout << "=== type found in local module" << endl;
403     return TRUE;
404   }
405   else 
406   {
407     UseEntry *use;
408     for (UseSDict::Iterator di(*usedict); (use=di.current()); ++di)
409     {
410       if ((cd= Doxygen::classSDict->find(use->module+"::"+tname)))
411       {
412         //cout << "===  type found in used module" << endl;
413         return TRUE;
414       }
415     }
416   }
417
418   return FALSE;
419 }
420
421 /**
422   searches for definition of function memberName
423   @param memberName the name of the function/variable
424   @param moduleName name of enclosing module or null, if global entry
425   @param md the entry, if found or null
426   @param usedict array of data of USE-statement
427   @returns true, if found 
428 */
429 static bool getFortranDefs(const QCString &memberName, const QCString &moduleName, 
430                            MemberDef *&md, UseSDict *usedict=0)
431 {
432   if (memberName.isEmpty()) return FALSE; /* empty name => nothing to link */
433
434   // look in local variables
435   QListIterator<Scope> it(scopeStack);
436   Scope *scope;
437   for (it.toLast();(scope=it.current());--it)
438   {
439     if (scope->localVars.find(memberName) && (!scope->externalVars.find(memberName)))
440       return FALSE;
441   }
442
443   // search for function
444   MemberName *mn = Doxygen::functionNameSDict->find(memberName);
445   if (!mn)
446   {
447     mn = Doxygen::memberNameSDict->find(memberName);
448   }
449
450   if (mn) // name is known
451   {
452       MemberNameIterator mli(*mn);
453       for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name
454       {
455         FileDef  *fd=md->getFileDef();
456         GroupDef *gd=md->getGroupDef();
457         ClassDef *cd=md->getClassDef();
458
459  //cout << "found link with same name: " << fd->fileName() << "  " <<  memberName;
460  //if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl;
461
462         if ((gd && gd->isLinkable()) || (fd && fd->isLinkable()))
463         {
464            NamespaceDef *nspace= md->getNamespaceDef();
465
466            if (nspace == 0) 
467            { // found function in global scope
468              if(cd == 0) { // Skip if bound to type
469                 return TRUE;
470               }
471            }
472            else if (moduleName == nspace->name()) 
473            { // found in local scope
474              return TRUE;
475            }
476            else 
477            { // else search in used modules
478              QCString moduleName= nspace->name();
479              UseEntry *ue= usedict->find(moduleName);
480              if (ue) 
481              {
482                // check if only-list exists and if current entry exists is this list
483                QCStringList &only= ue->onlyNames;
484                if (only.isEmpty()) 
485                {
486                //cout << " found in module " << moduleName << " entry " << memberName <<  endl;
487                  return TRUE; // whole module used
488                }
489                else
490                {
491                  for ( QCStringList::Iterator it = only.begin(); it != only.end(); ++it)
492                  {
493                    //cout << " search in only: " << moduleName << ":: " << memberName << "==" << (*it)<<  endl;
494                    if (memberName == *it)
495                    {
496                      return TRUE; // found in ONLY-part of use list
497                    }
498                  }
499                }
500              }
501            }
502         } // if linkable
503       } // for
504   }
505   return FALSE;
506 }
507
508 /**
509  gets the link to a generic procedure which depends not on the name, but on the parameter list
510  @todo implementation
511 */
512 static bool getGenericProcedureLink(const ClassDef *cd, 
513                                     const char *memberText, 
514                                     CodeOutputInterface &ol) 
515 {
516   (void)cd;
517   (void)memberText;
518   (void)ol;
519   return FALSE;
520 }
521
522 static bool getLink(UseSDict *usedict, // dictonary with used modules
523                     const char *memberText,  // exact member text
524                     CodeOutputInterface &ol,
525                     const char *text)
526 {
527   MemberDef *md=0;
528   QCString memberName= removeRedundantWhiteSpace(memberText);
529
530   if (getFortranDefs(memberName, currentModule, md, usedict) && md->isLinkable())
531   { 
532     if (md->isVariable() && (md->getLanguage()!=SrcLangExt_Fortran)) return FALSE; // Non Fortran variables aren't handled yet,
533                                                                                    // see also linkifyText in util.cpp
534
535     Definition *d = md->getOuterScope()==Doxygen::globalScope ?
536                     md->getBodyDef() : md->getOuterScope();
537     if (md->getGroupDef()) d = md->getGroupDef();
538     if (d && d->isLinkable())
539     {
540       if (g_currentDefinition && g_currentMemberDef && 
541           md!=g_currentMemberDef && g_insideBody && g_collectXRefs)
542       { 
543         addDocCrossReference(g_currentMemberDef,md); 
544       }     
545       writeMultiLineCodeLink(ol,md,text ? text : memberText);
546       addToSearchIndex(text ? text : memberText);
547       return TRUE;
548     } 
549   }
550   return FALSE;
551 }
552
553
554 static void generateLink(CodeOutputInterface &ol, char *lname)
555 {
556   ClassDef *cd=0;
557   NamespaceDef *nsd=0;
558   QCString tmp = lname;
559   tmp = removeRedundantWhiteSpace(tmp.lower());
560  
561   // check if lowercase lname is a linkable type or interface
562   if ( (getFortranTypeDefs(tmp, currentModule, cd, useMembers)) && cd->isLinkable() )
563   {
564     if ( (cd->compoundType() == ClassDef::Class) && // was  Entry::INTERFACE_SEC) &&
565          (getGenericProcedureLink(cd, tmp, ol)) ) 
566     {
567       //cout << "=== generic procedure resolved" << endl; 
568     } 
569     else 
570     { // write type or interface link
571       writeMultiLineCodeLink(ol,cd,tmp);
572       addToSearchIndex(tmp.data());
573     }
574   }
575   // check for module
576   else if ( (getFortranNamespaceDefs(tmp, nsd)) && nsd->isLinkable() )
577   { // write module link
578     writeMultiLineCodeLink(ol,nsd,tmp);
579     addToSearchIndex(tmp.data());
580   }
581   // check for function/variable
582   else if (getLink(useMembers, tmp, ol, tmp)) 
583   {
584     //cout << "=== found link for lowercase " << lname << endl;
585   }
586   else 
587   {
588     // nothing found, just write out the word
589     //startFontClass("charliteral"); //test
590     codifyLines(tmp);
591     //endFontClass(); //test
592     addToSearchIndex(tmp.data());
593   }
594 }
595
596 /*! counts the number of lines in the input */
597 static int countLines()
598 {
599   const char *p=g_inputString;
600   char c;
601   int count=1;
602   while ((c=*p)) 
603   { 
604     p++ ; 
605     if (c=='\n') count++;  
606   }
607   if (p>g_inputString && *(p-1)!='\n') 
608   { // last line does not end with a \n, so we add an extra
609     // line and explicitly terminate the line after parsing.
610     count++, 
611     g_needsTermination=TRUE; 
612   } 
613   return count;
614 }
615
616 //----------------------------------------------------------------------------
617 /** start scope */
618 static void startScope() 
619 {
620   DBG_CTX((stderr, "===> startScope %s",yytext));
621   Scope *scope = new Scope;
622   scopeStack.append(scope);
623 }
624
625 /** end scope */
626 static void endScope() 
627 {
628   DBG_CTX((stderr,"===> endScope %s",yytext));
629   if (scopeStack.isEmpty()) 
630   {
631     DBG_CTX((stderr,"WARNING: fortrancode.l: stack empty!\n")); 
632     return;
633   }
634
635   Scope *scope = scopeStack.getLast();
636   scopeStack.removeLast();
637   for ( QCStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it) 
638   {
639     useMembers->remove(*it);
640   }
641   delete scope;
642 }
643
644 static void addUse(const QCString &moduleName) 
645 {
646   if (!scopeStack.isEmpty())
647     scopeStack.getLast()->useNames.append(moduleName);
648 }
649
650 static void addLocalVar(const QCString &varName) 
651 {
652   if (!scopeStack.isEmpty())
653   {
654     scopeStack.getLast()->localVars.insert(varName, (void*)1);
655     if (g_isExternal) scopeStack.getLast()->externalVars.insert(varName, (void*)1);
656   }
657 }
658
659 //----------------------------------------------------------------------------
660
661 /* -----------------------------------------------------------------*/
662 #undef  YY_INPUT
663 #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
664
665 static int yyread(char *buf,int max_size)
666 {
667     int c=0;
668     while( c < max_size && g_inputString[g_inputPosition] )
669     {
670         *buf = g_inputString[g_inputPosition++] ;
671         c++; buf++;
672     }
673     return c;
674 }
675
676 %}
677
678 IDSYM     [a-z_A-Z0-9]
679 ID        [a-z_A-Z]+{IDSYM}*
680 SUBPROG   (subroutine|function)
681 B         [ \t]
682 BS        [ \t]*
683 BS_       [ \t]+
684 COMMA     {BS},{BS}
685 ARGS_L0   ("("[^)]*")")
686 ARGS_L1a  [^()]*"("[^)]*")"[^)]*
687 ARGS_L1   ("("{ARGS_L1a}*")")
688 ARGS_L2   "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
689 ARGS      {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
690
691 NUM_TYPE  (complex|integer|logical|real)
692 LOG_OPER  (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
693 KIND      {ARGS}
694 CHAR      (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
695 TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE|ENUMERATOR)
696
697 INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
698 ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|(NON_)?RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE)
699 ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC)
700 /* Assume that attribute statements are almost the same as attributes. */
701 ATTR_STMT {ATTR_SPEC}|DIMENSION
702 FLOW      (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO)
703 COMMANDS  (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON)
704 IGNORE    (CALL)
705 PREFIX    ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?0
706 LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")"
707
708 /* |  */
709
710 %option noyywrap
711 %option stack
712 %option caseless
713 /*%option debug*/
714
715 %x Start
716 %x SubCall
717 %x FuncDef
718 %x ClassName
719 %x ClassVar
720 %x Subprog
721 %x DocBlock
722 %x Use
723 %x UseOnly
724 %x Import
725 %x Declaration
726 %x DeclarationBinding
727 %x DeclContLine
728 %x Parameterlist
729 %x String
730 %x Subprogend
731
732 %%
733  /*==================================================================*/
734
735  /*-------- ignore ------------------------------------------------------------*/
736
737 <Start>{IGNORE}/{BS}"("                 { // do not search keywords, intrinsics... TODO: complete list
738                                           codifyLines(yytext);
739                                         }
740  /*-------- inner construct ---------------------------------------------------*/
741  
742 <Start>{COMMANDS}/{BS}[,( \t\n]         {  // highlight
743                                           /* font class is defined e.g. in doxygen.css */
744                                           startFontClass("keyword");
745                                           codifyLines(yytext);
746                                           endFontClass();
747                                         }
748 <Start>{FLOW}/{BS}[,( \t\n]               {
749                                           if (g_isFixedForm)
750                                           {
751                                             if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT;
752                                           }
753                                           /* font class is defined e.g. in doxygen.css */
754                                           startFontClass("keywordflow");
755                                           codifyLines(yytext);
756                                           endFontClass();
757                                         }
758 <Start>{BS}(CASE|CLASS|TYPE){BS_}(IS|DEFAULT) {
759                                           startFontClass("keywordflow");
760                                           codifyLines(yytext);
761                                           endFontClass();
762                                         }
763 <Start>{BS}"end"({BS}{FLOW})/[ \t\n]       { // list is a bit long as not all have possible end
764                                           startFontClass("keywordflow");
765                                           codifyLines(yytext);
766                                           endFontClass();
767                                         }
768 <Start>"implicit"{BS}("none"|{TYPE_SPEC})  { 
769                                           startFontClass("keywordtype"); 
770                                           codifyLines(yytext);
771                                           endFontClass();
772                                         }
773 <Start>^{BS}"namelist"/[//]             {  // Namelist specification
774                                           startFontClass("keywordtype");
775                                           codifyLines(yytext);
776                                           endFontClass();
777                                         }
778  /*-------- use statement -------------------------------------------*/
779 <Start>"use"{BS_}                       { 
780                                           startFontClass("keywordtype"); 
781                                           codifyLines(yytext);
782                                           endFontClass();
783                                           yy_push_state(YY_START);
784                                           BEGIN(Use);     
785                                         }
786 <Use>"ONLY"                             { // TODO: rename
787                                           startFontClass("keywordtype"); 
788                                           codifyLines(yytext);
789                                           endFontClass();
790                                           yy_push_state(YY_START);
791                                           BEGIN(UseOnly);     
792                                         }           
793 <Use>{ID}                               {
794                                           QCString tmp = yytext;
795                                           tmp = tmp.lower();
796                                           g_insideBody=TRUE;
797                                           generateLink(*g_code, yytext);
798                                           g_insideBody=FALSE;
799
800                                           /* append module name to use dict */
801                                           useEntry = new UseEntry();
802                                           //useEntry->module = yytext;
803                                           //useMembers->append(yytext, useEntry);
804                                           //addUse(yytext);
805                                           useEntry->module = tmp;
806                                           useMembers->append(tmp, useEntry);
807                                           addUse(tmp);
808                                         }           
809 <Use,UseOnly,Import>{BS},{BS}           { codifyLines(yytext); }
810 <UseOnly,Import>{BS}&{BS}"\n"           { codifyLines(yytext);
811                                           g_contLineNr++;
812                                           YY_FTN_RESET}
813 <UseOnly>{ID}                           {
814                                           QCString tmp = yytext;
815                                           tmp = tmp.lower();
816                                           useEntry->onlyNames.append(tmp);
817                                           g_insideBody=TRUE;
818                                           generateLink(*g_code, yytext);
819                                           g_insideBody=FALSE;
820                                         }
821 <Use,UseOnly,Import>"\n"                {
822                                           unput(*yytext);
823                                           yy_pop_state();YY_FTN_RESET
824                                         }
825 <*>"import"{BS}/"\n"                  |
826 <*>"import"{BS_}                        {
827                                           startFontClass("keywordtype");
828                                           codifyLines(yytext);
829                                           endFontClass();
830                                           yy_push_state(YY_START);
831                                           BEGIN(Import);
832                                         }
833 <Import>{ID}                            {
834                                           g_insideBody=TRUE;
835                                           generateLink(*g_code, yytext);
836                                           g_insideBody=FALSE;
837                                         }
838 <Import>("ONLY"|"NONE"|"ALL")           {
839                                           startFontClass("keywordtype");
840                                           codifyLines(yytext);
841                                           endFontClass();
842                                         }
843  /*-------- fortran module  -----------------------------------------*/
844 <Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n {  //
845                                           startScope();
846                                           startFontClass("keyword"); 
847                                           codifyLines(yytext);
848                                           endFontClass();
849                                           yy_push_state(YY_START);
850                                           BEGIN(ClassName); 
851                                           if (!qstricmp(yytext,"module")) currentModule="module";
852                                         }
853 <Start>("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n {  //
854                                           startScope();
855                                           startFontClass("keyword");
856                                           codifyLines(yytext);
857                                           endFontClass();
858                                           yy_push_state(YY_START);
859                                           BEGIN(ClassName);
860                                           currentClass="class";
861                                         }
862 <*>{LANGUAGE_BIND_SPEC}                 {  //
863                                           startFontClass("keyword");
864                                           codifyLines(yytext);
865                                           endFontClass();
866                                         }
867 <Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n {  //
868                                           startScope();
869                                           startFontClass("keyword");
870                                           codifyLines(yytext);
871                                           endFontClass();
872                                           yy_push_state(YY_START);
873                                           BEGIN(ClassName);
874                                           currentClass="class";
875                                         }
876 <ClassName>{ID}                         {
877                                           if (currentModule == "module")
878                                           {
879                                             currentModule=yytext;
880                                             currentModule = currentModule.lower();
881                                           }
882                                           generateLink(*g_code,yytext);
883                                           yy_pop_state();
884                                         }
885 <ClassName>({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable declaration
886               startFontClass("keyword");
887             g_code->codify(yytext);
888             endFontClass();
889             }
890 <ClassName>\n                           { // interface may be without name
891                                           yy_pop_state();
892                                           YY_FTN_REJECT;
893                                         }
894 <Start>^{BS}"end"({BS_}"enum").*        { // just reset currentClass, rest is done in following rule
895                                           currentClass=0;
896                                           YY_FTN_REJECT;
897                                         }
898 <Start>^{BS}"end"({BS_}"type").*        { // just reset currentClass, rest is done in following rule
899                                           currentClass=0;
900                                           YY_FTN_REJECT;
901                                         }
902 <Start>^{BS}"end"({BS_}"module").*      { // just reset currentModule, rest is done in following rule
903                                           currentModule=0;
904                                           YY_FTN_REJECT;
905                                         }
906  /*-------- subprog definition -------------------------------------*/
907 <Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_}  {   // TYPE_SPEC is for old function style function result
908                                           startFontClass("keyword");
909                                           codifyLines(yytext);
910                                           endFontClass();
911                                        }              
912 <Start>({PREFIX}{BS_})?{SUBPROG}{BS_}   {  // Fortran subroutine or function found
913                                           startFontClass("keyword");
914                                           codifyLines(yytext);
915                                           endFontClass();
916                                           yy_push_state(YY_START);
917                                           BEGIN(Subprog);
918                                         }
919 <Subprog>{ID}                           { // subroutine/function name
920                                           DBG_CTX((stderr, "===> start subprogram %s\n", yytext));
921                                           startScope();
922                                           generateLink(*g_code,yytext);
923                                         }
924 <Subprog>"result"/{BS}"("[^)]*")"       {
925                                           startFontClass("keyword");
926                                           codifyLines(yytext);
927                                           endFontClass();
928                                         }
929 <Subprog>"("[^)]*")"                    { // ignore rest of line 
930                                           codifyLines(yytext);
931                                         }
932 <Subprog,Subprogend>"\n"                { codifyLines(yytext);
933                                           g_contLineNr++;
934                                           yy_pop_state();
935                                           YY_FTN_RESET
936                                         }
937 <Start>^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface")?{BS}     {  // Fortran subroutine or function ends
938                                           //cout << "===> end function " << yytext << endl;
939                                           endScope();
940                                           startFontClass("keyword");
941                                           codifyLines(yytext);
942                                           endFontClass();
943                                           yy_push_state(YY_START);
944                                           BEGIN(Subprogend);
945                                         }
946 <Subprogend>{ID}/{BS}(\n|!)             {
947                                           generateLink(*g_code,yytext);
948                                           yy_pop_state();
949                                         }
950 <Start>^{BS}"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface"){BS}/(\n|!) {  // Fortran subroutine or function ends
951                                           //cout << "===> end function " << yytext << endl;
952                                           endScope();
953                                           startFontClass("keyword");
954                                           codifyLines(yytext);
955                                           endFontClass();
956                                         }
957  /*-------- variable declaration ----------------------------------*/
958 <Start>^{BS}"real"/[,:( ]               { // real is a bit tricky as it is a data type but also a function.
959                                           yy_push_state(YY_START);
960                                           BEGIN(Declaration);
961                                           startFontClass("keywordtype");
962                                           g_code->codify(yytext);
963                                           endFontClass();
964                                        }
965 <Start>{TYPE_SPEC}/[,:( ]               { 
966                                           QCString typ = yytext;
967                                           typ = removeRedundantWhiteSpace(typ.lower());
968                                           if (QString(typ).startsWith("real")) YY_FTN_REJECT;
969                                           if (typ == "type" || typ == "class" || typ == "procedure") inTypeDecl = 1;
970                                           yy_push_state(YY_START);
971                                           BEGIN(Declaration);
972                                           startFontClass("keywordtype");
973                                           g_code->codify(yytext);
974                                           endFontClass();
975                                        }
976 <Start>{ATTR_SPEC}                     { 
977                                           if (QCString(yytext) == "external")
978                                           {
979                                             yy_push_state(YY_START);
980                                             BEGIN(Declaration);
981                                             g_isExternal = true;
982                                           }
983                                           startFontClass("keywordtype");
984                                           g_code->codify(yytext);
985                                           endFontClass();
986                                        }
987 <Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration
988                                           if (QCString(yytext) == "external") g_isExternal = true;
989                                           startFontClass("keywordtype");
990                                           g_code->codify(yytext);
991                                           endFontClass();
992                                         }
993 <Declaration>{ID}                       { // local var
994                                           if (g_isFixedForm && yy_my_start == 1)
995                                           {
996                                             startFontClass("comment");
997                                             g_code->codify(yytext);
998                                             endFontClass();
999                                           }
1000                                           else if (g_currentMemberDef &&
1001                                                    ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString()!=QCString("subroutine") || inTypeDecl)) ||
1002                                                      g_currentMemberDef->isVariable() || g_currentMemberDef->isEnumValue()
1003                                                     )
1004                                                    )
1005                                           {
1006                                             generateLink(*g_code, yytext);
1007                                           }
1008                                           else
1009                                           {
1010                                             g_code->codify(yytext);
1011                                             addLocalVar(yytext);
1012                                           }
1013                                         }
1014 <Declaration>{BS}("=>"|"="){BS}         { // Procedure binding
1015                                           BEGIN(DeclarationBinding);
1016                                           g_code->codify(yytext);
1017                                         }
1018 <DeclarationBinding>{ID}                { // Type bound procedure link
1019                                           generateLink(*g_code, yytext);
1020                                           yy_pop_state();
1021                                         }
1022 <Declaration>[(]                        { // start of array or type / class specification
1023                                           bracketCount++;
1024                                           g_code->codify(yytext);
1025                                         }
1026
1027 <Declaration>[)]                        { // end array specification
1028                                           bracketCount--;
1029                                           if (!bracketCount) inTypeDecl = 0;
1030                                           g_code->codify(yytext);
1031                                         }
1032
1033 <Declaration,DeclarationBinding>"&"     { // continuation line
1034                                           g_code->codify(yytext);
1035                                           if (!g_isFixedForm)
1036                                           {
1037                                             yy_push_state(YY_START);
1038                                             BEGIN(DeclContLine);                                          
1039                                           }
1040                                         }
1041 <DeclContLine>"\n"                      { // declaration not yet finished
1042                                           g_contLineNr++;
1043                                           codifyLines(yytext);
1044                                           bracketCount = 0;
1045                                           yy_pop_state();
1046                                           YY_FTN_RESET
1047                                         }
1048 <Declaration,DeclarationBinding>"\n"    { // end declaration line (?)
1049                                           if (g_endComment)
1050                                           {
1051                                             g_endComment=FALSE;
1052                                           }
1053                                           else
1054                                           {
1055                                             codifyLines(yytext);
1056                                           }
1057                                           bracketCount = 0;
1058                                           g_contLineNr++;
1059                                           if (!(g_hasContLine && g_hasContLine[g_contLineNr - 1]))
1060                                           {
1061                                             g_isExternal = false;
1062                                             yy_pop_state();
1063                                           }
1064                                           YY_FTN_RESET
1065                                         }
1066
1067  /*-------- subprog calls  -----------------------------------------*/
1068
1069 <Start>"call"{BS_}                      {
1070                                           startFontClass("keyword");
1071                                           codifyLines(yytext);
1072                                           endFontClass();
1073                                           yy_push_state(YY_START);
1074                                           BEGIN(SubCall);
1075                                         }
1076 <SubCall>{ID}                           { // subroutine call
1077                                           g_insideBody=TRUE;
1078                                           generateLink(*g_code, yytext);
1079                                           g_insideBody=FALSE;
1080                                           yy_pop_state();
1081                                         }
1082 <Start>{ID}{BS}/"("                     { // function call
1083                                           if (g_isFixedForm && yy_my_start == 6)
1084                                           {
1085                                             // fixed form continuation line
1086                                             YY_FTN_REJECT;
1087                                           }
1088                                           else if (QCString(yytext).stripWhiteSpace().lower() == "type")
1089                                           {
1090                                             yy_push_state(YY_START);
1091                                             BEGIN(Declaration);
1092                                             startFontClass("keywordtype");
1093                                             g_code->codify(QCString(yytext).stripWhiteSpace());
1094                                             endFontClass();
1095                                             g_code->codify(yytext + 4);
1096                                           }
1097                                           else
1098                                           {
1099                                             g_insideBody=TRUE;
1100                                             generateLink(*g_code, yytext);
1101                                             g_insideBody=FALSE;
1102                                           }
1103                                         }
1104
1105  /*-------- comments ---------------------------------------------------*/
1106 <Start,Declaration,DeclarationBinding>\n?{BS}"!>"|"!<"                 { // start comment line or comment block
1107                                           if (yytext[0] == '\n')
1108                                           {
1109                                             g_contLineNr++;
1110                                             yy_old_start = 0;
1111                                             yy_my_start = 1;
1112                                             yy_end = yyleng;
1113                                           }
1114                                           // Actually we should see if ! on position 6, can be continuation
1115                                           // but the chance is very unlikely, so no effort to solve it here
1116                                           yy_push_state(YY_START);
1117                                           BEGIN(DocBlock);
1118                                           docBlock=yytext;
1119                                         }
1120 <Declaration,DeclarationBinding>{BS}"!<"                   { // start comment line or comment block
1121                                           yy_push_state(YY_START);
1122                                           BEGIN(DocBlock);
1123                                           docBlock=yytext;
1124                                         }
1125
1126 <DocBlock>.*                            { // contents of current comment line
1127                                           docBlock+=yytext;
1128                                         }
1129 <DocBlock>"\n"{BS}("!>"|"!<"|"!!")      { // comment block (next line is also comment line)
1130                                           g_contLineNr++;
1131                                           yy_old_start = 0;
1132                                           yy_my_start = 1;
1133                                           yy_end = yyleng;
1134                                           // Actually we should see if ! on position 6, can be continuation
1135                                           // but the chance is very unlikely, so no effort to solve it here
1136                                           docBlock+=yytext; 
1137                                         }
1138 <DocBlock>"\n"                          { // comment block ends at the end of this line
1139                                           // remove special comment (default config)
1140                                           g_contLineNr++;
1141                                           if (Config_getBool(STRIP_CODE_COMMENTS))
1142                                           {
1143                                             g_yyLineNr+=((QCString)docBlock).contains('\n');
1144               g_yyLineNr+=1;
1145                                             endCodeLine();
1146                                             if (g_yyLineNr<g_inputLines)
1147                                             {
1148                                               startCodeLine();
1149                                             }
1150               g_endComment=TRUE;
1151                                           }
1152                                           else // do not remove comment
1153                                           {
1154                                             startFontClass("comment");
1155                                             codifyLines(docBlock);
1156                                             endFontClass();
1157                                           }
1158             unput(*yytext);
1159                                           g_contLineNr--;
1160                                          yy_pop_state();
1161                                           YY_FTN_RESET
1162                                         }
1163
1164 <*>"!"[^><\n].*|"!"$                    { // normal comment
1165                                           if(YY_START == String) YY_FTN_REJECT; // ignore in strings
1166                                           if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT;
1167                                           startFontClass("comment");
1168                                           codifyLines(yytext);
1169                                           endFontClass();
1170                                         }
1171
1172 <*>^[Cc*].*                             { // normal comment
1173                                           if(! g_isFixedForm) YY_FTN_REJECT;
1174
1175                                           startFontClass("comment");
1176                                           codifyLines(yytext);
1177                                           endFontClass();
1178                                         }
1179 <*>"assignment"/{BS}"("{BS}"="{BS}")"   {
1180                                           startFontClass("keyword");
1181                                           codifyLines(yytext);
1182                                           endFontClass();
1183                                         }
1184 <*>"operator"/{BS}"("[^)]*")"           {
1185                                           startFontClass("keyword");
1186                                           codifyLines(yytext);
1187                                           endFontClass();
1188                                         }
1189
1190  /*------ preprocessor  --------------------------------------------*/ 
1191 <Start>"#".*\n                          {
1192                                           if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT;
1193                                           g_contLineNr++;
1194                                           startFontClass("preprocessor");
1195                                           codifyLines(yytext);
1196                                           endFontClass();
1197                                           YY_FTN_RESET
1198                                         }
1199  /*------ variable references?  -------------------------------------*/ 
1200
1201 <Start>"%"{BS}{ID}                      { // ignore references to elements 
1202                                           g_code->codify(yytext);
1203                                         }
1204 <Start>{ID}                             {   
1205                                             g_insideBody=TRUE;
1206                                             generateLink(*g_code, yytext);
1207                                             g_insideBody=FALSE;
1208                                         }
1209  /*------ strings --------------------------------------------------*/ 
1210 <String>\n                              { // string with \n inside
1211                                           g_contLineNr++;
1212                                           str+=yytext;
1213                                           startFontClass("stringliteral");
1214                                           codifyLines(str);
1215                                           endFontClass();
1216                                           str = "";
1217                                           YY_FTN_RESET
1218                                         }           
1219 <String>\"|\'                           { // string ends with next quote without previous backspace 
1220                                           if(yytext[0]!=stringStartSymbol) YY_FTN_REJECT; // single vs double quote
1221                                           str+=yytext;
1222                                           startFontClass("stringliteral");
1223                                           codifyLines(str);
1224                                           endFontClass();
1225                                           yy_pop_state();
1226                                         }           
1227 <String>.                               {str+=yytext;}
1228
1229 <*>\"|\'                                { /* string starts */
1230                                           /* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */
1231                                           if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT;
1232                                           yy_push_state(YY_START);
1233                                           stringStartSymbol=yytext[0]; // single or double quote
1234                                           BEGIN(String);
1235                                           str=yytext;
1236                                         }
1237  /*-----------------------------------------------------------------------------*/
1238
1239 <*>\n                                   {
1240                                           if (g_endComment)
1241                                           {
1242                                             g_endComment=FALSE;
1243                                           }
1244                                           else
1245                                           {
1246                                             codifyLines(yytext);
1247                                             // comment cannot extend over the end of a line so should always be terminatd at the end of the line.
1248                                             if (g_currentFontClass && !strcmp(g_currentFontClass,"comment")) endFontClass();
1249                                           }
1250                                           g_contLineNr++;
1251                                           YY_FTN_RESET
1252                                         }
1253 <*>^{BS}"type"{BS}"="                   { g_code->codify(yytext); }
1254
1255 <*>.                                    { 
1256                                           if (g_isFixedForm && yy_my_start > fixedCommentAfter)
1257                                           {
1258                                             //yy_push_state(YY_START);
1259                                             //BEGIN(DocBlock);
1260                                             //docBlock=yytext;
1261                                             startFontClass("comment");
1262                                             codifyLines(yytext);
1263                                           }
1264                                           else
1265                                           {
1266                                             g_code->codify(yytext);
1267                                           }
1268                                         }
1269 <*>{LOG_OPER}                           { // Fortran logical comparison keywords
1270                                           g_code->codify(yytext);
1271                                         }
1272 <*><<EOF>>                              {
1273                                           if (YY_START == DocBlock) {
1274                                             if (!Config_getBool(STRIP_CODE_COMMENTS))
1275                                             {
1276                                               startFontClass("comment");
1277                                               codifyLines(docBlock);
1278                                               endFontClass();
1279                                             }
1280                                           }
1281                                           yyterminate();
1282                                         }
1283 %%
1284
1285 /*@ ----------------------------------------------------------------------------
1286  */
1287
1288 /*===================================================================*/
1289
1290
1291 void resetFortranCodeParserState() {}
1292
1293 bool recognizeFixedForm(const char* contents, FortranFormat format); /* prototype, implementation in fortranscanner.l */
1294 const char* prepassFixedForm(const char* contents, int *hasContLine); /* prototype, implementation in fortranscanner.l */
1295 static void checkContLines(const char *s)
1296 {
1297   int numLines = 0;
1298   int curLine = 0;
1299   int i = 0;
1300   const char *p = s;
1301
1302   numLines = 2; // one for element 0, one in case no \n at end
1303   while (*p)
1304   {
1305     if (*p == '\n') numLines++;
1306     p++;
1307   }
1308
1309   g_hasContLine = (int *) malloc((numLines) * sizeof(int));
1310   for (i = 0; i < numLines; i++)
1311     g_hasContLine[i] = 0;
1312   p = prepassFixedForm(s, g_hasContLine);
1313   g_hasContLine[0] = 0;
1314 }
1315
1316 void parseFortranCode(CodeOutputInterface &od,const char *className,const QCString &s, 
1317                   bool exBlock, const char *exName,FileDef *fd,
1318                   int startLine,int endLine,bool inlineFragment,
1319                   MemberDef *memberDef,bool,Definition *searchCtx,
1320                   bool collectXRefs, FortranFormat format)
1321 {
1322   //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd);
1323
1324   // used parameters
1325   (void)memberDef;
1326   (void)className;
1327
1328   if (s.isEmpty()) return;
1329   printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL);
1330   TooltipManager::instance()->clearTooltips();
1331   g_code = &od;
1332   g_inputString   = s;
1333   g_inputPosition = 0;
1334   g_isFixedForm = recognizeFixedForm((const char*)s,format);
1335   g_contLineNr = 1;
1336   g_hasContLine = NULL;
1337   if (g_isFixedForm)
1338   {
1339     checkContLines(g_inputString);
1340   }
1341   g_currentFontClass = 0;
1342   g_needsTermination = FALSE;
1343   g_searchCtx = searchCtx;
1344   g_collectXRefs = collectXRefs;
1345   if (startLine!=-1)
1346     g_yyLineNr    = startLine;
1347   else
1348     g_yyLineNr    = 1;
1349
1350   if (endLine!=-1)
1351     g_inputLines  = endLine+1;
1352   else
1353     g_inputLines  = g_yyLineNr + countLines() - 1;
1354
1355   g_exampleBlock  = exBlock; 
1356   g_exampleName   = exName;
1357   g_sourceFileDef = fd;
1358   if (exBlock && fd==0)
1359   {
1360     // create a dummy filedef for the example
1361     g_sourceFileDef = new FileDef("",exName);
1362   }
1363   if (g_sourceFileDef) 
1364   {
1365     setCurrentDoc("l00001");
1366   }
1367   g_currentDefinition = 0;
1368   g_currentMemberDef = 0;
1369   if (!g_exampleName.isEmpty())
1370   {
1371     g_exampleFile = convertNameToFile(g_exampleName+"-example");
1372   }
1373   g_includeCodeFragment = inlineFragment;
1374   startCodeLine();
1375   g_parmName.resize(0);
1376   g_parmType.resize(0);
1377   fortrancodeYYrestart( fortrancodeYYin );
1378   BEGIN( Start );
1379   fortrancodeYYlex();
1380   if (g_needsTermination)
1381   {
1382     endFontClass();
1383     g_code->endCodeLine();
1384   }
1385   if (fd)
1386   {
1387     TooltipManager::instance()->writeTooltips(*g_code);
1388   }
1389   if (exBlock && g_sourceFileDef)
1390   {
1391     // delete the temporary file definition used for this example
1392     delete g_sourceFileDef;
1393     g_sourceFileDef=0;
1394   }
1395   if (g_hasContLine) free(g_hasContLine);
1396   g_hasContLine = NULL;
1397   printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL);
1398   return;
1399 }
1400
1401 #if !defined(YY_FLEX_SUBMINOR_VERSION)
1402 extern "C" { // some bogus code to keep the compiler happy
1403   void fortrancodeYYdummy() { yy_flex_realloc(0,0); }
1404 }
1405 #elif YY_FLEX_MAJOR_VERSION<=2 && YY_FLEX_MINOR_VERSION<=5 && YY_FLEX_SUBMINOR_VERSION<33
1406 #error "You seem to be using a version of flex newer than 2.5.4 but older than 2.5.33. These versions do NOT work with doxygen! Please use version <=2.5.4 or >=2.5.33 or expect things to be parsed wrongly!"
1407 #else
1408 extern "C" { // some bogus code to keep the compiler happy
1409   void fortrancodeYYdummy() { yy_top_state(); } 
1410 }
1411 #endif
1412