cmt_triggers.cxx Source File

Main Page Class Hierarchy Compound List File List Compound Members File Members

# cmt_triggers.cxx

Go to the documentation of this file.

    00001 /*
    00002
    00003 From Frank Behner, John Allison 13th February 1999.
    00004 From Christian Arnault               Oct.     2000
    00005
    00006 */
    00007
    00008 #include <stdio.h>
    00009 #include <stdlib.h>
    00010 #include <ctype.h>
    00011
    00012 #include "cmt_triggers.h"
    00013 #include "cmt_std.h"
    00014 #include "cmt_string.h"
    00015 #include "cmt_system.h"
    00016 #include "cmt_awk.h"
    00017 #include "cmt_use.h"
    00018 #include "cmt_symbol.h"
    00019 #include "cmt_constituent.h"
    00020
    00021 //--------------------------------------------------
    00022 class Libmap
    00023 {
    00024 public:
    00025   typedef cmt_vector<Libmap> LibmapVector;
    00026
    00027   static Libmap& find (const cmt_string& name, const cmt_string& package);
    00028   static Libmap& add (const cmt_string& name, const cmt_string& package);
    00029   static LibmapVector& libmaps ();
    00030   static Libmap& find_with_trigger (const cmt_string& name);
    00031   static Libmap& null ();
    00032
    00033 public:
    00034   Libmap ();
    00035
    00036   void add_trigger (const cmt_string& trigger_name);
    00037   void add_use (const cmt_string& use_name);
    00038   int operator != (const Libmap& other) const;
    00039   int operator == (const Libmap& other) const;
    00040   void set_used ();
    00041
    00042   cmt_string name;
    00043   cmt_string package;
    00044   CmtSystem::cmt_string_vector triggers;
    00045   bool used;
    00046   CmtSystem::cmt_string_vector uses;
    00047 };
    00048 //--------------------------------------------------
    00049
    00050 //--------------------------------------------------
    00051 Libmap& Libmap::find (const cmt_string& name, const cmt_string& package)
    00052 {
    00053   LibmapVector& table = libmaps ();
    00054
    00055   for (int i = 0; i < table.size (); i++)
    00056     {
    00057       Libmap& libmap = table[i];
    00058
    00059 #ifdef USE_PACKAGE_SCOPE
    00060       if ((name == libmap.name) &&
    00061           (package == libmap.package)) return (libmap);
    00062 #else
    00063       if (name == libmap.name) return (libmap);
    00064 #endif
    00065     }
    00066
    00067   return (null ());
    00068 }
    00069
    00070 Libmap& Libmap::add (const cmt_string& name, const cmt_string& package)
    00071 {
    00072   {
    00073     Libmap& libmap = find (name, package);
    00074
    00075     if (libmap != null ()) return (libmap);
    00076   }
    00077
    00078   LibmapVector& table = libmaps ();
    00079
    00080   Libmap& libmap = table.add ();
    00081
    00082   libmap.name = name;
    00083   libmap.package = package;
    00084
    00085   return (libmap);
    00086 }
    00087
    00088 Libmap::LibmapVector& Libmap::libmaps ()
    00089 {
    00090   static cmt_vector<Libmap> table;
    00091
    00092   return (table);
    00093 }
    00094
    00095 Libmap::Libmap () : used (false)
    00096 {
    00097 }
    00098
    00099 void Libmap::add_trigger (const cmt_string& trigger_name)
    00100 {
    00101   cmt_string& trigger = triggers.add ();
    00102
    00103   trigger = trigger_name;
    00104 }
    00105
    00106 void Libmap::add_use (const cmt_string& use_name)
    00107 {
    00108   cmt_string& use = uses.add ();
    00109
    00110   use = use_name;
    00111 }
    00112
    00113 Libmap& Libmap::find_with_trigger (const cmt_string& name)
    00114 {
    00115   LibmapVector& table = libmaps ();
    00116
    00117   for (int i = 0; i < table.size (); i++)
    00118     {
    00119       Libmap& libmap = table[i];
    00120
    00121       for (int j = 0; j < libmap.triggers.size (); j++)
    00122         {
    00123           const cmt_string& trigger = libmap.triggers[j];
    00124
    00125           if (name == trigger) return (libmap);
    00126         }
    00127     }
    00128
    00129   return (null ());
    00130 }
    00131
    00132 Libmap& Libmap::null ()
    00133 {
    00134   static Libmap null_libmap;
    00135
    00136   return (null_libmap);
    00137 }
    00138
    00139 int Libmap::operator != (const Libmap& other) const
    00140 {
    00141   return (this != &other);
    00142 }
    00143
    00144 int Libmap::operator == (const Libmap& other) const
    00145 {
    00146   return (this == &other);
    00147 }
    00148
    00149 void Libmap::set_used ()
    00150 {
    00151   if (used) return;
    00152
    00153   used = true;
    00154
    00155   cmt_string package_name;
    00156   cmt_string use_name;
    00157
    00158   for (int i = 0; i < uses.size (); i++)
    00159     {
    00160       const cmt_string& use = uses[i];
    00161
    00162       int pos = use.find ("::");
    00163
    00164       if (pos == cmt_string::npos)
    00165         {
    00166           package_name = "";
    00167           use_name = use;
    00168         }
    00169       else
    00170         {
    00171           use.substr (0, pos, package_name);
    00172           use.substr (pos + 2, use_name);
    00173
    00174           Libmap& libmap = find (use_name, package_name);
    00175           if (libmap != null ())
    00176             {
    00177               libmap.set_used ();
    00178             }
    00179         }
    00180     }
    00181 }
    00182 //--------------------------------------------------
    00183
    00184 //--------------------------------------------------
    00185 //
    00186 //  This class analyzes a trigger description file (ie a file
    00187 // named <constituent>.triggers and located in the cmt directory of
    00188 // a package).
    00189 //
    00190 //  The file is expected to include lines of the form:
    00191 //
    00192 //    <constituent>_implied_libs=<lib> <lib> ...
    00193 //    <constituent>_triggers=<trigger> <trigger> ...
    00194 //
    00195 //  with <lib> having the form:
    00196 //
    00197 //    <package>::<constituent>
    00198 //     eg: Cm::Cm
    00199 //
    00200 //    or more simply
    00201 //
    00202 //    <constituent>
    00203 //
    00204 //  and <trigger> being an include file path (in the same form as
    00205 //  the one used in the dependency files)
    00206 //
    00207 //     eg: $(CMROOT)/src/Cm.h
    00208 //         $(AGDDROOT)/AGDD/AGDD.h
    00209 //
    00210 //
    00211 //    When reading one trigger description file, one Libmap object is
    00212 // created, and its list of uses and triggers are filled in.
    00213 //
    00214 //--------------------------------------------------
    00215 class TriggerAnalyzer : public FAwk
    00216 {
    00217 public:
    00218   TriggerAnalyzer (const cmt_string& package_name);
    00219   void begin ();
    00220   void filter (const cmt_string& line);
    00221   void end ();
    00222
    00223 private:
    00224   cmt_string package;
    00225 };
    00226 //--------------------------------------------------
    00227
    00228 //--------------------------------------------------
    00229 TriggerAnalyzer::TriggerAnalyzer (const cmt_string& package_name) :
    00230   package (package_name)
    00231 {
    00232 }
    00233
    00234 void TriggerAnalyzer::begin ()
    00235 {
    00236 }
    00237
    00238 void TriggerAnalyzer::filter (const cmt_string& line)
    00239 {
    00240   int pos = line.find ("=");
    00241   if (pos == 0)
    00242     {
    00243       if (!Cmt::get_quiet ())
    00244         {
    00245           cerr << "Syntax error in trigger file : empty name" << endl;
    00246         }
    00247       exit (0);
    00248     }
    00249   if (pos == cmt_string::npos)
    00250     {
    00251       if (!Cmt::get_quiet ())
    00252         {
    00253           cerr << "Syntax error in trigger file : no = sign" << endl;
    00254         }
    00255       exit (0);
    00256     }
    00257
    00258   cmt_string name;
    00259   cmt_string text;
    00260   CmtSystem::cmt_string_vector words;
    00261
    00262   line.substr (0, pos, name);
    00263   line.substr (pos + 1, text);
    00264   CmtSystem::split (text, " ", words);
    00265
    00266   if (name.find ("_triggers") != cmt_string::npos)
    00267     {
    00268       name.replace ("_triggers", "");
    00269
    00270       Libmap& libmap = Libmap::add (name, package);
    00271
    00272       for (int i = 0; i < words.size (); i++)
    00273         {
    00274           const cmt_string& w = words[i];
    00275           libmap.add_trigger (w);
    00276         }
    00277     }
    00278   else if (name.find ("_implied_libraries") != cmt_string::npos)
    00279     {
    00280       name.replace ("_implied_libraries", "");
    00281
    00282       Libmap& libmap = Libmap::add (name, package);
    00283
    00284       for (int i = 0; i < words.size (); i++)
    00285         {
    00286           const cmt_string& w = words[i];
    00287           libmap.add_use (w);
    00288         }
    00289     }
    00290   else
    00291     {
    00292       if (!Cmt::get_quiet ())
    00293         {
    00294           cerr << "Syntax error in trigger file : bad keyword (" <<
    00295               name << ")" << endl;
    00296         }
    00297       exit (0);
    00298     }
    00299 }
    00300
    00301 void TriggerAnalyzer::end ()
    00302 {
    00303 }
    00304 //--------------------------------------------------
    00305
    00306 //--------------------------------------------------
    00307 //
    00308 //  This filter scans the CMT dependency file of a constituent.
    00309 //
    00310 //  The file should contains a set of entries, each composed of one line:
    00311 //
    00312 //      <module-name>_dependencies=<dependency> <dependency> ...
    00313 //
    00314 //  (Each such line actually defines one make macro used to trigger the
    00315 //   rebuild of the corresponding module)
    00316 //
    00317 //  Dependencies may typically be:
    00318 //     o the module source itself
    00319 //     o a local dependency (ie. one which is preficed by one of the
    00320 //              include dirs)
    00321 //     o an external dependency (all other cases)
    00322 //
    00323 //  Local dependencies will generate triggers for this constituent (filling
    00324 //  up the "triggers" unique-vector)
    00325 //
    00326 //  External dependencies will trigger the use of one Libmap object (thus
    00327 //  filling up the "uses" unique-vector)
    00328 //
    00329 //  At the end of the scan, the results are printed to standard output
    00330 //  with a format of a trigger description file.
    00331 //
    00332 //    For libraries, only the first level list is output (ie. only Libmap
    00333 //  object directly triggered by dependencies of that constituent are
    00334 //  listed)
    00335 //
    00336 //    For applications, indirect dependencies are considered and resolved
    00337 //  recursively.
    00338 //
    00339 //--------------------------------------------------
    00340 class DependencyAnalyzer : public FAwk
    00341 {
    00342 public:
    00343   DependencyAnalyzer (const cmt_string& package_name,
    00344                       Constituent& constituent_ref);
    00345   void begin ();
    00346   void filter (const cmt_string& line);
    00347   virtual void end ();
    00348
    00349 protected:
    00350
    00351   void add_trigger (const cmt_string& name);
    00352   void add_use (Libmap& libmap);
    00353
    00354   CmtSystem::cmt_string_vector include_dirs;
    00355   cmt_vector<Libmap*> uses;
    00356   CmtSystem::cmt_string_vector triggers;
    00357   Constituent& constituent;
    00358   cmt_string package;
    00359   cmt_string package_upper;
    00360 };
    00361
    00362 class LibraryAnalyzer : public DependencyAnalyzer
    00363 {
    00364 public:
    00365   LibraryAnalyzer (const cmt_string& package_name,
    00366                    Constituent& constituent_ref);
    00367   void end ();
    00368 };
    00369
    00370 class ApplicationAnalyzer : public DependencyAnalyzer
    00371 {
    00372 public:
    00373   ApplicationAnalyzer (const cmt_string& package_name,
    00374                        Constituent& constituent_ref);
    00375   void end ();
    00376 };
    00377 //--------------------------------------------------
    00378
    00379 //--------------------------------------------------
    00380 DependencyAnalyzer::DependencyAnalyzer (const cmt_string& package_name,
    00381                                         Constituent& constituent_ref) :
    00382         package (package_name),
    00383         constituent (constituent_ref)
    00384 {
    00385   cmt_string dirs;
    00386
    00387   int pos;
    00388   char c;
    00389
    00390   package_upper = package;
    00391
    00392   for (pos = 0; pos < package_upper.size (); pos++)
    00393     {
    00394       c = package_upper[pos];
    00395       package_upper[pos] = toupper (c);
    00396     }
    00397
    00398   CmtSystem::execute ("cmt show include_dirs", dirs);
    00399   dirs.replace_all ("\n", "");
    00400   CmtSystem::split (dirs, " ", include_dirs);
    00401 }
    00402
    00403 void DependencyAnalyzer::begin ()
    00404 {
    00405 }
    00406
    00407 void DependencyAnalyzer::filter (const cmt_string& line)
    00408 {
    00409     /* Clip target out of dependency file... */
    00410   int pos = line.find ("=");
    00411   if ((pos == 0) || (pos == cmt_string::npos))
    00412     {
    00413       if (!Cmt::get_quiet ())
    00414         {
    00415           cerr << "  ERROR: Syntax in dependency file: " << line << endl;
    00416           cerr << "  Missing = or target name." << endl;
    00417         }
    00418       exit (1);
    00419     }
    00420
    00421   cmt_string module;
    00422
    00423   line.substr (0, pos, module);
    00424   module.trim ();
    00425   module.replace ("_dependencies", "");
    00426
    00427   if (module == "cmt_path_make") return;
    00428
    00429   int underscore = module.find_last_of ("_");
    00430
    00431   if (underscore != cmt_string::npos)
    00432     {
    00433       module[underscore] = '.';
    00434     }
    00435
    00436   static cmt_string dependencies;
    00437
    00438   line.substr (pos + 1, dependencies);
    00439
    00440   if (dependencies == "")
    00441     {
    00442       cerr << "  WARNING: It seems there is nothing after \'=\' "
    00443           "in dependency file " << m_file_name << endl;
    00444       return;
    00445     }
    00446
    00447   CmtSystem::cmt_string_vector deps;
    00448
    00449   CmtSystem::split (dependencies, " ", deps);
    00450
    00451   for (int i = 0; i < deps.size (); i++)
    00452     {
    00453       const cmt_string& dep = deps[i];
    00454
    00455         //
    00456         // dep may either be:
    00457         //  o the module itself
    00458         //  o a file in one of include_dirs
    00459         //  o something else
    00460         //
    00461
    00462       if (dep.find (module) != cmt_string::npos)
    00463         {
    00464           // This is the module itself.
    00465         }
    00466       else
    00467         {
    00468           bool found = false;
    00469
    00470           for (int j = 0; j < include_dirs.size (); j++)
    00471             {
    00472               const cmt_string& dir = include_dirs[j];
    00473
    00474               if (dep.find (dir) == 0)
    00475                 {
    00476                   // This is a local dependency.
    00477
    00478                   cmt_string name = dep;
    00479
    00480                   if (dir == "$(src)")
    00481                     {
    00482                       cmt_string new_dir;
    00483
    00484                       new_dir = "$(";
    00485                       new_dir += package_upper;
    00486                       new_dir += "ROOT)/src/";
    00487
    00488                       name.replace (dir, new_dir);
    00489                     }
    00490
    00491                   if (CmtSystem::file_separator () == '\\')
    00492                     {
    00493                       name.replace_all (CmtSystem::file_separator (), "/");
    00494                     }
    00495
    00496                   Libmap& libmap = Libmap::find_with_trigger (name);
    00497
    00498                   if (libmap != Libmap::null ())
    00499                     {
    00500                       add_use (libmap);
    00501                     }
    00502                   else
    00503                     {
    00504                       add_trigger (name);
    00505                     }
    00506
    00507                   found = true;
    00508                   break;
    00509                 }
    00510             }
    00511
    00512           if (!found)
    00513             {
    00514               cmt_string name = dep;
    00515
    00516               if (CmtSystem::file_separator () == '\\')
    00517                 {
    00518                   name.replace_all (CmtSystem::file_separator (), "/");
    00519                 }
    00520
    00521               // This is an external dependency.
    00522
    00523               Libmap& libmap = Libmap::find_with_trigger (name);
    00524
    00525               if (libmap != Libmap::null ())
    00526                 {
    00527                   add_use (libmap);
    00528                 }
    00529             }
    00530         }
    00531     }
    00532 }
    00533
    00534 void DependencyAnalyzer::end ()
    00535 {
    00536 }
    00537
    00538 void DependencyAnalyzer::add_trigger (const cmt_string& name)
    00539 {
    00540   for (int i = 0; i < triggers.size (); i++)
    00541     {
    00542       const cmt_string& trigger = triggers[i];
    00543
    00544       if (trigger == name) return;
    00545     }
    00546
    00547   cmt_string& new_trigger = triggers.add ();
    00548
    00549   new_trigger = name;
    00550 }
    00551
    00552 void DependencyAnalyzer::add_use (Libmap& libmap)
    00553 {
    00554   for (int i = 0; i < uses.size (); i++)
    00555     {
    00556       const Libmap& ref = *(uses[i]);
    00557
    00558       if (ref == libmap) return;
    00559     }
    00560
    00561   uses.push_back (&libmap);
    00562 }
    00563
    00564 LibraryAnalyzer::LibraryAnalyzer (const cmt_string& package_name,
    00565                                   Constituent& constituent_ref) :
    00566     DependencyAnalyzer (package_name, constituent_ref)
    00567 {
    00568 }
    00569
    00570 void LibraryAnalyzer::end ()
    00571 {
    00572   cmt_string macro_name;
    00573   cmt_string output;
    00574
    00575   int i;
    00576
    00577   if (uses.size () > 0)
    00578     {
    00579       for (i = 0; i < uses.size (); i++)
    00580         {
    00581           Libmap& libmap = *(uses[i]);
    00582
    00583           libmap.set_used ();
    00584         }
    00585
    00586       Libmap::LibmapVector& table = Libmap::libmaps ();
    00587
    00588       macro_name = constituent.name;
    00589       macro_name += "_implied_libraries";
    00590
    00591       output  = "macro_prepend ";
    00592       output += macro_name;
    00593       output += " \"";
    00594       for (i = 0; i < table.size (); i++)
    00595         {
    00596           Libmap& libmap = table[i];
    00597
    00598           if (libmap.used)
    00599             {
    00600 #ifdef USE_PACKAGE_SCOPE
    00601               output += libmap.package;
    00602               output += "::";
    00603 #endif
    00604               output += libmap.name;
    00605               output += " ";
    00606             }
    00607         }
    00608       output += "\"";
    00609
    00610       Cmt::parse_requirements_text (output, "", 0);
    00611
    00612       Symbol* macro = Symbol::find (macro_name);
    00613       output = macro_name;
    00614       output += "=";
    00615       output += macro->build_macro_value ();
    00616
    00617       cout << output << endl;
    00618     }
    00619
    00620   if (triggers.size () > 0)
    00621     {
    00622       macro_name = constituent.name;
    00623       macro_name += "_triggers";
    00624
    00625       output  = "macro_prepend ";
    00626       output += macro_name;
    00627       output += " \"";
    00628       for (i = 0; i < triggers.size (); i++)
    00629         {
    00630           const cmt_string& trigger = triggers[i];
    00631
    00632           output += trigger;
    00633           output += " ";
    00634         }
    00635       output += "\"";
    00636
    00637       Cmt::parse_requirements_text (output, "", 0);
    00638
    00639       Symbol* macro = Symbol::find (macro_name);
    00640       output = macro_name;
    00641       output += "=";
    00642       output += macro->build_macro_value ();
    00643
    00644       cout << output << endl;
    00645     }
    00646 }
    00647
    00648 ApplicationAnalyzer::ApplicationAnalyzer (const cmt_string& package_name,
    00649                                           Constituent& constituent_ref) :
    00650     DependencyAnalyzer (package_name, constituent_ref)
    00651 {
    00652 }
    00653
    00654 void ApplicationAnalyzer::end ()
    00655 {
    00656   cmt_string macro_name;
    00657   cmt_string output;
    00658
    00659   int i;
    00660
    00661   if (uses.size () > 0)
    00662     {
    00663       for (i = 0; i < uses.size (); i++)
    00664         {
    00665           Libmap& libmap = *(uses[i]);
    00666
    00667           libmap.set_used ();
    00668         }
    00669
    00670       Libmap::LibmapVector& table = Libmap::libmaps ();
    00671
    00672       macro_name = constituent.name;
    00673       macro_name += "linkopts";
    00674
    00675       output  = "macro_prepend ";
    00676       output += macro_name;
    00677       output += " \"";
    00678       for (i = 0; i < table.size (); i++)
    00679         {
    00680           Libmap& libmap = table[i];
    00681
    00682           if (libmap.used)
    00683             {
    00684               output += "$(implied_library_prefix)";
    00685               output += libmap.name;
    00686               output += "$(implied_library_suffix) ";
    00687             }
    00688         }
    00689       output += "\"";
    00690
    00691       Cmt::parse_requirements_text (output, "", 0);
    00692
    00693       Symbol* macro = Symbol::find (macro_name);
    00694       output = macro_name;
    00695       output += "=";
    00696       output += macro->build_macro_value ();
    00697
    00698       cout << output << endl;
    00699     }
    00700 }
    00701 //--------------------------------------------------
    00702
    00703 //--------------------------------------------------
    00704 //
    00705 //  The UseAnalyzer is called first to reach all used packages.
    00706 // For each package found, it retreives the *.triggers files
    00707 // which contain the trigger descriptions for every constituent
    00708 // of the package.
    00709 //
    00710 //  For each trigger description file found, a TriggerAnalyzer is run
    00711 // which in turn fills in the database of Libmap objects.
    00712 //
    00713 //--------------------------------------------------
    00714 class UseAnalyzer
    00715 {
    00716 public:
    00717   void run (const cmt_string& constituent);
    00718   void run (const cmt_string& location,
    00719             const cmt_string& package,
    00720             const cmt_string& filter_out = "");
    00721 };
    00722 //--------------------------------------------------
    00723
    00724 //--------------------------------------------------
    00725 void UseAnalyzer::run (const cmt_string& constituent)
    00726 {
    00727   Use* use = &(Use::current ());
    00728
    00729   run ("./", use->package, constituent);
    00730
    00731   Use::UsePtrVector& uses = Use::uses ();
    00732   for (int i = 0; i < uses.size (); i++)
    00733     {
    00734       use = uses[i];
    00735
    00736       cmt_string s;
    00737
    00738       s = use->real_path;
    00739       s += CmtSystem::file_separator ();
    00740       s += use->package;
    00741       s += CmtSystem::file_separator ();
    00742       s += use->version;
    00743       s += CmtSystem::file_separator ();
    00744
    00745       if (use->style == mgr_style) s += "mgr";
    00746       else s += "cmt";
    00747
    00748       s += CmtSystem::file_separator ();
    00749
    00750       run (s, use->package);
    00751     }
    00752 }
    00753
    00754 void UseAnalyzer::run (const cmt_string& location,
    00755                        const cmt_string& package,
    00756                        const cmt_string& filter_out)
    00757 {
    00758   static cmt_regexp expression ("[.]triggers$");
    00759
    00760   TriggerAnalyzer analyzer (package);
    00761
    00762   CmtSystem::cmt_string_vector files;
    00763
    00764   CmtSystem::scan_dir (location, expression, files);
    00765
    00766   cmt_string name;
    00767
    00768   for (int i = 0; i < files.size (); i++)
    00769     {
    00770       const cmt_string& file = files[i];
    00771
    00772       if (filter_out != "")
    00773         {
    00774           CmtSystem::basename (file, ".triggers", name);
    00775           if (name == filter_out) continue;
    00776         }
    00777
    00778       analyzer.run (file);
    00779     }
    00780 }
    00781 //--------------------------------------------------
    00782
    00783
    00784 //--------------------------------------------------
    00785 void TriggerGenerator::run (const cmt_string& constituent_name)
    00786 {
    00787   Constituent* constituent = Constituent::find (constituent_name);
    00788
    00789   Use* use = &(Use::current ());
    00790   cmt_string package = use->package;
    00791
    00792     // UseAnalyzer use_analyzer (package);
    00793     // use_analyzer.run ("cmt show uses -quiet");
    00794
    00795   UseAnalyzer use_analyzer;
    00796   use_analyzer.run (constituent_name);
    00797
    00798   cmt_string file_name;
    00799
    00800   file_name = "./";
    00801   file_name += constituent_name;
    00802   file_name += "_dependencies.";
    00803 #ifdef WIN32
    00804   file_name += "nmake";
    00805 #else
    00806   file_name += "make";
    00807 #endif
    00808
    00809   DependencyAnalyzer* analyzer = 0;
    00810
    00811   if (constituent->type == Library)
    00812     {
    00813       analyzer = new LibraryAnalyzer (package, *constituent);
    00814     }
    00815   else if (constituent->type == Application)
    00816     {
    00817       analyzer = new ApplicationAnalyzer (package, *constituent);
    00818     }
    00819   else
    00820     {
    00821       return;
    00822     }
    00823
    00824   if (analyzer->run (file_name) == Awk::failed)
    00825     {
    00826       cerr << "  File " << file_name << " not found" << endl;
    00827     }
    00828
    00829   delete analyzer;
    00830 }
    00831 //--------------------------------------------------