Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

vimports.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019  // Created on Wed Jul  2 16:10:28 PDT 1997 by heydon
00020 // Last modified on Thu Aug  5 13:57:22 EDT 2004 by ken@xorian.net  
00021 //      modified on Sat Feb 12 18:15:03 PST 2000 by mann  
00022 //      modified on Wed Jan 27 10:26:31 PST 1999 by heydon
00023 
00024 // vimports(1) - print the models imported by a specified model
00025 
00026 #include <unistd.h>    // for getcwd(3)
00027 #include <Basics.H>
00028 #include <Sequence.H>
00029 #include <Generics.H>  // for TextSeq
00030 #include <FS.H>
00031 #include <ParseImports.H>
00032 
00033 using std::ostream;
00034 using std::cout;
00035 using std::cerr;
00036 using std::endl;
00037 
00038 class ShowEntry {
00039   public:
00040     Text name; // name of partial path to elide
00041     int depth; // depth to elide that subtree (-1 => no ellision)
00042     ShowEntry() throw () { /* SKIP */ }
00043     ShowEntry(const Text &name, int depth) throw ()
00044         : name(name), depth(depth) { /*SKIP*/ }
00045 };
00046 
00047 typedef Sequence<ShowEntry> ShowEntrySeq;
00048 
00049 void Syntax(char *msg, char *arg = (char *)NULL) throw ()
00050 {
00051     cerr << "Error: " << msg;
00052     if (arg != (char *)NULL) cerr << ": '" << arg << "'";
00053     cerr << endl;
00054     cerr << "Syntax: vimports [-depth num] "
00055          << "[-elide name]... [-show name [depth]]... "
00056          << "[model]" << endl;
00057     exit(1); /* Status == 1 implies command line parse error */
00058 }
00059 
00060 void Indent(ostream &os, int n) throw ()
00061 {
00062     for (/*SKIP*/; n > 0; n--) os << "| ";
00063 }
00064 
00065 int Search(const Text &model, int depth, int elideDepth,
00066   const TextSeq &elideNames, const ShowEntrySeq &showNames) throw ()
00067 {
00068   /* Status = 0:  Success
00069               1:  Command line parse error
00070               2:  Model-file-not-found error
00071               3:  Model file parse error
00072               4:  Filesystem (e.g. read) error
00073   */
00074     int status = 0; /* Assume success */
00075     Indent(cout, depth); cout << model;
00076     ImportSeq imports(/*sizehint=*/ 10);
00077     try {
00078         ParseImports::P(model, /*INOUT*/ imports);
00079 
00080         // test if this subtree should be elided
00081         bool elide = false;
00082         for (int i = 0; i < elideNames.size(); i++) {
00083             if (model.FindText(elideNames.get(i)) >= 0) {
00084                 elide = true;
00085                 break;
00086             }
00087         }
00088 
00089         if (!elide) {
00090             // test if this subtree should be shown
00091             bool show = false;
00092             int maxShowDepth = 0;
00093             for (int i = 0; i < showNames.size(); i++) {
00094                 if (model.FindText(showNames.get(i).name) >= 0) {
00095                     show = true;
00096                     if (maxShowDepth >= 0) {
00097                         int thisDepth = showNames.get(i).depth;
00098                         if (thisDepth < 0) maxShowDepth = thisDepth;
00099                         else maxShowDepth = max(maxShowDepth, thisDepth);
00100                     }
00101                 }
00102             }
00103             if (show) {
00104                 // set "elideDepth" from "maxShowDepth"
00105                 elideDepth = maxShowDepth;
00106                 if (elideDepth >= 0) elideDepth += depth;
00107             }
00108         }
00109 
00110         // compute whether to recurse or not
00111         if (!elide && (elideDepth < 0 || depth < elideDepth)) {
00112             cout << endl;
00113             while (imports.size() > 0) {
00114               Import imp(*(imports.getlo()));
00115               delete imports.remlo();
00116               Search(imp.path, depth+1, elideDepth, elideNames, showNames);
00117             }
00118         } else {
00119             if (imports.size() > 0) cout << "...";
00120             cout << endl;
00121         }
00122     }
00123     catch (FS::DoesNotExist) {
00124         cerr << endl; Indent(cerr, depth);
00125         cerr << "vimports: model file " << model << " does not exist" << endl;
00126         status = 2;
00127     }
00128     catch (const FS::Failure &f) {
00129         cerr << endl << "vimports: " << f << endl;
00130         status = 4;
00131     }
00132     catch (const ParseImports::Error &err) {
00133         cerr << endl; Indent(cerr, depth);
00134         cerr << endl << "vimports: " << err << endl;
00135         status = 3;
00136     }
00137     // Free any remaining Import objects.
00138     while (imports.size() > 0)
00139       delete imports.remlo();
00140     return status;
00141 }
00142 
00143 static bool isnumber(char *s) throw ()
00144 {
00145     while (isdigit(*s)) s++;
00146     return (*s == '\0');
00147 }
00148 
00149 int main(int argc, char *argv[]) 
00150 {
00151   /* Status = 0:  Success
00152               1:  Command line parse error
00153               2:  Model-file-not-found error
00154               3:  Model file parse error
00155               4:  Filesystem (e.g. read) error
00156   */
00157   int status; /* Set only by Search(); parse errors exit via Syntax() call... */
00158     // command-line arguments
00159     int elideDepth = -1;
00160     TextSeq elideNames;
00161     ShowEntrySeq showNames;
00162 
00163     // parse command-line
00164     int arg = 1;
00165     while (arg < argc && *(argv[arg]) == '-') {
00166         if (strcmp(argv[arg], "-depth") == 0) {
00167             arg++;
00168             if (arg < argc) {
00169                 int res = sscanf(argv[arg], "%d", &elideDepth);
00170                 if (res != 1) {
00171                     Syntax("argument to '-depth' not a number", argv[arg]);
00172                 }
00173                 arg++;
00174             } else {
00175                 Syntax("no argument to '-depth' switch");
00176             }
00177         } else if (strcmp(argv[arg], "-elide") == 0) {
00178             arg++;
00179             if (arg < argc) {
00180                 elideNames.addhi(argv[arg++]);
00181             } else {
00182                 Syntax("no argument to '-elide' switch");
00183             }
00184         } else if (strcmp(argv[arg], "-show") == 0) {
00185             arg++;
00186             if (arg < argc) {
00187                 int depth = -1; // default if none specified
00188                 Text name(argv[arg++]);
00189                 if (arg < argc) {
00190                     if (isnumber(argv[arg])) {
00191                         int res = sscanf(argv[arg], "%d", &depth);
00192                         assert(res == 1);
00193                         arg++;
00194                     } else if (*argv[arg] != '-' && arg != argc - 1) {
00195                         Syntax("bad depth argument to '-show' switch",
00196                                argv[arg]);
00197                     }
00198                 }
00199                 showNames.addhi(ShowEntry(name, depth));
00200             } else {
00201                 Syntax("no argument to '-show' switch");
00202             }
00203         } else {
00204             Syntax("unrecognized argument", argv[arg]);
00205         }
00206     }
00207     if (argc > arg+1) {
00208       Syntax("too many arguments");
00209     }
00210     Text model((arg < argc) ? argv[arg] : ".main.ves");
00211 
00212     // get the working directory
00213     char wd_buff[PATH_MAX+1];
00214     char *res = getcwd(wd_buff, PATH_MAX+1); assert(res != (char *)NULL);
00215     res = strcat(wd_buff, "/"); assert(res != (char *)NULL);
00216     Text wd(wd_buff);
00217 
00218     // search for imports.
00219     // Could return the status directly, but this gives some additional debuggability.
00220     status = Search(ParseImports::ResolvePath(model, wd),
00221       /*depth=*/ 0, /*elideDepth=*/ elideDepth,
00222       elideNames, showNames);
00223     return status;
00224 }
00225     

Generated on Mon May 8 00:48:58 2006 for Vesta by  doxygen 1.4.2