Back

1     //------------------------------------------------------------------------------
2     // Module: Conv2HTML.cpp                                                      //
3     //                                                                            //
4     //    Converts source code into HTML                                          //
5     //    Converts source code into HTML using ...                                //
6     //       a) TItemStyle (a syntax highlighting style)                          //
7     //       b) TLanguage (a language definition)                                 //
8     //       c) TOptions (settings like tab stop positions)                       //
9     //                                                                            //
10    //    Copyright (c) 2000-2004 by Lars Haendel                                 //
11    //    Home: http://www.newty.de                                               //
12    //                                                                            //
13    //    This program is free software and can be used under the terms of the    //
14    //    GNU licence. See header-file for further information and disclaimer.    //
15    //                                                                            //
16    //------------------------------------------------------------------------------
17
18
19    #include <iomanip>               // due to:  setw()
20
21    #include "Conv2HTML.h"
22    #include "NameUtil.h"            //          GetFileName()
23
24    #define LINE_NUMBER_WIDTH 5      // width min. used for line numbers
25
26    //#define TAB_DEBUG_MODE         // debug options: tabs are exanded to 't' and not written "virtually"
27
28    //----------------------------------------------------------------------------------------------------------------------
29    // constructor
30    TConv2HTML::TConv2HTML(const TItemStyle*const& _style, const TLanguage*const& _lang, const TOptions*const& _options)
31    {
32       // copy
33       style   = _style;       // highlighting style
34       lang    = _lang;        // language definition
35       options = _options;     // options like tab stop positions etc.
36
37       // create color map: check if different code items have the same color
38       for(int i=0;i<nItemType;i++)
39          for(int j=0;j<=i;j++)
40             if(strcmp(style->szColor[i], style->szColor[j])==0)
41             {
42                cMap[i]=j;        // note: if i equals j no match was found, color is unique so far
43                break;
44             }
45    }
46
47
48       //-------------------------------------------------------------------------------------------------------------------
49       //  functions which virtually(!) write HTML output
50       //
51
52    //----------------------------------------------------------------------------------------------------------------------
53    // (virtually) write one tab
54    inline void TConv2HTML::VirtuallyWriteTab()
55    {
56       int _nSpaces = options->tabPos-col%options->tabPos;    // calculate necessary number of spaces to match tab stops
57
58       nSpaces += _nSpaces;
59       col     += _nSpaces;                                   // increment actual column
60    }
61
62
63
64    //----------------------------------------------------------------------------------------------------------------------
65    // (virtually) write one space
66    inline void TConv2HTML::VirtuallyWriteSpace()
67    {
68       nSpaces++;
69       col++;                                                // increment actual column
70    }
71
72
73    //----------------------------------------------------------------------------------------------------------------------
74    // (virtually) write one linefeed
75    // note: if enabled all HTML tags are closed when there are 'options->nEndl' successive linefeeds
76    void TConv2HTML::VirtuallyWriteLF(ofstream& file)
77    {
78       col     = 0;                           // new line: reset column and outstanding spaces
79       nSpaces = 0;
80       nLines++;                              // increment outstanding linefeeds
81
82       // if enabled: close all HTML tags if there are 'options.nEndl' successive linefeeds
83       if(options->f_TagClosingOnEndl)
84          if(nLines == options->nEndl)        // note: equality prevents useless execution
85             CloseHtmlTags(file);
86    }
87
88
89
90       //-------------------------------------------------------------------------------------------------------------------
91       //  functions which really write HTML output
92       //
93
94    //----------------------------------------------------------------------------------------------------------------------
95    // write one tab  -  note: used in WriteChar() when for example comments or preprocessor are written
96    void TConv2HTML::WriteTab(ofstream& file)
97    {
98       int nSpaces = options->tabPos-col%options->tabPos;    // calculate necessary number of spaces to match tab stops
99
100      for(int i=0;i<nSpaces;i++)
101   #ifdef TAB_DEBUG_MODE
102         file << "t";
103   #else
104         file << " ";
105   #endif
106
107      col += nSpaces;                                       // increment actual column
108   }
109
110
111   //----------------------------------------------------------------------------------------------------------------------
112   // function closes all opened HTML tags - may be safely called twice or more time
113   void TConv2HTML::CloseHtmlTags(ofstream& file)
114   {
115      // a) if necessary end bold state and/or italic state
116      if(style->f_Italic[lastType])
117         file << "</i>";
118      if(style->f_Bold[lastType])
119         file << "</b>";
120
121      // b) if the previous item type had a specific color, i.e. not the default one
122      if(cMap[lastType]!=cMap[TItemStyle::Identifier])
123         file << "</font>";
124
125      lastType = TItemStyle::Identifier;
126   }
127
128
129   //----------------------------------------------------------------------------------------------------------------------
130   // write character replacing some like '<', '>' ...
131   void TConv2HTML::WriteChar(ofstream& file, const char& c)
132   {
133      // a) check if it's one of the "above 128 characters" and replace it
134      if(c<0)
135      {
136         file << "&#" << dec << ((int) 256+c) << ";";
137         col++;
138         return;
139      }
140
141
142      // b) check character for the special HTML characters (<, >, &, ") and replace them.
143      //    additionally check for tabs
144      switch(c)
145      {
146         case '<' : file << "&lt;";   col++;    break;      // replace
147         case '>' : file << "&gt;";   col++;    break;
148         case '&' : file << "&amp;";  col++;    break;
149         case '"' : file << "&quot;"; col++;    break;
150         case '\t': WriteTab(file);             break;      // write tab
151         default  : file << c;  col++;                      // default: write real character
152      }
153   }
154
155   //----------------------------------------------------------------------------------------------------------------------
156   // write all outstanding linefeeds and spaces
157   void TConv2HTML::WriteWhiteSpaces(ofstream& file)
158   {
159      for(int i=0;i<nLines;i++)               // write outstanding linefeeds
160         file << endl;
161      line += nLines;
162
163      if(nLines!=0)                           // if a new line has started -> ...
164         for(int i=0;i<options->indent;i++)   // ... write indent
165           file << " ";
166
167      for(int i=0;i<nSpaces;i++)              // write outstanding spaces
168      #ifdef TAB_DEBUG_MODE
169         file << "w";
170      #else
171         file << " ";
172      #endif
173
174
175      nLines  = 0;                            // reset
176      nSpaces = 0;
177   }
178
179
180   //----------------------------------------------------------------------------------------------------------------------
181   // writes a code item as HTML to the output file
182   //  <type> identifies the type of the code item
183   //  <szCode> points to a character field containing at least the code of the code item
184   //  <nChar> is the length of the code item
185   void TConv2HTML::WriteItem(ofstream& file, const TItemStyle::ItemType& type, const char*const& szCode, const int& nChar)
186   {
187      // 1. if enabled and if it's the first item (nItems<0): write line number(s)
188      if(nItems<0)
189         if(options->f_AddLineNumbers)
190         {
191            char szBuffer[256];           // buffer
192            nItems = 0;                   // set to zero: do not execute again
193
194            int tmp = nSpaces;            // remember number of outstanding spaces and ...
195            nSpaces = 0;                  // ... set it temporarily to zero
196
197            int n = nLines;               // remember number of outstanding linefeeds ...
198            for(int i=0;i<n;i++)          // ... and call WriteItem() as many times with 'nLines=1'
199            {
200               // set to one in order to execute WriteItem with one outstanding linefeed as many times as necessary
201               nLines = 1;
202
203               // generate line number
204               sprintf(szBuffer, "%d", line);   // generate line number (left justified)
205               WriteItem(file, TItemStyle::Number, szBuffer, SizeOfString(szBuffer));      // call recursive
206
207
208               // if specified: generate line anchor
209               if(options->f_AddLineAnchors)
210               {
211                  // generate line anchor text, '-1' as line number has just been incremented in above call to WriteItem()
212                  sprintf(szBuffer, "<a name=\"%d\"></a>", line-1);
213                  file << szBuffer;                                     // and write it
214               }
215
216
217               // add (virtually) as may spaces to get left justified line numbers with width LINE_NUMBER_WIDTH
218               int j=0;
219               if(i==n-1)     // only for last line, i.e. for the line where some code/text comes afterwards
220               {
221                  do
222                  {
223                     VirtuallyWriteSpace();  // virtually write space
224                     j++;
225                  }
226                  while(j<LINE_NUMBER_WIDTH-(log(line-1)/log(10)));
227               }
228               else
229                  if(options->f_TagClosingOnEndl)  // if specified: close all HTML tags if more linefeeds will be written
230                     CloseHtmlTags(file);
231
232            }
233            nSpaces += tmp;   // restore previous value of outstanding spaces, note: use '+' cause VirtuallyWriteSpace may also have added some
234            col = 0;          // reset column counter, note: has been incremented in call to WriteItem() or VirtuallyWriteSpace()
235         }
236         else
237            nItems=0;   // else set to zero: do not execute again
238
239
240      //  2. check for color/format changes - note: WriteWhiteSpaces() is called once in each posible branch
241      if(cMap[lastType]!=cMap[type])      // if color has changed ...
242      {
243         // a) close all HTML tags and write outstanding spaces and line feeds
244         CloseHtmlTags(file);
245         WriteWhiteSpaces(file);
246
247
248         // b) begin new color if the actual item type has a specific color, i.e. not the default one
249         if(cMap[type] != cMap[TItemStyle::Identifier])
250            file << "<font color=\"" << style->szColor[cMap[type]] << "\">";
251
252
253         // c) if necessary: begin bold state and/or italic state
254         if(style->f_Bold[type])
255            file << "<b>";
256         if(style->f_Italic[type])
257            file << "<i>";
258      }
259      else
260      {
261         // 3. check for sole ends of the bold state and/or italic state
262
263         // a) the bold state changes which implies an end of an italic state
264         if((style->f_Bold[lastType] && !style->f_Bold[type]) || (!style->f_Bold[lastType] && style->f_Bold[type]))
265         {
266            if(style->f_Italic[lastType])
267               file << "</i>";               // if necessary end italic state
268
269            if(!style->f_Bold[type])
270            {
271               file << "</b>";
272               WriteWhiteSpaces(file);       // write outstanding spaces and line feeds
273            }
274            else
275            {
276               WriteWhiteSpaces(file);       // write outstanding spaces and line feeds
277               file << "<b>";
278            }
279
280            if(style->f_Italic[type])
281               file << "<i>";
282         }
283         else
284
285         // b) if the bold state doesn't change -> check for italic state changes
286         {
287            if(style->f_Italic[lastType] && !style->f_Italic[type])
288            {
289               file << "</i>";
290               WriteWhiteSpaces(file);       // write outstanding spaces and line feeds
291            }
292            else
293               if(!style->f_Italic[lastType] && style->f_Italic[type])
294               {
295                  WriteWhiteSpaces(file);    // write outstanding spaces and line feeds
296                  file << "<i>";
297               }
298               else
299                  WriteWhiteSpaces(file);    // default, write outstanding spaces and line feeds
300         }
301      }
302
303
304      // 4. write item code
305      // write all characters using WriteChar() which replaces HTML characters and checks for whitespaces as tabs
306      for(int i=0;i<nChar;i++)
307         WriteChar(file, szCode[i]);
308
309
310      lastType=type;                            // remember type
311      nItems++;                                 // increment item counter
312   }
313
314
315      //-------------------------------------------------------------------------------------------------------------------
316      //   write header and footer
317      //
318
319   //----------------------------------------------------------------------------------------------------------------------
320   // writes header at the top of the HTML file
321   void TConv2HTML::WriteHeader(ofstream& file, const char*const& szSrcFileName, const char*const& szBackLink)
322   {
323      // if enabled: write <html> and <body> tags
324      if(options->f_HtmlAndBodyTags)
325      {
326         file << "<html>" << endl << "<head>" << endl;
327         file << "   <title>" << GetFileName(szSrcFileName) << "</title>" << endl;
328         file << "   <meta name=\"generator\" content=\"" << SZ_HTML_PRGNAME << " - http://" << SZ_HTML_PRGLINK;
329         file << "\"" << endl << "</head>" << endl << endl;
330         file << "<body style=\"background:" << style->szColor[TItemStyle::Bkgnd] << ";\">";
331      }
332      else
333      {
334         file << "<div style=\"background:" << style->szColor[TItemStyle::Bkgnd];
335         file << ";border-style:none;border-width:thin;\">";
336      }
337
338      // if enabled: add top name for top link
339      if(options->f_AddTopLinks)
340         file << "<a name=\"top\"></a>" << endl;
341
342
343      // if enabled: write back link to overview file   -  Note: backslash is exchanged by '/'
344      if(options->f_AddBackLink)
345      {
346         file << "<tr><td><a href=\"" << szBackLink << "\">";
347         file << "<font color=\"" << style->szColor[TItemStyle::Identifier] << "\">";
348         file << "Back </font></a>";
349      }
350
351
352      file << endl << endl << "<pre><code><font color=\"";
353      file << style->szColor[TItemStyle::Identifier] << "\">";
354   }
355
356
357   //----------------------------------------------------------------------------------------------------------------------
358   // writes footer at the end of the HTML file
359   void TConv2HTML::WriteFooter(ofstream& file, const bool& f_Stop)
360   {
361      file << endl << "</font>" << endl << "</code></pre>" << endl;
362
363
364      // if process was interrupted by the user: write short message
365      if(f_Stop)
366      {
367         file << "<font color=\"" << style->szColor[TItemStyle::Identifier] << "\">";
368         file << "<br> User breaked conversion process, thus this HTML file is truncated here!</font>";
369         file << endl << endl;
370      }
371
372
373      // if enabled: add back link
374      if(options->f_AddTopLinks)
375      {
376         file << "<a href=\"#top\">";
377         file << "<font color=\"" << style->szColor[TItemStyle::Identifier] << "\">";
378         file << "Top</a></font>";
379      }
380
381
382      // if enabled: close <html> and <body> tags
383      if(options->f_HtmlAndBodyTags)
384         file << "</body></html>";
385      else
386         file << "</div>";
387
388      file << endl << endl << "<!-- Generated by " << SZ_HTML_PRGNAME << "(http://" << SZ_HTML_PRGLINK << ") -->" << endl;
389   }
390
391
392      //-------------------------------------------------------------------------------------------------------------------
393      //   parse functions
394      //
395
396   //----------------------------------------------------------------------------------------------------------------------
397   // (virtually) write space/tab if line[pos] contains a space/tab
398   bool TConv2HTML::Check4Spaces(const char*const& szLine, int& pos)
399   {
400      if(szLine[pos]==' ')             // a) check for space
401      {
402         VirtuallyWriteSpace();           // virtually write it
403         pos++;                           // increment parser's position
404         return true;
405      }
406      else
407         if(szLine[pos]=='\t')         // b) check for tab
408         {
409            VirtuallyWriteTab();          // virtually write it
410            pos++;                        // increment parser's position
411            return true;
412         }
413
414      return false;
415   }
416
417
418   //----------------------------------------------------------------------------------------------------------------------
419   // write multiline comment checking for the terminating characters
420   void TConv2HTML::ProcessComment(ofstream& file, const char*const& szLine, int& pos, const int& len, const int& h)
421   {
422      int i;
423      f_MultiLineComment = true;                      // activate multiline comment
424
425      for(i=pos+h;i<len;i++)                          // note: 'szLine[len]' is the terminating '\0'
426      {
427         // check for terminating characters; function returns # of terminating characters; '0' means no match
428         int nChars = lang->EndsMultiLineComment(&szLine[i]);
429         if(nChars>0)
430         {
431            f_MultiLineComment = false;               // terminate multiline comment
432            i += nChars;                              // increment by # terminating characters
433            break;
434         }
435      }
436
437      WriteItem(file, TItemStyle::Comment, &szLine[pos], i-pos);       // write comment
438      pos = i;
439   }
440
441
442   //----------------------------------------------------------------------------------------------------------------------
443   // process preprocessor directive, i.e. find its end and write it using TConv2HTML::WriteItem()
444   void TConv2HTML::ProcessPreproc(const char*const& szLine, int& pos, ofstream& des, const int& len, const int& h)
445   {
446      f_MultiLinePreproc = false;    // reset flag
447
448      // a) check for comments which would terminate or interrupt a preprocessor directive
449      bool f_Ended = false, f_Interrupted = false;   // ini
450      int i;
451      for(i=pos+h;i<len;i++)    // note: 'szLine[len]' is the terminating '\0'
452      {
453         // check for single line comment, preproc directive will be ended
454         if((f_Ended = lang->StartsSingleLineComment(&szLine[i]))>0)
455            break;
456
457         // check for multi line comment, preproc directive will be interrupted
458         if((f_Interrupted = lang->StartsMultiLineComment(&szLine[i]))>0)
459            break;
460      }
461
462      // b) if preprocessor was ended or interrupted ... position back all whitespaces
463      if(f_Ended || f_Interrupted)
464         if(i>0)
465            while(isspace(szLine[i-1])) // 'szLine[i-1]' is the character just before the comments starts
466               i--;
467
468
469      // c) write preprocessor
470      WriteItem(des, TItemStyle::Preproc, &szLine[pos], i-pos);
471      pos = i;                                         // update position
472
473
474      // d) if preprocessor was interrupted by multiline comment
475      if(f_Interrupted)
476      {
477         while(Check4Spaces(szLine, pos))             // check for spaces
478            continue;
479         ProcessComment(des, szLine, pos, len, h);    // process comment
480      }
481
482
483      // e) check last character for '\' which indicates multi line preprocessor directives ...
484      //    ... if no single line comment ended the preprocessor directive and ...
485      //    ... if no multi line comment is active (note: this may happen if preproc was interrupted
486      //        by multiline comment)
487      if(!f_Ended && !f_MultiLineComment)
488         if(szLine[len-1]=='\\')             // note: '-1' because szLine[len] is the terminating '\0'
489            f_MultiLinePreproc = true;
490   }
491
492
493   //----------------------------------------------------------------------------------------------------------------------
494   // process string, i.e. find end and write it using TConv2HTML::WriteItem()
495   void TConv2HTML::ProcessString(ofstream& des, const char*const& szLine, int& pos, const int& len)
496   {
497      int i;                              // parse start position
498      if(!f_MultiLineString)              // if new string starts ...
499         cStringChar = szLine[pos];       // ... store starting character
500      i=pos+(!f_MultiLineString);         // init parse position (skip first character if new string starts)
501
502      // init multiline string flag: set again if strings are to be continued to the next line(s) until the end character
503      // is found, else reset
504      f_MultiLineString = lang->SillyStringHandling();
505
506      // parse until the terminating character is found. If not found till endl:
507      //   a) continue string to next line if last character is the escape character
508      //   b) terminate
509      while(szLine[i]!='\0')                 // while endl is not reached ...
510      {
511         if(szLine[i]==lang->EscapeChar())   // do not check next character if an escape is encountered and ...
512         {
513            if(szLine[i+1]=='\0')            // ... if line ends afterwards extend string to next line (again)
514               f_MultiLineString = true;
515            else
516               i++;                          // ... else increment to skip (i.e. do not check) next charcater
517         }
518         else                                // check if it's the terminating character
519            if(szLine[i]==cStringChar)
520            {
521               i++;
522               f_MultiLineString = false;    // end of string was found, reset flag
523               break;
524            }
525         i++;
526      }
527
528      if(cStringChar==lang->String())
529         WriteItem(des, TItemStyle::String, &szLine[pos], i-pos);          // write as string
530      else
531         WriteItem(des, TItemStyle::Character, &szLine[pos], i-pos);       // write as character
532      pos = i;                                                             // store new line position
533   }
534
535
536   //----------------------------------------------------------------------------------------------------------------------
537   // process number, i.e. find end and write it using TConv2HTML::WriteItem()
538   void TConv2HTML::ProcessNumber(ofstream& des, const char*const& szLine, int& pos, const int& len)
539   {
540      int i;
541
542      // determine length of the number: numbers are ended by whitespaces or symbols (except '.' and '+' or '-' if there
543      // is a preceeding 'e').   Note: numbers are not syntactically checked! They're assumed to be correct!
544      for(i=pos+1;i<len;i++)
545         if( (szLine[i]=='.' && szLine[i+1]=='.') ||
546           ( (szLine[i]=='+' || szLine[i]=='-') && szLine[i-1]!='e' && szLine[i-1]!='E' ) ||
547             isspace(szLine[i]) ||
548             lang->SymbolEndsNumber(szLine[i]))
549            break;
550
551      WriteItem(des, TItemStyle::Number, &szLine[pos], i-pos);    // write number
552      pos =i;
553   }
554
555
556
557      //-------------------------------------------------------------------------------------------------------------------
558      //   conversion routine
559      //
560
561   //----------------------------------------------------------------------------------------------------------------------
562   // load file <src> and write it as HTML to file <des>
563   int TConv2HTML::Convert(ifstream& src, ofstream& des, const bool& f_Stop, int& progress
564                , const char*const& szSrcFileName, const char*const& szBackLink)
565   {
566      // 1. initialize the variables needed by TConv2HTML::WriteItem() and others
567      lastType = TItemStyle::Identifier;
568      col      = 0;
569      nSpaces  = 0;
570      nLines   = 1;     // note: inserts an empty line - also ensures correct indents of first non empty HTML line
571      line     = 1;     // line counter
572
573
574      // 2. write HTML header
575      WriteHeader(des, szSrcFileName, szBackLink);
576
577
578      // 3. initialize
579      f_MultiLinePreproc  = false;                    // flag: multiline preprocessor directive
580      f_MultiLineComment = false;                     // flag: multiline comment
581      f_MultiLineString   = false;                    // flag: multiline string
582
583      IdType = TItemStyle::Identifier;                // used to map type identifier to any other type
584      TStdList<const TLanguage::TInfo*> exchInfo;     // list with identifier type exchange info
585      int nEndSeq;                                    // size of current end sequence
586
587      char szLine[MAX_LEN_LINE];          // linebuffer
588      int pos;                            // position in linebuffer
589
590
591
592      // 4. read all lines until eof occurs (to be more precise: the stream is checked for a failstate) or until stop flag
593      //    is set from caller to abort
594      while(src.fail()==0 && !f_Stop)
595      {
596         // read one line
597         // note: the same as getline() but multiple empty liney are not ignored. Bug of builder 5.0.!
598         src.get(szLine, MAX_LEN_LINE);
599         int len = src.gcount();          // number of characters in line without the terminating '\0'
600                                          // note: szLine[len] is the terminating '\0'
601         src.get();                       // get next character (most probable '\n' (endl))
602
603         // ini
604         pos = 0;                         // reset line position
605         progress += len+1;               // increment progress counter  note: '+1' cause terminating '\0' also counts
606         nItems = -1;                     // reset item counter
607
608
609         //----------------------------------------------------------------------------------------------------------------
610         // parsing loop: identify all objects in the line
611         while(szLine[pos]!='\0')         // until end of line ...
612         {
613            // a) check end of identifier type exchange
614            if(IdType!=TItemStyle::Identifier)
615               if(TLanguage::SequenceStartsString(&szLine[pos], exchInfo.Get()->szEndSeq, nEndSeq))
616               {
617                  exchInfo.Del();                                                // ... delete list entry
618
619                  if(exchInfo.Size()==0)                                         // if list is empty ....
620                     IdType = TItemStyle::Identifier;                            // restore original type
621                  else
622                     IdType = exchInfo.Get(exchInfo.Size()-1)->type2;            // else restore previous type
623               }
624
625            // b) continue multiline comment
626            if(f_MultiLineComment)
627            {
628               ProcessComment(des, szLine, pos, len, 0);
629               continue;
630            }
631
632            // c) continue multiline string or check for begin of new string
633            if(f_MultiLineString || szLine[pos]==lang->String() || szLine[pos]==lang->Character())
634            {
635               ProcessString(des, szLine, pos, len);
636               continue;
637            }
638
639            // d) continue multiline pre-processor directive
640            if(f_MultiLinePreproc)
641            {
642               ProcessPreproc(szLine, pos, des, len, 0);
643               continue;
644            }
645
646            // f) check for begin of multiline comment
647            int h = lang->StartsMultiLineComment(&szLine[pos]);
648            if(h>0)
649            {
650               ProcessComment(des, szLine, pos, len, h);
651               continue;
652            }
653
654            // h) check for single line comment
655            if(lang->StartsSingleLineComment(&szLine[pos])>0)
656            {
657               WriteItem(des, TItemStyle::Comment, &szLine[pos], len-pos);   // write comment
658               break;                                                        // line is complete, so ...
659            }
660
661            //-------------------------------------------------------------------------------------------------------------
662            // g) check for spaces and tabs
663            if(Check4Spaces(szLine, pos))
664            {
665               while(Check4Spaces(szLine, pos));      // note: check for more spaces ... maybe faster
666               continue;
667            }
668
669            //-------------------------------------------------------------------------------------------------------------
670            // determine length of name/keyword - first character irrelevant, then accept '_', all numbers [0..9], all
671            // characters [A..Z] and [a..z] and language specific symbols that may be within strings
672            int i;
673            for(i=pos+1;i<len;i++)
674               if(szLine[i]!='_' && !IsAlpha(szLine[i]) && !IsDigit(szLine[i]) && !lang->SymbolMayBeWithinString(szLine[i]))
675                  break;
676            int nChar = i-pos;   // size of name/keyword
677
678
679            //-------------------------------------------------------------------------------------------------------------
680            // m) identify string type (keyword, custom 1 or custom 2) and write it
681
682            // temporarily terminate string
683            char cTmp = szLine[i];
684            szLine[i] = '\0';
685
686            // determine if it's a keyword
687            if(lang->IsKeyword(&szLine[pos]))
688            {
689               WriteItem(des, TItemStyle::Keyword, &szLine[pos], nChar);   // write item
690               pos += nChar;                                               // increment line position
691               szLine[i] = cTmp;         // restore
692               continue;
693            }
694
695            // determine if it's a user defined word
696            if(lang->IsUserWord(&szLine[pos]))
697            {
698               const TLanguage::TInfo* info = lang->WordListInfo();
699               WriteItem(des, info->type1, &szLine[pos], nChar);           // write item
700
701               pos += nChar;                                               // increment line position
702               szLine[i] = cTmp;         // restore
703
704               if(info->type2>=0)                                 // if word list starts identifier type exchange
705               {
706                  exchInfo.Ins() = info;                          // insert new identifier exchange info in list
707                  nEndSeq = SizeOfString(info->szEndSeq);         // calculate size of current end sequence
708                  IdType = info->type2;                           // set the new type
709               }
710               continue;
711            }
712            szLine[i] = cTmp;         // restore
713
714
715            //-------------------------------------------------------------------------------------------------------------
716            // e) check for regex
717            h = lang->StartsWithRegex(&szLine[pos]);
718            if(h>0)
719            {
720               const TLanguage::TInfo* info = lang->RegexInfo();     // abbreviation
721               WriteItem(des, info->type1, &szLine[pos], h);         // write item
722               pos += h;                                             // increment line position
723
724               if(info->type2>=0)                                 // if regex starts identifier type exchange
725               {
726                  exchInfo.Ins() = info;                          // insert new identifier exchange info in list
727                  nEndSeq = SizeOfString(info->szEndSeq);         // calculate size of current end sequence
728                  IdType = info->type2;                           // set the new type
729               }
730               continue;
731            }
732
733
734            // k) check for pre-processor directive
735            if(nItems<=0 && (h=lang->StartsPreproc(&szLine[pos], nChar))>0)
736            {
737               ProcessPreproc(szLine, pos, des, len, h);
738               continue;
739            }
740
741            // i) check for symbol
742            if(lang->IsSymbol(szLine[pos]))
743            {
744               WriteItem(des, TItemStyle::Symbol, &szLine[pos++], 1);           // write symbol
745               continue;
746            }
747
748            // j) check for number
749            if(IsDigit(szLine[pos]))
750            {
751               ProcessNumber(des, szLine, pos, len);
752               continue;
753            }
754
755            // identifier
756            WriteItem(des, IdType, &szLine[pos], nChar);  // write item
757            pos += nChar;                                 // increment line position
758
759         } // end of the parsing loop
760
761
762         VirtuallyWriteLF(des);        // write line feed (lf)
763         if(des.fail()!=0)             // check if the outfile is in a failstate and return if true
764            return WRITE_FAILED;
765
766      }
767
768      // 5. close all opened HTML tags
769      CloseHtmlTags(des);
770
771      // 6. write footer
772      WriteFooter(des, f_Stop);
773
774      return OK;   // end function convert()
775   }

Top