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 << "<"; col++; break; // replace
147 case '>' : file << ">"; col++; break;
148 case '&' : file << "&"; col++; break;
149 case '"' : file << """; 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 |