aboutsummaryrefslogtreecommitdiff
path: root/src/builder.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/builder.cpp825
1 files changed, 0 insertions, 825 deletions
diff --git a/src/builder.cpp b/src/builder.cpp
deleted file mode 100644
index 8c3bbbb..0000000
--- a/src/builder.cpp
+++ /dev/null
@@ -1,825 +0,0 @@
1#include <iostream>
2#include <sstream>
3#include <errno.h>
4#include <dirent.h>
5
6#include "builder.h"
7#include "action.h"
8#include "command.h"
9#include "target.h"
10#include "filetarget.h"
11#include "build.tab.h"
12#include "rule.h"
13#include "viewer.h"
14#include "cache.h"
15#include "serializerbinary.h"
16
17subExceptionDef( BuildException )
18
19Builder::Builder( Viewer &rView ) :
20 pDefaultAction( NULL ),
21 pLastAddedAction( NULL ),
22 sTmp(""),
23 sContext(""),
24 rView( rView ),
25 bUsingList( false )
26{
27}
28
29Builder::~Builder()
30{
31 if( sCacheFile.getLength() > 0 )
32 {
33 try
34 {
35 SerializerBinary ar( sCacheFile, Serializer::save );
36
37 ar << cRequires;
38 }
39 catch( ExceptionBase &e )
40 {
41 }
42 }
43}
44
45void yyparse( Builder &bld );
46
47void Builder::load( const char *sFN )
48{
49 file = sFN;
50
51 scanBegin();
52 yyparse( *this );
53 scanEnd();
54}
55
56void Builder::build( const char *sAct )
57{
58 Action *pAct;
59 if( sAct == NULL )
60 pAct = pDefaultAction;
61 else
62 {
63 if( mAction.find( sAct ) == mAction.end() )
64 throw BuildException("No action matches '%s'.", sAct );
65 pAct = mAction[sAct];
66 }
67
68 rView.beginAction( sAct, pAct->getNumCommands() );
69
70 pAct->execute( *this );
71
72 rView.endAction();
73}
74
75void Builder::setCache( const std::string &sFile )
76{
77 sCacheFile = sFile.c_str();
78
79 try
80 {
81 SerializerBinary ar( sCacheFile, Serializer::load );
82
83 ar >> cRequires;
84 }
85 catch( ExceptionBase &e )
86 {
87 }
88}
89
90void Builder::execute( Action *pAct )
91{
92 pAct->execute( *this );
93}
94
95void Builder::add( Action *pAct )
96{
97 if( pAct->isDefault() )
98 {
99 if( pDefaultAction )
100 throw BuildException("There's already a default exception");
101 pDefaultAction = pAct;
102 }
103 else
104 {
105 mAction[pAct->getName()] = pAct;
106 }
107 pLastAddedAction = pAct;
108}
109
110void Builder::add( Command *pCmd )
111{
112 if( pLastAddedAction )
113 {
114 pLastAddedAction->add( pCmd );
115 }
116}
117
118void Builder::addRegexCommand( int nType, const char *sReg )
119{
120 if( pLastAddedAction )
121 {
122 pLastAddedAction->add( nType, sReg );
123 }
124}
125
126void Builder::add( Rule *pRule )
127{
128 pLastAddedRule = pRule;
129 mRule[pRule->getName()] = pRule;
130}
131
132void Builder::add( Target *pTarg )
133{
134 pLastAddedTarget = pTarg;
135 mTarget[pTarg->getName()] = pTarg;
136}
137
138void Builder::addTarget( int tokType, const char *sName )
139{
140 nTargetType = tokType;
141 sTargetName = sName;
142}
143
144void Builder::setTargetInputType( int tokType )
145{
146 nTargetInputType = tokType;
147}
148
149void Builder::addTargetInput( const char *sInput )
150{
151 lsTargetInput.push_back( sInput );
152}
153
154void Builder::setTargetRule( const char *sRule )
155{
156 sTargetRule = sRule;
157}
158
159void Builder::endTarget()
160{
161 if( bUsingList == false )
162 {
163 switch( nTargetType )
164 {
165 case TOK_FILE:
166 add( new FileTarget( sTargetName.c_str() ) );
167 switch( nTargetInputType )
168 {
169 case TOK_FILES:
170 for( std::list<std::string>::iterator
171 i = lsTargetInput.begin();
172 i != lsTargetInput.end(); i++ )
173 {
174 ((FileTarget *)lastTarget())->addInputDir(
175 (*i).c_str()
176 );
177 }
178 break;
179 }
180 lastTarget()->setRule( sTargetRule.c_str() );
181 break;
182 }
183 }
184 else
185 {
186 switch( nTargetType )
187 {
188 case TOK_FILE:
189 for( std::list<std::pair<std::string,std::map<std::string,std::string> > >::iterator j = lTok.begin(); j != lTok.end(); j++ )
190 {
191 std::string sName = varRepl( sTargetName.c_str(), "", &(*j).second );
192 add( new FileTarget( sName.c_str() ) );
193 switch( nTargetInputType )
194 {
195 case TOK_FILES:
196 for( std::list<std::string>::iterator
197 i = lsTargetInput.begin();
198 i != lsTargetInput.end(); i++ )
199 {
200 std::string sInput = varRepl(
201 (*i).c_str(), "",
202 &(*j).second
203 );
204 ((FileTarget *)lastTarget())->addInputDir(
205 sInput.c_str()
206 );
207 }
208 break;
209 }
210 lastTarget()->setRule( sTargetRule.c_str() );
211 }
212 break;
213 }
214 }
215
216 clearList();
217}
218
219void Builder::debug()
220{
221 printf("Actions:\n");
222 pDefaultAction->debug();
223 for( std::map<const char *, Action *, ltstr>::iterator i = mAction.begin();
224 i != mAction.end(); i++ )
225 {
226 (*i).second->debug();
227 }
228
229 printf("Targets:\n");
230 for( std::map<const char *, Target *, ltstr>::iterator i = mTarget.begin();
231 i != mTarget.end(); i++ )
232 {
233 (*i).second->debug();
234 }
235
236 printf("Rules:\n");
237 for( std::map<const char *, Rule *, ltstr>::iterator i = mRule.begin();
238 i != mRule.end(); i++ )
239 {
240 (*i).second->debug();
241 }
242
243 printf("Variables:\n");
244 for( varmap::iterator i = mVar.begin(); i != mVar.end(); i++ )
245 {
246 printf(" %s = \"%s\"\n", (*i).first.c_str(), (*i).second.c_str() );
247 }
248
249 printf("Variables (by context):\n");
250 for( std::map<std::string, varmap>::iterator j = mContVar.begin();
251 j != mContVar.end(); j++ )
252 {
253 printf(" %s:\n", (*j).first.c_str() );
254 for( varmap::iterator i = (*j).second.begin();
255 i != (*j).second.end(); i++ )
256 {
257 printf(" %s = \"%s\"\n",
258 (*i).first.c_str(), (*i).second.c_str() );
259 }
260 }
261
262 printf("Dependancies:\n");
263 for( std::map<std::string, std::list<std::string> *>::iterator i =
264 mRequires.begin(); i != mRequires.end(); i++ )
265 {
266 printf(" %s: ", (*i).first.c_str() );
267 std::list<std::string> *pList = (*i).second;
268 int i = 0;
269 for( std::list<std::string>::iterator j = pList->begin();
270 j != pList->end(); j++ )
271 {
272 if( j != pList->begin() )
273 printf(", ");
274 printf("%s", (*j).c_str() );
275 if( i++ >= 3 )
276 {
277 printf("...");
278 break;
279 }
280 }
281 printf("\n");
282 }
283}
284
285void Builder::checkVar( const char *cont, const char *sName )
286{
287 if( cont[0] != '\0' )
288 {
289 varmap &mmVar = mContVar[cont];
290 if( mmVar.find( sName ) == mmVar.end() )
291 {
292 checkVar( "", sName );
293 mmVar[sName] = mVar[sName];
294 }
295 }
296 else
297 {
298 if( mVar.find( sName ) == mVar.end() )
299 {
300 char *env = getenv( sName );
301 if( env )
302 mVar[sName] = env;
303 else
304 mVar[sName] = "";
305 }
306 }
307}
308
309void Builder::varSet( const char *sName, const char *sValue )
310{
311 if( bUsingList )
312 {
313 for( std::list<std::pair<std::string,std::map<std::string,std::string> > >::iterator i = lTok.begin(); i != lTok.end(); i++ )
314 {
315 checkVar( (*i).first.c_str(), sName );
316
317 std::string newVal = varRepl( sValue, (*i).first.c_str(), &(*i).second );
318
319 mContVar[(*i).first.c_str()][sName] = newVal;
320 }
321 }
322 else
323 {
324 checkVar( sContext, sName );
325
326 std::string newVal = varRepl( sValue, sContext, NULL );
327
328 if( sContext[0] == '\0' )
329 {
330 mVar[sName] = newVal;
331 }
332 else
333 {
334 mContVar[sContext.getString()][sName] = newVal;
335 }
336 }
337}
338
339void Builder::varAddSet( const char *sName, const char *sValue )
340{
341 checkVar( sContext, sName );
342
343 std::string newVal = varRepl( sValue, sContext, NULL );
344
345 if( sContext[0] == '\0' )
346 {
347 std::string s = mVar[sName];
348 s += " ";
349 s += newVal;
350 mVar[sName] = s;
351 }
352 else
353 {
354 std::string s = mContVar[sContext.getString()][sName];
355 s += " ";
356 s += newVal;
357 mContVar[sContext.getString()][sName] = s;
358 }
359}
360
361void Builder::processRequires( std::list<std::string> &lInput )
362{
363 // These are cheap and handy to have all the time
364 for( regreqlist::iterator i = lRequiresRegexp.begin();
365 i != lRequiresRegexp.end(); i++ )
366 {
367 RegExp *re = (*i).first;
368 for( std::list<std::string>::iterator j = lInput.begin();
369 j != lInput.end(); j++ )
370 {
371 if( re->execute( (*j).c_str() ) )
372 {
373 varmap *revars = regexVars( re );
374 requiresNormal(
375 (*j).c_str(),
376 varRepl(
377 (*i).second.c_str(),
378 "",
379 revars
380 ).c_str()
381 );
382 delete revars;
383 }
384 }
385 }
386
387}
388
389void Builder::genRequiresFor( const char *sName, time_t tNewTime )
390{
391 Cache::Entry *ent = cRequires.get( sName );
392 if( ent && tNewTime > 0 )
393 {
394 if( ent->tCreated >= tNewTime )
395 {
396 for( std::list<std::string>::iterator i = ent->lData.begin();
397 i != ent->lData.end(); i++ )
398 {
399 requiresNormal(
400 sName,
401 (*i).c_str()
402 );
403 }
404
405 return;
406 }
407 }
408
409 ent = new Cache::Entry;
410 ent->tCreated = tNewTime;
411
412 for( regreqlist::iterator i = lRequiresRegexpCommand.begin();
413 i != lRequiresRegexpCommand.end(); i++ )
414 {
415 RegExp *re = (*i).first;
416 if( re->execute( sName ) )
417 {
418 varmap *revars = regexVars( re );
419 std::string s = varRepl( (*i).second.c_str(), "", revars );
420 rView.beginExtraRequiresCheck( s.c_str() );
421 rView.executeCmd( s.c_str() );
422 FILE *fcmd = popen( s.c_str(), "r" );
423 std::string rhs;
424 bool bHeader = true;
425 for(;;)
426 {
427 if( feof( fcmd ) )
428 break;
429 int cc = fgetc( fcmd );
430 if( cc == EOF )
431 break;
432 unsigned char c = cc;
433 if( bHeader )
434 {
435 if( c == ':' )
436 bHeader = false;
437 }
438 else
439 {
440 if( c == ' ' || c == '\t' )
441 {
442 if( rhs != "" )
443 {
444 requiresNormal(
445 sName,
446 rhs.c_str()
447 );
448 ent->lData.push_back( rhs );
449 rhs = "";
450 }
451 }
452 else
453 {
454 if( c == '\\' )
455 c = fgetc( fcmd );
456 if( c != '\n' )
457 rhs += c;
458 }
459 }
460 }
461 if( rhs != "" )
462 {
463 requiresNormal(
464 sName,
465 rhs.c_str()
466 );
467 ent->lData.push_back( rhs );
468 rhs = "";
469 }
470 pclose( fcmd );
471 delete revars;
472 rView.endExtraRequiresCheck();
473 }
474 }
475
476 cRequires.put( sName, ent );
477}
478
479std::map<std::string, std::string> *Builder::regexVars( RegExp *re )
480{
481 varmap *map = new varmap;
482
483 int jmax = re->getNumSubStrings();
484 for( int j = 0; j < jmax; j++ )
485 {
486 char buf[8];
487 sprintf( buf, "re:%d", j );
488 (*map)[buf] = re->getSubString( j );
489 }
490
491 return map;
492}
493
494void Builder::regexVars( RegExp *re, varmap &map )
495{
496 int jmax = re->getNumSubStrings();
497 for( int j = 0; j < jmax; j++ )
498 {
499 char buf[8];
500 sprintf( buf, "re:%d", j );
501 map[buf] = re->getSubString( j );
502 }
503}
504
505void Builder::requires( const char *sBase, const char *sReq )
506{
507 if( bReqRegexp )
508 {
509 requiresRegexp( sBase, sReq );
510 }
511 else
512 {
513 requiresNormal( sBase, sReq );
514 }
515}
516
517void Builder::requiresNormal( const char *sBase, const char *sReq )
518{
519 std::list<std::string> *pList = NULL;
520 if( mRequires.find(sBase) == mRequires.end() )
521 {
522 pList = new std::list<std::string>;
523 mRequires[sBase] = pList;
524 }
525 else
526 {
527 pList = mRequires[sBase];
528 }
529
530 pList->push_back( sReq );
531}
532
533void Builder::requiresRegexp( const char *sBase, const char *sReq )
534{
535 lRequiresRegexp.push_back(
536 std::pair<RegExp *, std::string>(
537 new RegExp( sBase ),
538 sReq
539 )
540 );
541}
542
543void Builder::requiresFromCommand( const char *sBase, const char *sCmd )
544{
545 lRequiresRegexpCommand.push_back(
546 std::pair<RegExp *, std::string>(
547 new RegExp( sBase ),
548 sCmd
549 )
550 );
551}
552
553void Builder::setContext( const char *sCont )
554{
555 sContext = sCont;
556}
557
558void Builder::setContext()
559{
560 setContext("");
561}
562
563bool Builder::hasVar( varmap *pMap, std::string &var )
564{
565 if( pMap == NULL )
566 return false;
567 if( pMap->find( var ) == pMap->end() )
568 return false;
569 return true;
570}
571
572std::string Builder::varRepl( const char *sSrc, const char *cont, varmap *mExtra )
573{
574 varmap *mCont = NULL;
575 if( cont[0] != '\0' )
576 {
577 if( mContVar.find( cont ) != mContVar.end() )
578 mCont = &mContVar[cont];
579 }
580
581 std::string out;
582 std::string var;
583 bool bVar = false;
584
585 for( const char *s = sSrc; *s; s++ )
586 {
587 if( *s == '{' )
588 {
589 bVar = true;
590 continue;
591 }
592 else if( *s == '}' && bVar )
593 {
594 if( hasVar( mExtra, var ) )
595 {
596 out += (*mExtra)[var];
597 }
598 else if( hasVar( mCont, var ) )
599 {
600 out += (*mCont)[var];
601 }
602 else if( hasVar( &mVar, var ) )
603 {
604 out += mVar[var];
605 }
606 var = "";
607 bVar = false;
608 continue;
609 }
610
611 if( bVar == true )
612 {
613 var += *s;
614 }
615 else
616 {
617 out += *s;
618 }
619 }
620
621 return out;
622}
623
624Rule *Builder::getRule( const char *sName )
625{
626 if( mRule.find( sName ) != mRule.end() )
627 return mRule[sName];
628
629 throw BuildException("No rule named %s registered.", sName );
630 return NULL;
631}
632
633std::list<Rule *> Builder::findRuleChain( Rule *pRule )
634{
635 std::list<Rule *> ret;
636
637 for( std::map<const char *, Rule *, ltstr>::iterator i = mRule.begin();
638 i != mRule.end(); i++ )
639 {
640 if( pRule == (*i).second )
641 continue;
642
643 if( pRule->willChain( (*i).second ) )
644 {
645 ret.push_back( (*i).second );
646 }
647 }
648
649 return ret;
650}
651
652void cleanList( std::list<std::string> &lst )
653{
654 std::map<std::string, bool> m;
655
656 for( std::list<std::string>::iterator i = lst.begin(); i != lst.end(); i++ )
657 {
658 if( m.find( *i ) == m.end() )
659 m[ *i ] = true;
660 else
661 {
662 std::list<std::string>::iterator j = i;
663 j--;
664 lst.erase( i );
665 i = j;
666 }
667 }
668}
669
670void Builder::error( const std::string &err )
671{
672 throw BuildException( err.c_str() );
673}
674
675void Builder::error( YYLTYPE *locp, const std::string &err )
676{
677 std::stringstream s;
678 s << file << ":" << locp->first_line << "." << locp->first_column;
679 if( locp->first_line != locp->last_line )
680 s << "-" << locp->last_line << "." << locp->last_column;
681 else if( locp->first_column != locp->last_column )
682 s << "-" << locp->last_column;
683 s << ": " << err;
684 throw BuildException( s.str().c_str() );
685}
686
687void Builder::startList( int tokType )
688{
689 bUsingList = true;
690 lTok.clear();
691 bTokFiltered = false;
692 nTokType = tokType;
693}
694
695void Builder::setFilter( const char *sRegExp )
696{
697 rTok.compile( sRegExp );
698 bTokFiltered = true;
699}
700
701void Builder::augmentList( const char *sFrom )
702{
703 switch( nTokType )
704 {
705 case TOK_DIRECTORIES:
706 {
707 DIR *dir = opendir( sFrom );
708 if( dir == NULL )
709 {
710 printf("dir: %s\n", sFrom );
711 throw BuildException( strerror( errno ) );
712 }
713
714 std::string base;
715 base += sFrom;
716 base += "/";
717
718 struct dirent *de;
719
720 while( (de = readdir( dir )) )
721 {
722 if( de->d_type != DT_DIR )
723 continue;
724 if( de->d_name[0] == '.' || de->d_name[0] == '\0' )
725 continue;
726
727 std::string s( base );
728 s += de->d_name;
729 addListItem( s.c_str() );
730 }
731
732 closedir( dir );
733 }
734 break;
735
736 default:
737 break;
738 }
739}
740
741void Builder::endList()
742{
743 switch( nTokType )
744 {
745 case TOK_TARGETS:
746 for( std::map<const char *, Target *, ltstr>::iterator i =
747 mTarget.begin(); i != mTarget.end(); i++ )
748 {
749 addListItem( (*i).first );
750 }
751 break;
752 }
753}
754
755void Builder::addListItem( const char *sItem )
756{
757 std::map<std::string,std::string> mVars;
758 mVars["match"] = sItem;
759 if( bTokFiltered )
760 {
761 if( rTok.execute( sItem ) )
762 {
763 regexVars( &rTok, mVars );
764 }
765 else
766 {
767 return;
768 }
769 }
770 lTok.push_back(
771 std::pair<std::string,std::map<std::string,std::string> >(
772 sItem, mVars
773 )
774 );
775}
776
777void Builder::clearList()
778{
779 lTok.clear();
780 lsTargetInput.clear();
781 bUsingList = false;
782}
783
784std::list<std::string> Builder::findTargets( const char *sRegex )
785{
786 RegExp r( sRegex );
787
788 std::list<std::string> lTmp;
789
790 for( std::map<const char *, Target *, ltstr>::iterator i = mTarget.begin();
791 i != mTarget.end(); i++ )
792 {
793 if( r.execute( (*i).first ) )
794 {
795 lTmp.push_back( (*i).first );
796 }
797 }
798
799 return lTmp;
800}
801
802std::string Builder::cmdToString( const char *sCmd )
803{
804 std::string buf;
805 FILE *pr = popen( sCmd, "r" );
806 if( pr == NULL )
807 throw BuildException("Couldn't execute program \"%s\"", sCmd );
808
809 char cbuf[2048];
810
811 for(;;)
812 {
813 int nRead = fread( cbuf, 1, 2048, pr );
814 for( int j = 0; j < nRead; j++ )
815 if( cbuf[j] != '\n' && cbuf[j] != '\r' )
816 buf.append( cbuf+j, 1 );
817 if( feof( pr ) )
818 break;
819 }
820
821 pclose( pr );
822
823 return buf;
824}
825