2 * Copyright 2005-2007 Adrian Thurston <thurston@complang.org>
5 /* This file is part of Ragel.
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.
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.
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
28 CodeGenData *makeCodeGen( const char *sourceFileName, const char *fsmName,
29 ostream &out, bool wantComplete )
33 cgd = dotMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
34 else if ( hostLang == &hostLangC )
35 cgd = cdMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
36 else if ( hostLang == &hostLangD )
37 cgd = cdMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
38 else if ( hostLang == &hostLangJava )
39 cgd = javaMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
40 else if ( hostLang == &hostLangRuby )
41 cgd = rubyMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
42 else if ( hostLang == &hostLangCSharp )
43 cgd = csharpMakeCodeGen( sourceFileName, fsmName, out, wantComplete );
47 void lineDirective( ostream &out, const char *fileName, int line )
50 if ( hostLang == &hostLangC )
51 cdLineDirective( out, fileName, line );
52 else if ( hostLang == &hostLangD )
53 cdLineDirective( out, fileName, line );
54 else if ( hostLang == &hostLangJava )
55 javaLineDirective( out, fileName, line );
56 else if ( hostLang == &hostLangRuby )
57 rubyLineDirective( out, fileName, line );
58 else if ( hostLang == &hostLangCSharp )
59 csharpLineDirective( out, fileName, line );
63 void genLineDirective( ostream &out )
65 std::streambuf *sbuf = out.rdbuf();
66 output_filter *filter = static_cast<output_filter*>(sbuf);
67 lineDirective( out, filter->fileName, filter->line + 1 );
71 /* Total error count. */
72 /* int gblErrorCount = 0; */
74 CodeGenData::CodeGenData( ostream &out )
103 hasLongestMatch(false),
112 void CodeGenData::createMachine()
114 redFsm = new RedFsmAp();
117 void CodeGenData::initActionList( unsigned long length )
119 allActions = new GenAction[length];
120 for ( unsigned long a = 0; a < length; a++ )
121 actionList.append( allActions+a );
124 void CodeGenData::newAction( int anum, const char *name, int line,
125 int col, GenInlineList *inlineList )
127 allActions[anum].actionId = anum;
128 allActions[anum].name = name;
129 allActions[anum].loc.line = line;
130 allActions[anum].loc.col = col;
131 allActions[anum].inlineList = inlineList;
134 void CodeGenData::initActionTableList( unsigned long length )
136 allActionTables = new RedAction[length];
139 void CodeGenData::initStateList( unsigned long length )
141 allStates = new RedStateAp[length];
142 for ( unsigned long s = 0; s < length; s++ )
143 redFsm->stateList.append( allStates+s );
145 /* We get the start state as an offset, set the pointer now. */
146 if ( startState >= 0 )
147 redFsm->startState = allStates + startState;
149 redFsm->errState = allStates + errState;
150 for ( EntryIdVect::Iter en = entryPointIds; en.lte(); en++ )
151 redFsm->entryPoints.insert( allStates + *en );
153 /* The nextStateId is no longer used to assign state ids (they come in set
154 * from the frontend now), however generation code still depends on it.
155 * Should eventually remove this variable. */
156 redFsm->nextStateId = redFsm->stateList.length();
159 void CodeGenData::setStartState( unsigned long startState )
161 this->startState = startState;
164 void CodeGenData::setErrorState( unsigned long errState )
166 this->errState = errState;
169 void CodeGenData::addEntryPoint( char *name, unsigned long entryState )
171 entryPointIds.append( entryState );
172 entryPointNames.append( name );
175 void CodeGenData::initTransList( int snum, unsigned long length )
177 /* Could preallocate the out range to save time growing it. For now do
181 void CodeGenData::newTrans( int snum, int tnum, Key lowKey,
182 Key highKey, long targ, long action )
184 /* Get the current state and range. */
185 RedStateAp *curState = allStates + snum;
186 RedTransList &destRange = curState->outRange;
188 if ( curState == redFsm->errState )
191 /* Make the new transitions. */
192 RedStateAp *targState = targ >= 0 ? (allStates + targ) :
193 wantComplete ? redFsm->getErrorState() : 0;
194 RedAction *actionTable = action >= 0 ? (allActionTables + action) : 0;
195 RedTransAp *trans = redFsm->allocateTrans( targState, actionTable );
196 RedTransEl transEl( lowKey, highKey, trans );
198 if ( wantComplete ) {
199 /* If the machine is to be complete then we need to fill any gaps with
200 * the error transitions. */
201 if ( destRange.length() == 0 ) {
202 /* Range is currently empty. */
203 if ( keyOps->minKey < lowKey ) {
204 /* The first range doesn't start at the low end. */
205 Key fillHighKey = lowKey;
206 fillHighKey.decrement();
208 /* Create the filler with the state's error transition. */
209 RedTransEl newTel( keyOps->minKey, fillHighKey, redFsm->getErrorTrans() );
210 destRange.append( newTel );
214 /* The range list is not empty, get the the last range. */
215 RedTransEl *last = &destRange[destRange.length()-1];
216 Key nextKey = last->highKey;
218 if ( nextKey < lowKey ) {
219 /* There is a gap to fill. Make the high key. */
220 Key fillHighKey = lowKey;
221 fillHighKey.decrement();
223 /* Create the filler with the state's error transtion. */
224 RedTransEl newTel( nextKey, fillHighKey, redFsm->getErrorTrans() );
225 destRange.append( newTel );
230 /* Filler taken care of. Append the range. */
231 destRange.append( RedTransEl( lowKey, highKey, trans ) );
234 void CodeGenData::finishTransList( int snum )
236 /* Get the current state and range. */
237 RedStateAp *curState = allStates + snum;
238 RedTransList &destRange = curState->outRange;
240 if ( curState == redFsm->errState )
243 /* If building a complete machine we may need filler on the end. */
244 if ( wantComplete ) {
245 /* Check if there are any ranges already. */
246 if ( destRange.length() == 0 ) {
247 /* Fill with the whole alphabet. */
248 /* Add the range on the lower and upper bound. */
249 RedTransEl newTel( keyOps->minKey, keyOps->maxKey, redFsm->getErrorTrans() );
250 destRange.append( newTel );
253 /* Get the last and check for a gap on the end. */
254 RedTransEl *last = &destRange[destRange.length()-1];
255 if ( last->highKey < keyOps->maxKey ) {
256 /* Make the high key. */
257 Key fillLowKey = last->highKey;
258 fillLowKey.increment();
260 /* Create the new range with the error trans and append it. */
261 RedTransEl newTel( fillLowKey, keyOps->maxKey, redFsm->getErrorTrans() );
262 destRange.append( newTel );
268 void CodeGenData::setId( int snum, int id )
270 RedStateAp *curState = allStates + snum;
274 void CodeGenData::setFinal( int snum )
276 RedStateAp *curState = allStates + snum;
277 curState->isFinal = true;
281 void CodeGenData::setStateActions( int snum, long toStateAction,
282 long fromStateAction, long eofAction )
284 RedStateAp *curState = allStates + snum;
285 if ( toStateAction >= 0 )
286 curState->toStateAction = allActionTables + toStateAction;
287 if ( fromStateAction >= 0 )
288 curState->fromStateAction = allActionTables + fromStateAction;
289 if ( eofAction >= 0 )
290 curState->eofAction = allActionTables + eofAction;
293 void CodeGenData::setEofTrans( int snum, long eofTarget, long actId )
295 RedStateAp *curState = allStates + snum;
296 RedStateAp *targState = allStates + eofTarget;
297 RedAction *eofAct = allActionTables + actId;
298 curState->eofTrans = redFsm->allocateTrans( targState, eofAct );
301 void CodeGenData::resolveTargetStates( GenInlineList *inlineList )
303 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
304 switch ( item->type ) {
305 case GenInlineItem::Goto: case GenInlineItem::Call:
306 case GenInlineItem::Next: case GenInlineItem::Entry:
307 item->targState = allStates + item->targId;
313 if ( item->children != 0 )
314 resolveTargetStates( item->children );
318 void CodeGenData::closeMachine()
320 for ( GenActionList::Iter a = actionList; a.lte(); a++ )
321 resolveTargetStates( a->inlineList );
323 /* Note that even if we want a complete graph we do not give the error
324 * state a default transition. All machines break out of the processing
325 * loop when in the error state. */
327 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
328 for ( GenStateCondList::Iter sci = st->stateCondList; sci.lte(); sci++ )
329 st->stateCondVect.append( sci );
334 bool CodeGenData::setAlphType( const char *data )
336 HostType *alphType = findAlphTypeInternal( data );
340 thisKeyOps.setAlphType( alphType );
344 void CodeGenData::initCondSpaceList( ulong length )
346 allCondSpaces = new GenCondSpace[length];
347 for ( ulong c = 0; c < length; c++ )
348 condSpaceList.append( allCondSpaces + c );
351 void CodeGenData::newCondSpace( int cnum, int condSpaceId, Key baseKey )
353 GenCondSpace *cond = allCondSpaces + cnum;
354 cond->condSpaceId = condSpaceId;
355 cond->baseKey = baseKey;
358 void CodeGenData::condSpaceItem( int cnum, long condActionId )
360 GenCondSpace *cond = allCondSpaces + cnum;
361 cond->condSet.append( allActions + condActionId );
364 void CodeGenData::initStateCondList( int snum, ulong length )
366 /* Could preallocate these, as we could with transitions. */
369 void CodeGenData::addStateCond( int snum, Key lowKey, Key highKey, long condNum )
371 RedStateAp *curState = allStates + snum;
373 /* Create the new state condition. */
374 GenStateCond *stateCond = new GenStateCond;
375 stateCond->lowKey = lowKey;
376 stateCond->highKey = highKey;
378 /* Assign it a cond space. */
379 GenCondSpace *condSpace = allCondSpaces + condNum;
380 stateCond->condSpace = condSpace;
382 curState->stateCondList.append( stateCond );
386 GenCondSpace *CodeGenData::findCondSpace( Key lowKey, Key highKey )
388 for ( CondSpaceList::Iter cs = condSpaceList; cs.lte(); cs++ ) {
389 Key csHighKey = cs->baseKey;
390 csHighKey += keyOps->alphSize() * (1 << cs->condSet.length());
392 if ( lowKey >= cs->baseKey && highKey <= csHighKey )
398 Condition *CodeGenData::findCondition( Key key )
400 for ( ConditionList::Iter cond = conditionList; cond.lte(); cond++ ) {
401 Key upperKey = cond->baseKey + (1 << cond->condSet.length());
402 if ( cond->baseKey <= key && key <= upperKey )
408 Key CodeGenData::findMaxKey()
410 Key maxKey = keyOps->maxKey;
411 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
412 assert( st->outSingle.length() == 0 );
413 assert( st->defTrans == 0 );
415 long rangeLen = st->outRange.length();
416 if ( rangeLen > 0 ) {
417 Key highKey = st->outRange[rangeLen-1].highKey;
418 if ( highKey > maxKey )
425 void CodeGenData::findFinalActionRefs()
427 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
428 /* Rerence count out of single transitions. */
429 for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) {
430 if ( rtel->value->action != 0 ) {
431 rtel->value->action->numTransRefs += 1;
432 for ( GenActionTable::Iter item = rtel->value->action->key; item.lte(); item++ )
433 item->value->numTransRefs += 1;
437 /* Reference count out of range transitions. */
438 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
439 if ( rtel->value->action != 0 ) {
440 rtel->value->action->numTransRefs += 1;
441 for ( GenActionTable::Iter item = rtel->value->action->key; item.lte(); item++ )
442 item->value->numTransRefs += 1;
446 /* Reference count default transition. */
447 if ( st->defTrans != 0 && st->defTrans->action != 0 ) {
448 st->defTrans->action->numTransRefs += 1;
449 for ( GenActionTable::Iter item = st->defTrans->action->key; item.lte(); item++ )
450 item->value->numTransRefs += 1;
453 /* Reference count eof transitions. */
454 if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) {
455 st->eofTrans->action->numTransRefs += 1;
456 for ( GenActionTable::Iter item = st->eofTrans->action->key; item.lte(); item++ )
457 item->value->numTransRefs += 1;
460 /* Reference count to state actions. */
461 if ( st->toStateAction != 0 ) {
462 st->toStateAction->numToStateRefs += 1;
463 for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ )
464 item->value->numToStateRefs += 1;
467 /* Reference count from state actions. */
468 if ( st->fromStateAction != 0 ) {
469 st->fromStateAction->numFromStateRefs += 1;
470 for ( GenActionTable::Iter item = st->fromStateAction->key; item.lte(); item++ )
471 item->value->numFromStateRefs += 1;
474 /* Reference count EOF actions. */
475 if ( st->eofAction != 0 ) {
476 st->eofAction->numEofRefs += 1;
477 for ( GenActionTable::Iter item = st->eofAction->key; item.lte(); item++ )
478 item->value->numEofRefs += 1;
483 void CodeGenData::analyzeAction( GenAction *act, GenInlineList *inlineList )
485 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
486 /* Only consider actions that are referenced. */
487 if ( act->numRefs() > 0 ) {
488 if ( item->type == GenInlineItem::Goto || item->type == GenInlineItem::GotoExpr )
489 redFsm->bAnyActionGotos = true;
490 else if ( item->type == GenInlineItem::Call || item->type == GenInlineItem::CallExpr )
491 redFsm->bAnyActionCalls = true;
492 else if ( item->type == GenInlineItem::Ret )
493 redFsm->bAnyActionRets = true;
496 /* Check for various things in regular actions. */
497 if ( act->numTransRefs > 0 || act->numToStateRefs > 0 || act->numFromStateRefs > 0 ) {
498 /* Any returns in regular actions? */
499 if ( item->type == GenInlineItem::Ret )
500 redFsm->bAnyRegActionRets = true;
502 /* Any next statements in the regular actions? */
503 if ( item->type == GenInlineItem::Next || item->type == GenInlineItem::NextExpr )
504 redFsm->bAnyRegNextStmt = true;
506 /* Any by value control in regular actions? */
507 if ( item->type == GenInlineItem::CallExpr || item->type == GenInlineItem::GotoExpr )
508 redFsm->bAnyRegActionByValControl = true;
510 /* Any references to the current state in regular actions? */
511 if ( item->type == GenInlineItem::Curs )
512 redFsm->bAnyRegCurStateRef = true;
514 if ( item->type == GenInlineItem::Break )
515 redFsm->bAnyRegBreak = true;
518 if ( item->children != 0 )
519 analyzeAction( act, item->children );
523 void CodeGenData::analyzeActionList( RedAction *redAct, GenInlineList *inlineList )
525 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
526 /* Any next statements in the action table? */
527 if ( item->type == GenInlineItem::Next || item->type == GenInlineItem::NextExpr )
528 redAct->bAnyNextStmt = true;
530 /* Any references to the current state. */
531 if ( item->type == GenInlineItem::Curs )
532 redAct->bAnyCurStateRef = true;
534 if ( item->type == GenInlineItem::Break )
535 redAct->bAnyBreakStmt = true;
537 if ( item->children != 0 )
538 analyzeActionList( redAct, item->children );
542 /* Assign ids to referenced actions. */
543 void CodeGenData::assignActionIds()
545 int nextActionId = 0;
546 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
547 /* Only ever interested in referenced actions. */
548 if ( act->numRefs() > 0 )
549 act->actionId = nextActionId++;
553 void CodeGenData::setValueLimits()
555 redFsm->maxSingleLen = 0;
556 redFsm->maxRangeLen = 0;
557 redFsm->maxKeyOffset = 0;
558 redFsm->maxIndexOffset = 0;
559 redFsm->maxActListId = 0;
560 redFsm->maxActionLoc = 0;
561 redFsm->maxActArrItem = 0;
563 redFsm->maxCondSpan = 0;
564 redFsm->maxFlatIndexOffset = 0;
565 redFsm->maxCondOffset = 0;
566 redFsm->maxCondLen = 0;
567 redFsm->maxCondSpaceId = 0;
568 redFsm->maxCondIndexOffset = 0;
570 /* In both of these cases the 0 index is reserved for no value, so the max
571 * is one more than it would be if they started at 0. */
572 redFsm->maxIndex = redFsm->transSet.length();
573 redFsm->maxCond = condSpaceList.length();
575 /* The nextStateId - 1 is the last state id assigned. */
576 redFsm->maxState = redFsm->nextStateId - 1;
578 for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
579 if ( csi->condSpaceId > redFsm->maxCondSpaceId )
580 redFsm->maxCondSpaceId = csi->condSpaceId;
583 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
584 /* Maximum cond length. */
585 if ( st->stateCondList.length() > redFsm->maxCondLen )
586 redFsm->maxCondLen = st->stateCondList.length();
588 /* Maximum single length. */
589 if ( st->outSingle.length() > redFsm->maxSingleLen )
590 redFsm->maxSingleLen = st->outSingle.length();
592 /* Maximum range length. */
593 if ( st->outRange.length() > redFsm->maxRangeLen )
594 redFsm->maxRangeLen = st->outRange.length();
596 /* The key offset index offset for the state after last is not used, skip it.. */
598 redFsm->maxCondOffset += st->stateCondList.length();
599 redFsm->maxKeyOffset += st->outSingle.length() + st->outRange.length()*2;
600 redFsm->maxIndexOffset += st->outSingle.length() + st->outRange.length() + 2;
604 if ( st->condList != 0 ) {
605 unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
606 if ( span > redFsm->maxCondSpan )
607 redFsm->maxCondSpan = span;
611 if ( st->transList != 0 ) {
612 unsigned long long span = keyOps->span( st->lowKey, st->highKey );
613 if ( span > redFsm->maxSpan )
614 redFsm->maxSpan = span;
617 /* Max cond index offset. */
619 if ( st->condList != 0 )
620 redFsm->maxCondIndexOffset += keyOps->span( st->condLowKey, st->condHighKey );
623 /* Max flat index offset. */
625 if ( st->transList != 0 )
626 redFsm->maxFlatIndexOffset += keyOps->span( st->lowKey, st->highKey );
627 redFsm->maxFlatIndexOffset += 1;
631 for ( GenActionTableMap::Iter at = redFsm->actionMap; at.lte(); at++ ) {
632 /* Maximum id of action lists. */
633 if ( at->actListId+1 > redFsm->maxActListId )
634 redFsm->maxActListId = at->actListId+1;
636 /* Maximum location of items in action array. */
637 if ( at->location+1 > redFsm->maxActionLoc )
638 redFsm->maxActionLoc = at->location+1;
640 /* Maximum values going into the action array. */
641 if ( at->key.length() > redFsm->maxActArrItem )
642 redFsm->maxActArrItem = at->key.length();
643 for ( GenActionTable::Iter item = at->key; item.lte(); item++ ) {
644 if ( item->value->actionId > redFsm->maxActArrItem )
645 redFsm->maxActArrItem = item->value->actionId;
652 /* Gather various info on the machine. */
653 void CodeGenData::analyzeMachine()
655 /* Find the true count of action references. */
656 findFinalActionRefs();
658 /* Check if there are any calls in action code. */
659 for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
660 /* Record the occurrence of various kinds of actions. */
661 if ( act->numToStateRefs > 0 )
662 redFsm->bAnyToStateActions = true;
663 if ( act->numFromStateRefs > 0 )
664 redFsm->bAnyFromStateActions = true;
665 if ( act->numEofRefs > 0 )
666 redFsm->bAnyEofActions = true;
667 if ( act->numTransRefs > 0 )
668 redFsm->bAnyRegActions = true;
670 /* Recurse through the action's parse tree looking for various things. */
671 analyzeAction( act, act->inlineList );
674 /* Analyze reduced action lists. */
675 for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
676 for ( GenActionTable::Iter act = redAct->key; act.lte(); act++ )
677 analyzeActionList( redAct, act->value->inlineList );
680 /* Find states that have transitions with actions that have next
682 for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
683 /* Check any actions out of outSinge. */
684 for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) {
685 if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() )
686 st->bAnyRegCurStateRef = true;
689 /* Check any actions out of outRange. */
690 for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
691 if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() )
692 st->bAnyRegCurStateRef = true;
695 /* Check any action out of default. */
696 if ( st->defTrans != 0 && st->defTrans->action != 0 &&
697 st->defTrans->action->anyCurStateRef() )
698 st->bAnyRegCurStateRef = true;
700 if ( st->stateCondList.length() > 0 )
701 redFsm->bAnyConditions = true;
703 if ( st->eofTrans != 0 )
704 redFsm->bAnyEofTrans = true;
707 /* Assign ids to actions that are referenced. */
710 /* Set the maximums of various values used for deciding types. */
714 void CodeGenData::write_option_error( InputLoc &loc, char *arg )
716 source_warning(loc) << "unrecognized write option \"" << arg << "\"" << endl;
719 void CodeGenData::writeStatement( InputLoc &loc, int nargs, char **args )
721 /* FIXME: This should be moved to the virtual functions in the code
724 * Force a newline. */
726 genLineDirective( out );
728 if ( strcmp( args[0], "data" ) == 0 ) {
729 for ( int i = 1; i < nargs; i++ ) {
730 if ( strcmp( args[i], "noerror" ) == 0 )
732 else if ( strcmp( args[i], "noprefix" ) == 0 )
734 else if ( strcmp( args[i], "nofinal" ) == 0 )
737 write_option_error( loc, args[i] );
741 else if ( strcmp( args[0], "init" ) == 0 ) {
742 for ( int i = 1; i < nargs; i++ ) {
743 if ( strcmp( args[i], "nocs" ) == 0 )
746 write_option_error( loc, args[i] );
750 else if ( strcmp( args[0], "exec" ) == 0 ) {
751 for ( int i = 1; i < nargs; i++ ) {
752 if ( strcmp( args[i], "noend" ) == 0 )
755 write_option_error( loc, args[i] );
759 else if ( strcmp( args[0], "exports" ) == 0 ) {
760 for ( int i = 1; i < nargs; i++ )
761 write_option_error( loc, args[i] );
764 else if ( strcmp( args[0], "start" ) == 0 ) {
765 for ( int i = 1; i < nargs; i++ )
766 write_option_error( loc, args[i] );
769 else if ( strcmp( args[0], "first_final" ) == 0 ) {
770 for ( int i = 1; i < nargs; i++ )
771 write_option_error( loc, args[i] );
774 else if ( strcmp( args[0], "error" ) == 0 ) {
775 for ( int i = 1; i < nargs; i++ )
776 write_option_error( loc, args[i] );
780 /* EMIT An error here. */
781 source_error(loc) << "unrecognized write command \"" <<
782 args[0] << "\"" << endl;
786 ostream &CodeGenData::source_warning( const InputLoc &loc )
788 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
792 ostream &CodeGenData::source_error( const InputLoc &loc )
795 assert( sourceFileName != 0 );
796 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";