The rest of the direct-to-backend code. Not tested yet.
[external/ragel.git] / ragel / xmlcodegen.cpp
1 /*
2  *  Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
3  */
4
5 /*  This file is part of Ragel.
6  *
7  *  Ragel is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  * 
12  *  Ragel is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  * 
17  *  You should have received a copy of the GNU General Public License
18  *  along with Ragel; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
20  */
21
22
23 #include "ragel.h"
24 #include "xmlcodegen.h"
25 #include "xmlparse.h"
26 #include "parsedata.h"
27 #include "fsmgraph.h"
28 #include "gendata.h"
29 #include <string.h>
30
31 using namespace std;
32
33 XMLCodeGen::XMLCodeGen( char *fsmName, ParseData *pd, FsmAp *fsm, 
34                 std::ostream &out, XmlParser &xmlParser )
35 :
36         fsmName(fsmName),
37         pd(pd),
38         fsm(fsm),
39         out(out),
40         xmlParser(xmlParser),
41         nextActionTableId(0)
42 {
43 }
44
45
46 void XMLCodeGen::writeActionList()
47 {
48         /* Determine which actions to write. */
49         int nextActionId = 0;
50         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
51                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
52                         act->actionId = nextActionId++;
53         }
54
55         /* Write the list. */
56         out << "    <action_list length=\"" << nextActionId << "\">\n";
57         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
58                 if ( act->actionId >= 0 )
59                         writeAction( act );
60         }
61         out << "    </action_list>\n";
62 }
63
64 void XMLCodeGen::writeActionTableList()
65 {
66         /* Must first order the action tables based on their id. */
67         int numTables = nextActionTableId;
68         RedActionTable **tables = new RedActionTable*[numTables];
69         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
70                 tables[at->id] = at;
71
72         out << "    <action_table_list length=\"" << numTables << "\">\n";
73         for ( int t = 0; t < numTables; t++ ) {
74                 out << "      <action_table id=\"" << t << "\" length=\"" << 
75                                 tables[t]->key.length() << "\">";
76                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
77                         out << atel->value->actionId;
78                         if ( ! atel.last() )
79                                 out << " ";
80                 }
81                 out << "</action_table>\n";
82         }
83         out << "    </action_table_list>\n";
84
85         delete[] tables;
86 }
87
88 void XMLCodeGen::reduceActionTables()
89 {
90         /* Reduce the actions tables to a set. */
91         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
92                 RedActionTable *actionTable = 0;
93
94                 /* Reduce To State Actions. */
95                 if ( st->toStateActionTable.length() > 0 ) {
96                         if ( actionTableMap.insert( st->toStateActionTable, &actionTable ) )
97                                 actionTable->id = nextActionTableId++;
98                 }
99
100                 /* Reduce From State Actions. */
101                 if ( st->fromStateActionTable.length() > 0 ) {
102                         if ( actionTableMap.insert( st->fromStateActionTable, &actionTable ) )
103                                 actionTable->id = nextActionTableId++;
104                 }
105
106                 /* Reduce EOF actions. */
107                 if ( st->eofActionTable.length() > 0 ) {
108                         if ( actionTableMap.insert( st->eofActionTable, &actionTable ) )
109                                 actionTable->id = nextActionTableId++;
110                 }
111
112                 /* Loop the transitions and reduce their actions. */
113                 for ( TransList::Iter trans = st->outList; trans.lte(); trans++ ) {
114                         if ( trans->actionTable.length() > 0 ) {
115                                 if ( actionTableMap.insert( trans->actionTable, &actionTable ) )
116                                         actionTable->id = nextActionTableId++;
117                         }
118                 }
119         }
120 }
121
122 void XMLCodeGen::appendTrans( TransListVect &outList, Key lowKey, 
123                 Key highKey, TransAp *trans )
124 {
125         if ( trans->toState != 0 || trans->actionTable.length() > 0 )
126                 outList.append( TransEl( lowKey, highKey, trans ) );
127 }
128
129 void XMLCodeGen::writeKey( Key key )
130 {
131         if ( keyOps->isSigned )
132                 out << key.getVal();
133         else
134                 out << (unsigned long) key.getVal();
135 }
136
137 void XMLCodeGen::writeTrans( Key lowKey, Key highKey, TransAp *trans )
138 {
139         /* First reduce the action. */
140         RedActionTable *actionTable = 0;
141         if ( trans->actionTable.length() > 0 )
142                 actionTable = actionTableMap.find( trans->actionTable );
143
144         /* Write the transition. */
145         out << "        <t>";
146         writeKey( lowKey );
147         out << " ";
148         writeKey( highKey );
149
150         if ( trans->toState != 0 )
151                 out << " " << trans->toState->alg.stateNum;
152         else
153                 out << " x";
154
155         if ( actionTable != 0 )
156                 out << " " << actionTable->id;
157         else
158                 out << " x";
159         out << "</t>\n";
160 }
161
162 void XMLCodeGen::writeTransList( StateAp *state )
163 {
164         TransListVect outList;
165
166         /* If there is only are no ranges the task is simple. */
167         if ( state->outList.length() > 0 ) {
168                 /* Loop each source range. */
169                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
170                         /* Reduce the transition. If it reduced to anything then add it. */
171                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
172                 }
173         }
174
175         out << "      <trans_list length=\"" << outList.length() << "\">\n";
176         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
177                 writeTrans( tvi->lowKey, tvi->highKey, tvi->value );
178         out << "      </trans_list>\n";
179 }
180
181 void XMLCodeGen::writeEofTrans( StateAp *state )
182 {
183         RedActionTable *eofActions = 0;
184         if ( state->eofActionTable.length() > 0 )
185                 eofActions = actionTableMap.find( state->eofActionTable );
186         
187         /* The <eof_t> is used when there is an eof target, otherwise the eof
188          * action goes into state actions. */
189         if ( state->eofTarget != 0 ) {
190                 out << "      <eof_t>" << state->eofTarget->alg.stateNum;
191
192                 if ( eofActions != 0 )
193                         out << " " << eofActions->id;
194                 else
195                         out << " x"; 
196
197                 out << "</eof_t>" << endl;
198         }
199 }
200
201 void XMLCodeGen::writeText( InlineItem *item )
202 {
203         if ( item->prev == 0 || item->prev->type != InlineItem::Text )
204                 out << "<text>";
205         xmlEscapeHost( out, item->data, strlen(item->data) );
206         if ( item->next == 0 || item->next->type != InlineItem::Text )
207                 out << "</text>";
208 }
209
210 void XMLCodeGen::writeGoto( InlineItem *item )
211 {
212         if ( pd->generatingSectionSubset )
213                 out << "<goto>-1</goto>";
214         else {
215                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
216                 out << "<goto>" << targ->value->alg.stateNum << "</goto>";
217         }
218 }
219
220 void XMLCodeGen::writeCall( InlineItem *item )
221 {
222         if ( pd->generatingSectionSubset )
223                 out << "<call>-1</call>";
224         else {
225                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
226                 out << "<call>" << targ->value->alg.stateNum << "</call>";
227         }
228 }
229
230 void XMLCodeGen::writeNext( InlineItem *item )
231 {
232         if ( pd->generatingSectionSubset )
233                 out << "<next>-1</next>";
234         else {
235                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
236                 out << "<next>" << targ->value->alg.stateNum << "</next>";
237         }
238 }
239
240 void XMLCodeGen::writeGotoExpr( InlineItem *item )
241 {
242         out << "<goto_expr>";
243         writeInlineList( item->children );
244         out << "</goto_expr>";
245 }
246
247 void XMLCodeGen::writeCallExpr( InlineItem *item )
248 {
249         out << "<call_expr>";
250         writeInlineList( item->children );
251         out << "</call_expr>";
252 }
253
254 void XMLCodeGen::writeNextExpr( InlineItem *item )
255 {
256         out << "<next_expr>";
257         writeInlineList( item->children );
258         out << "</next_expr>";
259 }
260
261 void XMLCodeGen::writeEntry( InlineItem *item )
262 {
263         if ( pd->generatingSectionSubset )
264                 out << "<entry>-1</entry>";
265         else {
266                 EntryMapEl *targ = fsm->entryPoints.find( item->nameTarg->id );
267                 out << "<entry>" << targ->value->alg.stateNum << "</entry>";
268         }
269 }
270
271 void XMLCodeGen::writeActionExec( InlineItem *item )
272 {
273         out << "<exec>";
274         writeInlineList( item->children );
275         out << "</exec>";
276 }
277
278 void XMLCodeGen::writeLmOnLast( InlineItem *item )
279 {
280         out << "<set_tokend>1</set_tokend>";
281
282         if ( item->longestMatchPart->action != 0 ) {
283                 out << "<sub_action>";
284                 writeInlineList( item->longestMatchPart->action->inlineList );
285                 out << "</sub_action>";
286         }
287 }
288
289 void XMLCodeGen::writeLmOnNext( InlineItem *item )
290 {
291         out << "<set_tokend>0</set_tokend>";
292         out << "<hold></hold>";
293
294         if ( item->longestMatchPart->action != 0 ) {
295                 out << "<sub_action>";
296                 writeInlineList( item->longestMatchPart->action->inlineList );
297                 out << "</sub_action>";
298         }
299 }
300
301 void XMLCodeGen::writeLmOnLagBehind( InlineItem *item )
302 {
303         out << "<exec><get_tokend></get_tokend></exec>";
304
305         if ( item->longestMatchPart->action != 0 ) {
306                 out << "<sub_action>";
307                 writeInlineList( item->longestMatchPart->action->inlineList );
308                 out << "</sub_action>";
309         }
310 }
311
312 void XMLCodeGen::writeLmSwitch( InlineItem *item )
313 {
314         LongestMatch *longestMatch = item->longestMatch;
315         out << "<lm_switch>\n";
316
317         /* We can't put the <exec> here because we may need to handle the error
318          * case and in that case p should not be changed. Instead use a default
319          * label in the switch to adjust p when user actions are not set. An id of
320          * -1 indicates the default. */
321
322         if ( longestMatch->lmSwitchHandlesError ) {
323                 /* If the switch handles error then we should have also forced the
324                  * error state. */
325                 assert( fsm->errState != 0 );
326
327                 out << "        <sub_action id=\"0\">";
328                 out << "<goto>" << fsm->errState->alg.stateNum << "</goto>";
329                 out << "</sub_action>\n";
330         }
331         
332         bool needDefault = false;
333         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
334                 if ( lmi->inLmSelect ) {
335                         if ( lmi->action == 0 )
336                                 needDefault = true;
337                         else {
338                                 /* Open the action. Write it with the context that sets up _p 
339                                  * when doing control flow changes from inside the machine. */
340                                 out << "        <sub_action id=\"" << lmi->longestMatchId << "\">";
341                                 out << "<exec><get_tokend></get_tokend></exec>";
342                                 writeInlineList( lmi->action->inlineList );
343                                 out << "</sub_action>\n";
344                         }
345                 }
346         }
347
348         if ( needDefault ) {
349                 out << "        <sub_action id=\"-1\"><exec><get_tokend>"
350                                 "</get_tokend></exec></sub_action>\n";
351         }
352
353         out << "    </lm_switch>";
354 }
355
356 void XMLCodeGen::writeInlineList( InlineList *inlineList )
357 {
358         for ( InlineList::Iter item = *inlineList; item.lte(); item++ ) {
359                 switch ( item->type ) {
360                 case InlineItem::Text:
361                         writeText( item );
362                         break;
363                 case InlineItem::Goto:
364                         writeGoto( item );
365                         break;
366                 case InlineItem::GotoExpr:
367                         writeGotoExpr( item );
368                         break;
369                 case InlineItem::Call:
370                         writeCall( item );
371                         break;
372                 case InlineItem::CallExpr:
373                         writeCallExpr( item );
374                         break;
375                 case InlineItem::Next:
376                         writeNext( item );
377                         break;
378                 case InlineItem::NextExpr:
379                         writeNextExpr( item );
380                         break;
381                 case InlineItem::Break:
382                         out << "<break></break>";
383                         break;
384                 case InlineItem::Ret: 
385                         out << "<ret></ret>";
386                         break;
387                 case InlineItem::PChar:
388                         out << "<pchar></pchar>";
389                         break;
390                 case InlineItem::Char: 
391                         out << "<char></char>";
392                         break;
393                 case InlineItem::Curs: 
394                         out << "<curs></curs>";
395                         break;
396                 case InlineItem::Targs: 
397                         out << "<targs></targs>";
398                         break;
399                 case InlineItem::Entry:
400                         writeEntry( item );
401                         break;
402
403                 case InlineItem::Hold:
404                         out << "<hold></hold>";
405                         break;
406                 case InlineItem::Exec:
407                         writeActionExec( item );
408                         break;
409
410                 case InlineItem::LmSetActId:
411                         out << "<set_act>" << 
412                                         item->longestMatchPart->longestMatchId << 
413                                         "</set_act>";
414                         break;
415                 case InlineItem::LmSetTokEnd:
416                         out << "<set_tokend>1</set_tokend>";
417                         break;
418
419                 case InlineItem::LmOnLast:
420                         writeLmOnLast( item );
421                         break;
422                 case InlineItem::LmOnNext:
423                         writeLmOnNext( item );
424                         break;
425                 case InlineItem::LmOnLagBehind:
426                         writeLmOnLagBehind( item );
427                         break;
428                 case InlineItem::LmSwitch: 
429                         writeLmSwitch( item );
430                         break;
431
432                 case InlineItem::LmInitAct:
433                         out << "<init_act></init_act>";
434                         break;
435                 case InlineItem::LmInitTokStart:
436                         out << "<init_tokstart></init_tokstart>";
437                         break;
438                 case InlineItem::LmSetTokStart:
439                         out << "<set_tokstart></set_tokstart>";
440                         break;
441                 }
442         }
443 }
444
445 void XMLCodeGen::makeKey( GenInlineList *outList, Key key )
446 {
447 }
448
449 void XMLCodeGen::makeText( GenInlineList *outList, InlineItem *item )
450 {
451         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Text );
452         inlineItem->data = item->data;
453
454         outList->append( inlineItem );
455 }
456
457 void XMLCodeGen::makeTargetItem( GenInlineList *outList, long targetId, GenInlineItem::Type type )
458 {
459         long targetState;
460         if ( pd->generatingSectionSubset )
461                 targetState = -1;
462         else {
463                 EntryMapEl *targ = fsm->entryPoints.find( targetId );
464                 targetState = targ->value->alg.stateNum;
465         }
466
467         /* Make the item. */
468         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), type );
469         inlineItem->targId = targetState;
470         outList->append( inlineItem );
471 }
472
473 /* Make a sublist item with a given type. */
474 void XMLCodeGen::makeSubList( GenInlineList *outList, 
475                 InlineList *inlineList, GenInlineItem::Type type )
476 {
477         /* Fill the sub list. */
478         GenInlineList *subList = new GenInlineList;
479         makeGenInlineList( subList, inlineList );
480
481         /* Make the item. */
482         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), type );
483         inlineItem->children = subList;
484         outList->append( inlineItem );
485 }
486
487 void XMLCodeGen::makeLmOnLast( GenInlineList *outList, InlineItem *item )
488 {
489         makeSetTokend( outList, 1 );
490
491         if ( item->longestMatchPart->action != 0 ) {
492                 makeSubList( outList, 
493                                 item->longestMatchPart->action->inlineList, 
494                                 GenInlineItem::SubAction );
495         }
496 }
497
498 void XMLCodeGen::makeLmOnNext( GenInlineList *outList, InlineItem *item )
499 {
500         makeSetTokend( outList, 0 );
501         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Hold ) );
502
503         if ( item->longestMatchPart->action != 0 ) {
504                 makeSubList( outList, 
505                         item->longestMatchPart->action->inlineList,
506                         GenInlineItem::SubAction );
507         }
508 }
509
510 void XMLCodeGen::makeExecGetTokend( GenInlineList *outList )
511 {
512         /* Make the Exec item. */
513         GenInlineItem *execItem = new GenInlineItem( GenInputLoc(), GenInlineItem::Exec );
514         execItem->children = new GenInlineList;
515
516         /* Make the GetTokEnd */
517         GenInlineItem *getTokend = new GenInlineItem( GenInputLoc(), GenInlineItem::LmGetTokEnd );
518         execItem->children->append( getTokend );
519
520         outList->append( execItem );
521 }
522
523 void XMLCodeGen::makeLmOnLagBehind( GenInlineList *outList, InlineItem *item )
524 {
525         /* Jump to the tokend. */
526         makeExecGetTokend( outList );
527
528         if ( item->longestMatchPart->action != 0 ) {
529                 makeSubList( outList,
530                         item->longestMatchPart->action->inlineList,
531                         GenInlineItem::SubAction );
532         }
533 }
534
535 void XMLCodeGen::makeLmSwitch( GenInlineList *outList, InlineItem *item )
536 {
537         GenInlineItem *lmSwitch = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSwitch );
538         GenInlineList *lmList = lmSwitch->children = new GenInlineList;
539         LongestMatch *longestMatch = item->longestMatch;
540
541         /* We can't put the <exec> here because we may need to handle the error
542          * case and in that case p should not be changed. Instead use a default
543          * label in the switch to adjust p when user actions are not set. An id of
544          * -1 indicates the default. */
545
546         if ( longestMatch->lmSwitchHandlesError ) {
547                 /* If the switch handles error then we should have also forced the
548                  * error state. */
549                 assert( fsm->errState != 0 );
550
551                 GenInlineItem *errCase = new GenInlineItem( GenInputLoc(), GenInlineItem::SubAction );
552                 errCase->lmId = 0;
553                 errCase->children = new GenInlineList;
554
555                 makeTargetItem( errCase->children, 
556                                 fsm->errState->alg.stateNum, GenInlineItem::Goto );
557
558                 lmList->append( errCase );
559         }
560         
561         bool needDefault = false;
562         for ( LmPartList::Iter lmi = *longestMatch->longestMatchList; lmi.lte(); lmi++ ) {
563                 if ( lmi->inLmSelect ) {
564                         if ( lmi->action == 0 )
565                                 needDefault = true;
566                         else {
567                                 /* Open the action. Write it with the context that sets up _p 
568                                  * when doing control flow changes from inside the machine. */
569                                 GenInlineItem *lmCase = new GenInlineItem( GenInputLoc(), 
570                                                 GenInlineItem::SubAction );
571                                 lmCase->lmId = lmi->longestMatchId;
572                                 lmCase->children = new GenInlineList;
573
574                                 makeExecGetTokend( lmCase->children );
575                                 makeGenInlineList( lmCase->children, lmi->action->inlineList );
576
577                                 lmList->append( lmCase );
578                         }
579                 }
580         }
581
582         if ( needDefault ) {
583                 GenInlineItem *defCase = new GenInlineItem( GenInputLoc(), 
584                                 GenInlineItem::SubAction );
585                 defCase->lmId = -1;
586                 defCase->children = new GenInlineList;
587
588                 makeExecGetTokend( defCase->children );
589
590                 lmList->append( defCase );
591         }
592
593         outList->append( lmSwitch );
594 }
595
596 void XMLCodeGen::makeSetTokend( GenInlineList *outList, long offset )
597 {
598         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokEnd );
599         inlineItem->offset = offset;
600         outList->append( inlineItem );
601 }
602
603 void XMLCodeGen::makeSetAct( GenInlineList *outList, long lmId )
604 {
605         GenInlineItem *inlineItem = new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetActId );
606         inlineItem->lmId = lmId;
607         outList->append( inlineItem );
608 }
609
610 void XMLCodeGen::makeGenInlineList( GenInlineList *outList, InlineList *inList )
611 {
612         for ( InlineList::Iter item = *inList; item.lte(); item++ ) {
613                 switch ( item->type ) {
614                 case InlineItem::Text:
615                         makeText( outList, item );
616                         break;
617                 case InlineItem::Goto:
618                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Goto );
619                         break;
620                 case InlineItem::GotoExpr:
621                         makeSubList( outList, item->children, GenInlineItem::GotoExpr );
622                         break;
623                 case InlineItem::Call:
624                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Call );
625                         break;
626                 case InlineItem::CallExpr:
627                         makeSubList( outList, item->children, GenInlineItem::CallExpr );
628                         break;
629                 case InlineItem::Next:
630                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Next );
631                         break;
632                 case InlineItem::NextExpr:
633                         makeSubList( outList, item->children, GenInlineItem::NextExpr );
634                         break;
635                 case InlineItem::Break:
636                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Break ) );
637                         break;
638                 case InlineItem::Ret: 
639                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Ret ) );
640                         break;
641                 case InlineItem::PChar:
642                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::PChar ) );
643                         break;
644                 case InlineItem::Char: 
645                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Char ) );
646                         break;
647                 case InlineItem::Curs: 
648                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Curs ) );
649                         break;
650                 case InlineItem::Targs: 
651                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Targs ) );
652                         break;
653                 case InlineItem::Entry:
654                         makeTargetItem( outList, item->nameTarg->id, GenInlineItem::Entry );
655                         break;
656
657                 case InlineItem::Hold:
658                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::Hold ) );
659                         break;
660                 case InlineItem::Exec:
661                         makeSubList( outList, item->children, GenInlineItem::Exec );
662                         break;
663
664                 case InlineItem::LmSetActId:
665                         makeSetAct( outList, item->longestMatchPart->longestMatchId );
666                         break;
667                 case InlineItem::LmSetTokEnd:
668                         makeSetTokend( outList, 1 );
669                         break;
670
671                 case InlineItem::LmOnLast:
672                         makeLmOnLast( outList, item );
673                         break;
674                 case InlineItem::LmOnNext:
675                         makeLmOnNext( outList, item );
676                         break;
677                 case InlineItem::LmOnLagBehind:
678                         makeLmOnLagBehind( outList, item );
679                         break;
680                 case InlineItem::LmSwitch: 
681                         makeLmSwitch( outList, item );
682                         break;
683
684                 case InlineItem::LmInitAct:
685                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitAct ) );
686                         break;
687                 case InlineItem::LmInitTokStart:
688                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::LmInitTokStart ) );
689                         break;
690                 case InlineItem::LmSetTokStart:
691                         outList->append( new GenInlineItem( GenInputLoc(), GenInlineItem::LmSetTokStart ) );
692                         xmlParser.cgd->hasLongestMatch = true;
693                         break;
694                 }
695         }
696 }
697
698
699 void XMLCodeGen::writeAction( Action *action )
700 {
701         out << "      <action id=\"" << action->actionId << "\"";
702         if ( action->name != 0 ) 
703                 out << " name=\"" << action->name << "\"";
704         out << " line=\"" << action->loc.line << "\" col=\"" << action->loc.col << "\">";
705         writeInlineList( action->inlineList );
706         out << "</action>\n";
707 }
708
709 void xmlEscapeHost( std::ostream &out, char *data, long len )
710 {
711         char *end = data + len;
712         while ( data != end ) {
713                 switch ( *data ) {
714                 case '<': out << "&lt;"; break;
715                 case '>': out << "&gt;"; break;
716                 case '&': out << "&amp;"; break;
717                 default: out << *data; break;
718                 }
719                 data += 1;
720         }
721 }
722
723 void XMLCodeGen::writeStateActions( StateAp *state )
724 {
725         RedActionTable *toStateActions = 0;
726         if ( state->toStateActionTable.length() > 0 )
727                 toStateActions = actionTableMap.find( state->toStateActionTable );
728
729         RedActionTable *fromStateActions = 0;
730         if ( state->fromStateActionTable.length() > 0 )
731                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
732
733         /* EOF actions go out here only if the state has no eof target. If it has
734          * an eof target then an eof transition will be used instead. */
735         RedActionTable *eofActions = 0;
736         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
737                 eofActions = actionTableMap.find( state->eofActionTable );
738         
739         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
740                 out << "      <state_actions>";
741                 if ( toStateActions != 0 )
742                         out << toStateActions->id;
743                 else
744                         out << "x";
745
746                 if ( fromStateActions != 0 )
747                         out << " " << fromStateActions->id;
748                 else
749                         out << " x";
750
751                 if ( eofActions != 0 )
752                         out << " " << eofActions->id;
753                 else
754                         out << " x";
755
756                 out << "</state_actions>\n";
757         }
758 }
759
760 void XMLCodeGen::writeStateConditions( StateAp *state )
761 {
762         if ( state->stateCondList.length() > 0 ) {
763                 out << "      <cond_list length=\"" << state->stateCondList.length() << "\">\n";
764                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
765                         out << "        <c>";
766                         writeKey( scdi->lowKey );
767                         out << " ";
768                         writeKey( scdi->highKey );
769                         out << " ";
770                         out << scdi->condSpace->condSpaceId;
771                         out << "</c>\n";
772                 }
773                 out << "      </cond_list>\n";
774         }
775 }
776
777 void XMLCodeGen::writeStateList()
778 {
779         /* Write the list of states. */
780         out << "    <state_list length=\"" << fsm->stateList.length() << "\">\n";
781         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
782                 out << "      <state id=\"" << st->alg.stateNum << "\"";
783                 if ( st->isFinState() )
784                         out << " final=\"t\"";
785                 out << ">\n";
786
787                 writeStateActions( st );
788                 writeEofTrans( st );
789                 writeStateConditions( st );
790                 writeTransList( st );
791
792                 out << "      </state>\n";
793
794                 if ( !st.last() )
795                         out << "\n";
796         }
797         out << "    </state_list>\n";
798 }
799
800 bool XMLCodeGen::writeNameInst( NameInst *nameInst )
801 {
802         bool written = false;
803         if ( nameInst->parent != 0 )
804                 written = writeNameInst( nameInst->parent );
805         
806         if ( nameInst->name != 0 ) {
807                 if ( written )
808                         out << '_';
809                 out << nameInst->name;
810                 written = true;
811         }
812
813         return written;
814 }
815
816 void XMLCodeGen::writeEntryPoints()
817 {
818         /* List of entry points other than start state. */
819         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
820                 out << "    <entry_points";
821                 if ( pd->lmRequiresErrorState )
822                         out << " error=\"t\"";
823                 out << ">\n";
824                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
825                         /* Get the name instantiation from nameIndex. */
826                         NameInst *nameInst = pd->nameIndex[en->key];
827                         StateAp *state = en->value;
828                         out << "      <entry name=\"";
829                         writeNameInst( nameInst );
830                         out << "\">" << state->alg.stateNum << "</entry>\n";
831                 }
832                 out << "    </entry_points>\n";
833         }
834 }
835
836 void XMLCodeGen::writeMachine()
837 {
838         /* Open the machine. */
839         out << "  <machine>\n"; 
840         
841         /* Action tables. */
842         reduceActionTables();
843
844         writeActionList();
845         writeActionTableList();
846         writeConditions();
847
848         /* Start state. */
849         out << "    <start_state>" << fsm->startState->alg.stateNum << 
850                         "</start_state>\n";
851         
852         /* Error state. */
853         if ( fsm->errState != 0 ) {
854                 out << "    <error_state>" << fsm->errState->alg.stateNum << 
855                         "</error_state>\n";
856         }
857
858         writeEntryPoints();
859         writeStateList();
860
861         out << "  </machine>\n";
862 }
863
864
865 void XMLCodeGen::writeConditions()
866 {
867         if ( condData->condSpaceMap.length() > 0 ) {
868                 long nextCondSpaceId = 0;
869                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
870                         cs->condSpaceId = nextCondSpaceId++;
871
872                 out << "    <cond_space_list length=\"" << condData->condSpaceMap.length() << "\">\n";
873                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
874                         out << "      <cond_space id=\"" << cs->condSpaceId << 
875                                 "\" length=\"" << cs->condSet.length() << "\">";
876                         writeKey( cs->baseKey );
877                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
878                                 out << " " << (*csi)->actionId;
879                         out << "</cond_space>\n";
880                 }
881                 out << "    </cond_space_list>\n";
882         }
883 }
884
885 void XMLCodeGen::writeExports()
886 {
887         if ( pd->exportList.length() > 0 ) {
888                 out << "  <exports>\n";
889                 for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ ) {
890                         out << "    <ex name=\"" << exp->name << "\">";
891                         writeKey( exp->key );
892                         out << "</ex>\n";
893                 }
894                 out << "  </exports>\n";
895         }
896 }
897
898 void XMLCodeGen::writeXML()
899 {
900         /* Open the definition. */
901         out << "<ragel_def name=\"" << fsmName << "\">\n";
902
903         /* Alphabet type. */
904         out << "  <alphtype>" << keyOps->alphType->internalName << "</alphtype>\n";
905         
906         /* Getkey expression. */
907         if ( pd->getKeyExpr != 0 ) {
908                 out << "  <getkey>";
909                 writeInlineList( pd->getKeyExpr );
910                 out << "</getkey>\n";
911         }
912
913         /* Access expression. */
914         if ( pd->accessExpr != 0 ) {
915                 out << "  <access>";
916                 writeInlineList( pd->accessExpr );
917                 out << "</access>\n";
918         }
919
920         /* PrePush expression. */
921         if ( pd->prePushExpr != 0 ) {
922                 out << "  <prepush>";
923                 writeInlineList( pd->prePushExpr );
924                 out << "</prepush>\n";
925         }
926
927         /* PostPop expression. */
928         if ( pd->postPopExpr != 0 ) {
929                 out << "  <postpop>";
930                 writeInlineList( pd->postPopExpr );
931                 out << "</postpop>\n";
932         }
933
934         /*
935          * Variable expressions.
936          */
937
938         if ( pd->pExpr != 0 ) {
939                 out << "  <p_expr>";
940                 writeInlineList( pd->pExpr );
941                 out << "</p_expr>\n";
942         }
943         
944         if ( pd->peExpr != 0 ) {
945                 out << "  <pe_expr>";
946                 writeInlineList( pd->peExpr );
947                 out << "</pe_expr>\n";
948         }
949
950         if ( pd->eofExpr != 0 ) {
951                 out << "  <eof_expr>";
952                 writeInlineList( pd->eofExpr );
953                 out << "</eof_expr>\n";
954         }
955         
956         if ( pd->csExpr != 0 ) {
957                 out << "  <cs_expr>";
958                 writeInlineList( pd->csExpr );
959                 out << "</cs_expr>\n";
960         }
961         
962         if ( pd->topExpr != 0 ) {
963                 out << "  <top_expr>";
964                 writeInlineList( pd->topExpr );
965                 out << "</top_expr>\n";
966         }
967         
968         if ( pd->stackExpr != 0 ) {
969                 out << "  <stack_expr>";
970                 writeInlineList( pd->stackExpr );
971                 out << "</stack_expr>\n";
972         }
973         
974         if ( pd->actExpr != 0 ) {
975                 out << "  <act_expr>";
976                 writeInlineList( pd->actExpr );
977                 out << "</act_expr>\n";
978         }
979         
980         if ( pd->tokstartExpr != 0 ) {
981                 out << "  <tokstart_expr>";
982                 writeInlineList( pd->tokstartExpr );
983                 out << "</tokstart_expr>\n";
984         }
985         
986         if ( pd->tokendExpr != 0 ) {
987                 out << "  <tokend_expr>";
988                 writeInlineList( pd->tokendExpr );
989                 out << "</tokend_expr>\n";
990         }
991         
992         if ( pd->dataExpr != 0 ) {
993                 out << "  <data_expr>";
994                 writeInlineList( pd->dataExpr );
995                 out << "</data_expr>\n";
996         }
997         
998         writeExports();
999         
1000         writeMachine();
1001
1002         out <<
1003                 "</ragel_def>\n";
1004 }
1005
1006 void XMLCodeGen::makeExports()
1007 {
1008         for ( ExportList::Iter exp = pd->exportList; exp.lte(); exp++ )
1009                 xmlParser.cgd->exportList.append( new Export( exp->name, exp->key ) );
1010 }
1011
1012 void XMLCodeGen::makeAction( Action *action )
1013 {
1014         GenInlineList *genList = new GenInlineList;
1015         makeGenInlineList( genList, action->inlineList );
1016
1017         xmlParser.cgd->newAction( xmlParser.curAction++, action->name, 
1018                         action->loc.line, action->loc.col, genList );
1019 }
1020
1021
1022 void XMLCodeGen::makeActionList()
1023 {
1024         /* Determine which actions to write. */
1025         int nextActionId = 0;
1026         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1027                 if ( act->numRefs() > 0 || act->numCondRefs > 0 )
1028                         act->actionId = nextActionId++;
1029         }
1030
1031         /* Write the list. */
1032         xmlParser.cgd->initActionList( nextActionId );
1033         xmlParser.curAction = 0;
1034
1035         for ( ActionList::Iter act = pd->actionList; act.lte(); act++ ) {
1036                 if ( act->actionId >= 0 )
1037                         makeAction( act );
1038         }
1039 }
1040
1041 void XMLCodeGen::makeActionTableList()
1042 {
1043         /* Must first order the action tables based on their id. */
1044         int numTables = nextActionTableId;
1045         RedActionTable **tables = new RedActionTable*[numTables];
1046         for ( ActionTableMap::Iter at = actionTableMap; at.lte(); at++ )
1047                 tables[at->id] = at;
1048
1049         xmlParser.cgd->initActionTableList( numTables );
1050         xmlParser.curActionTable = 0;
1051
1052         for ( int t = 0; t < numTables; t++ ) {
1053                 long length = tables[t]->key.length();
1054
1055                 /* Collect the action table. */
1056                 RedAction *redAct = xmlParser.cgd->allActionTables + xmlParser.curActionTable;
1057                 redAct->actListId = xmlParser.curActionTable;
1058                 redAct->key.setAsNew( length );
1059
1060                 for ( ActionTable::Iter atel = tables[t]->key; atel.lte(); atel++ ) {
1061                         redAct->key[atel.pos()].key = 0;
1062                         redAct->key[atel.pos()].value = xmlParser.cgd->allActions + 
1063                                         atel->value->actionId;
1064                 }
1065
1066                 xmlParser.curActionTable += 1;
1067         }
1068
1069         delete[] tables;
1070 }
1071
1072 void XMLCodeGen::makeConditions()
1073 {
1074         if ( condData->condSpaceMap.length() > 0 ) {
1075                 long nextCondSpaceId = 0;
1076                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ )
1077                         cs->condSpaceId = nextCondSpaceId++;
1078
1079                 long listLength = condData->condSpaceMap.length();
1080                 xmlParser.cgd->initCondSpaceList( listLength );
1081                 xmlParser.curCondSpace = 0;
1082
1083                 for ( CondSpaceMap::Iter cs = condData->condSpaceMap; cs.lte(); cs++ ) {
1084                         long id = cs->condSpaceId;
1085                         xmlParser.cgd->newCondSpace( xmlParser.curCondSpace, id, cs->baseKey );
1086                         for ( CondSet::Iter csi = cs->condSet; csi.lte(); csi++ )
1087                                 xmlParser.cgd->condSpaceItem( xmlParser.curCondSpace, (*csi)->actionId );
1088                         xmlParser.curCondSpace += 1;
1089                 }
1090         }
1091 }
1092
1093 bool XMLCodeGen::makeNameInst( std::string &res, NameInst *nameInst )
1094 {
1095         bool written = false;
1096         if ( nameInst->parent != 0 )
1097                 written = makeNameInst( res, nameInst->parent );
1098         
1099         if ( nameInst->name != 0 ) {
1100                 if ( written )
1101                         res += '_';
1102                 res += nameInst->name;
1103                 written = true;
1104         }
1105
1106         return written;
1107 }
1108
1109 void XMLCodeGen::makeEntryPoints()
1110 {
1111         /* List of entry points other than start state. */
1112         if ( fsm->entryPoints.length() > 0 || pd->lmRequiresErrorState ) {
1113                 if ( pd->lmRequiresErrorState )
1114                         xmlParser.cgd->setForcedErrorState();
1115
1116                 for ( EntryMap::Iter en = fsm->entryPoints; en.lte(); en++ ) {
1117                         /* Get the name instantiation from nameIndex. */
1118                         NameInst *nameInst = pd->nameIndex[en->key];
1119                         std::string name;
1120                         makeNameInst( name, nameInst );
1121                         StateAp *state = en->value;
1122                         xmlParser.cgd->addEntryPoint( strdup(name.c_str()), state->alg.stateNum );
1123                 }
1124         }
1125 }
1126
1127 void XMLCodeGen::makeStateActions( StateAp *state )
1128 {
1129         RedActionTable *toStateActions = 0;
1130         if ( state->toStateActionTable.length() > 0 )
1131                 toStateActions = actionTableMap.find( state->toStateActionTable );
1132
1133         RedActionTable *fromStateActions = 0;
1134         if ( state->fromStateActionTable.length() > 0 )
1135                 fromStateActions = actionTableMap.find( state->fromStateActionTable );
1136
1137         /* EOF actions go out here only if the state has no eof target. If it has
1138          * an eof target then an eof transition will be used instead. */
1139         RedActionTable *eofActions = 0;
1140         if ( state->eofTarget == 0 && state->eofActionTable.length() > 0 )
1141                 eofActions = actionTableMap.find( state->eofActionTable );
1142         
1143         if ( toStateActions != 0 || fromStateActions != 0 || eofActions != 0 ) {
1144                 long to = -1;
1145                 if ( toStateActions != 0 )
1146                         to = toStateActions->id;
1147
1148                 long from = -1;
1149                 if ( fromStateActions != 0 )
1150                         from = fromStateActions->id;
1151
1152                 long eof = -1;
1153                 if ( eofActions != 0 )
1154                         eof = eofActions->id;
1155
1156                 xmlParser.cgd->setStateActions( xmlParser.curState, to, from, eof );
1157         }
1158 }
1159
1160 void XMLCodeGen::makeEofTrans( StateAp *state )
1161 {
1162         RedActionTable *eofActions = 0;
1163         if ( state->eofActionTable.length() > 0 )
1164                 eofActions = actionTableMap.find( state->eofActionTable );
1165         
1166         /* The EOF trans is used when there is an eof target, otherwise the eof
1167          * action goes into state actions. */
1168         if ( state->eofTarget != 0 ) {
1169                 long targ = state->eofTarget->alg.stateNum;
1170                 long action = -1;
1171                 if ( eofActions != 0 )
1172                         action = eofActions->id;
1173
1174                 xmlParser.cgd->setEofTrans( xmlParser.curState, targ, action );
1175         }
1176 }
1177
1178 void XMLCodeGen::makeStateConditions( StateAp *state )
1179 {
1180         if ( state->stateCondList.length() > 0 ) {
1181                 long length = state->stateCondList.length();
1182                 xmlParser.cgd->initStateCondList( xmlParser.curState, length );
1183                 xmlParser.curStateCond = 0;
1184
1185                 for ( StateCondList::Iter scdi = state->stateCondList; scdi.lte(); scdi++ ) {
1186                         xmlParser.cgd->addStateCond( xmlParser.curState, scdi->lowKey, scdi->highKey, 
1187                                         scdi->condSpace->condSpaceId );
1188                 }
1189         }
1190 }
1191
1192 void XMLCodeGen::makeTrans( Key lowKey, Key highKey, TransAp *trans )
1193 {
1194         /* First reduce the action. */
1195         RedActionTable *actionTable = 0;
1196         if ( trans->actionTable.length() > 0 )
1197                 actionTable = actionTableMap.find( trans->actionTable );
1198
1199         long targ = -1;
1200         if ( trans->toState != 0 )
1201                 targ = trans->toState->alg.stateNum;
1202
1203         long action = -1;
1204         if ( actionTable != 0 )
1205                 action = actionTable->id;
1206
1207         xmlParser.cgd->newTrans( xmlParser.curState, xmlParser.curTrans++, lowKey, highKey, targ, action );
1208 }
1209
1210
1211 void XMLCodeGen::makeTransList( StateAp *state )
1212 {
1213         TransListVect outList;
1214
1215         /* If there is only are no ranges the task is simple. */
1216         if ( state->outList.length() > 0 ) {
1217                 /* Loop each source range. */
1218                 for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
1219                         /* Reduce the transition. If it reduced to anything then add it. */
1220                         appendTrans( outList, trans->lowKey, trans->highKey, trans );
1221                 }
1222         }
1223
1224         xmlParser.cgd->initTransList( xmlParser.curState, outList.length() );
1225         xmlParser.curTrans = 0;
1226
1227         for ( TransListVect::Iter tvi = outList; tvi.lte(); tvi++ )
1228                 makeTrans( tvi->lowKey, tvi->highKey, tvi->value );
1229
1230         xmlParser.cgd->finishTransList( xmlParser.curState );
1231 }
1232
1233
1234 void XMLCodeGen::makeStateList()
1235 {
1236         /* Write the list of states. */
1237         long length = fsm->stateList.length();
1238         xmlParser.cgd->initStateList( length );
1239         xmlParser.curState = 0;
1240         for ( StateList::Iter st = fsm->stateList; st.lte(); st++ ) {
1241                 makeStateActions( st );
1242                 makeEofTrans( st );
1243                 makeStateConditions( st );
1244                 makeTransList( st );
1245
1246                 long id = st->alg.stateNum;
1247                 xmlParser.cgd->setId( xmlParser.curState, id );
1248
1249                 if ( st->isFinState() )
1250                         xmlParser.cgd->setFinal( xmlParser.curState );
1251
1252                 xmlParser.curState += 1;
1253         }
1254 }
1255
1256
1257 void XMLCodeGen::makeMachine()
1258 {
1259         xmlParser.cgd->createMachine();
1260
1261         /* Action tables. */
1262         reduceActionTables();
1263
1264         makeActionList();
1265         makeActionTableList();
1266         makeConditions();
1267
1268         /* Start State. */
1269         xmlParser.cgd->setStartState( fsm->startState->alg.stateNum );
1270
1271         /* Error state. */
1272         if ( fsm->errState != 0 )
1273                 xmlParser.cgd->setErrorState( fsm->errState->alg.stateNum );
1274
1275         makeEntryPoints();
1276         makeStateList();
1277 }
1278
1279 void XMLCodeGen::makeBackend()
1280 {
1281         /* Open the definition. */
1282         xmlParser.open_ragel_def( fsmName );
1283
1284         /* Alphabet type. */
1285         xmlParser.cgd->setAlphType( keyOps->alphType->internalName );
1286         
1287         /* Getkey expression. */
1288         if ( pd->getKeyExpr != 0 ) {
1289                 xmlParser.cgd->getKeyExpr = new GenInlineList;
1290                 makeGenInlineList( xmlParser.cgd->getKeyExpr, pd->getKeyExpr );
1291         }
1292
1293         /* Access expression. */
1294         if ( pd->accessExpr != 0 ) {
1295                 xmlParser.cgd->accessExpr = new GenInlineList;
1296                 makeGenInlineList( xmlParser.cgd->accessExpr, pd->accessExpr );
1297         }
1298
1299         /* PrePush expression. */
1300         if ( pd->prePushExpr != 0 ) {
1301                 xmlParser.cgd->prePushExpr = new GenInlineList;
1302                 makeGenInlineList( xmlParser.cgd->prePushExpr, pd->prePushExpr );
1303         }
1304
1305         /* PostPop expression. */
1306         if ( pd->postPopExpr != 0 ) {
1307                 xmlParser.cgd->postPopExpr = new GenInlineList;
1308                 makeGenInlineList( xmlParser.cgd->postPopExpr, pd->postPopExpr );
1309         }
1310
1311         /*
1312          * Variable expressions.
1313          */
1314
1315         if ( pd->pExpr != 0 ) {
1316                 xmlParser.cgd->pExpr = new GenInlineList;
1317                 makeGenInlineList( xmlParser.cgd->pExpr, pd->pExpr );
1318         }
1319         
1320         if ( pd->peExpr != 0 ) {
1321                 xmlParser.cgd->peExpr = new GenInlineList;
1322                 makeGenInlineList( xmlParser.cgd->peExpr, pd->peExpr );
1323         }
1324
1325         if ( pd->eofExpr != 0 ) {
1326                 xmlParser.cgd->eofExpr = new GenInlineList;
1327                 makeGenInlineList( xmlParser.cgd->eofExpr, pd->eofExpr );
1328         }
1329         
1330         if ( pd->csExpr != 0 ) {
1331                 xmlParser.cgd->csExpr = new GenInlineList;
1332                 makeGenInlineList( xmlParser.cgd->csExpr, pd->csExpr );
1333         }
1334         
1335         if ( pd->topExpr != 0 ) {
1336                 xmlParser.cgd->topExpr = new GenInlineList;
1337                 makeGenInlineList( xmlParser.cgd->topExpr, pd->topExpr );
1338         }
1339         
1340         if ( pd->stackExpr != 0 ) {
1341                 xmlParser.cgd->stackExpr = new GenInlineList;
1342                 makeGenInlineList( xmlParser.cgd->stackExpr, pd->stackExpr );
1343         }
1344         
1345         if ( pd->actExpr != 0 ) {
1346                 xmlParser.cgd->actExpr = new GenInlineList;
1347                 makeGenInlineList( xmlParser.cgd->actExpr, pd->actExpr );
1348         }
1349         
1350         if ( pd->tokstartExpr != 0 ) {
1351                 xmlParser.cgd->tokstartExpr = new GenInlineList;
1352                 makeGenInlineList( xmlParser.cgd->tokstartExpr, pd->tokstartExpr );
1353         }
1354         
1355         if ( pd->tokendExpr != 0 ) {
1356                 xmlParser.cgd->tokendExpr = new GenInlineList;
1357                 makeGenInlineList( xmlParser.cgd->tokendExpr, pd->tokendExpr );
1358         }
1359         
1360         if ( pd->dataExpr != 0 ) {
1361                 xmlParser.cgd->dataExpr = new GenInlineList;
1362                 makeGenInlineList( xmlParser.cgd->dataExpr, pd->dataExpr );
1363         }
1364         
1365         makeExports();
1366         makeMachine();
1367 }
1368
1369