arg.h

Go to the documentation of this file.
00001 
00002 
00003 
00053 
00054 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00055 //
00056 // This file is part of the Homology Library.  This library is free software;
00057 // you can redistribute it and/or modify it under the terms of the GNU
00058 // General Public License as published by the Free Software Foundation;
00059 // either version 2 of the License, or (at your option) any later version.
00060 //
00061 // This library is distributed in the hope that it will be useful,
00062 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00063 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00064 // GNU General Public License for more details.
00065 //
00066 // You should have received a copy of the GNU General Public License along
00067 // with this software; see the file "license.txt".  If not, write to the
00068 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00069 // MA 02111-1307, USA.
00070 
00071 // You may want to include "textfile.h" and "timeused.h" before this file.
00072 // Started on March 3, 2002. Last revision: March 9, 2007.
00073 
00074 
00075 #ifndef _CHOMP_SYSTEM_ARG_H_
00076 #define _CHOMP_SYSTEM_ARG_H_
00077 
00078 #include "chomp/system/config.h"
00079 
00080 #include <iostream>
00081 #include <iomanip>
00082 #include <cstring>
00083 #include <sstream>
00084 #include <cctype>
00085 
00086 namespace chomp {
00087 namespace homology {
00088 
00089 // the main front-end class defined in this file
00090 class arguments;
00091 
00092 
00093 // --------------------------------------------------
00094 // -------------------- argflags --------------------
00095 // --------------------------------------------------
00096 
00100 class argflags
00101 {
00102 public:
00104         enum names {obligatory = 0x01, hasdefault = 0x02,
00105                 filled = 0x04, breakinterpreting = 0x08,
00106                 toomany = 0x10, missingvalue = 0x20,
00107                 readerror = 0x40, ignorevalue = 0x80};
00108 
00110         argflags (): n (0) {}
00111 
00113         ~argflags () {}
00114 
00116         void set (int flag) {n |= flag;}
00117 
00119         void unset (int flag) {n &= ~flag;}
00120 
00122         bool get (int flag) const {return !!(n & flag);}
00123 
00124 private:
00126         int n;
00127 
00128 }; /* argflags */
00129 
00130 
00131 // --------------------------------------------------
00132 // ------------------- argelement -------------------
00133 // --------------------------------------------------
00134 
00137 class argelement
00138 {
00139 public:
00141         argelement (const char *_name);
00142 
00144         virtual ~argelement ();
00145 
00147         const char *getname () const;
00148 
00151         char *getvalue (char *str);
00152 
00156         virtual int setvalue (char *str, char *next) = 0;
00157 
00159         virtual void restore () = 0;
00160 
00162         virtual void show (std::ostream &out) const = 0;
00163 
00165         void resetflags ();
00166 
00168         void set (int flag);
00169 
00171         void unset (int flag);
00172 
00174         bool get (int flag) const;
00175 
00176 private:
00179         char *name;
00180 
00182         argflags flags;
00183 
00184 }; /* class argelement */
00185 
00186 inline argelement::argelement (const char *_name): flags ()
00187 {
00188         if (!_name || !*_name)
00189                 name = NULL;
00190         else
00191         {
00192                 name = new char [strlen (_name) + 1];
00193                 strcpy (name, _name);
00194         }
00195         return;
00196 } /* argelement::argelement */
00197 
00198 inline argelement::~argelement ()
00199 {
00200         if (name)
00201                 delete [] name;
00202         return;
00203 } /* argelement::~argelement */
00204 
00205 inline const char *argelement::getname () const
00206 {
00207         return name;
00208 } /* argelement::getname */
00209 
00210 inline void argelement::resetflags ()
00211 {
00212         flags. unset (argflags::filled);
00213         flags. unset (argflags::readerror);
00214         flags. unset (argflags::toomany);
00215         flags. unset (argflags::missingvalue);
00216         return;
00217 } /* argelement::resetflags */
00218 
00219 inline void argelement::set (int flag)
00220 {
00221         flags. set (flag);
00222         return;
00223 } /* argelement::set */
00224 
00225 inline void argelement::unset (int flag)
00226 {
00227         flags. unset (flag);
00228         return;
00229 } /* argelement::unset */
00230 
00231 inline bool argelement::get (int flag) const
00232 {
00233         return flags. get (flag);
00234 } /* argelement::get */
00235 
00236 inline std::ostream &operator << (std::ostream &out, const argelement &p)
00237 {
00238         p. show (out);
00239         return out;
00240 } /* operator << */
00241 
00242 
00243 // --------------------------------------------------
00244 // -------------------- argunit ---------------------
00245 // --------------------------------------------------
00246 
00252 template <class type>
00253 class argunit: public argelement
00254 {
00255 public:
00258         argunit (const char *_name, type &_value);
00259 
00263         argunit (const char *_name, type &_value, type defaultvalue);
00264 
00267         argunit (const char *_name, type *_value, int &_count,
00268                 int _size);
00269 
00272         argunit (const char *_name, type *_value, int &_count,
00273                 int _size, type defaultvalue);
00274 
00276         int setvalue (char *str, char *next);
00277 
00279         void restore ();
00280 
00282         void show (std::ostream &out) const;
00283 
00284 private:
00287         type &value;
00288 
00290         type defaultvalue;
00291 
00294         type previousvalue;
00295 
00297         type *table;
00298 
00301         int *count;
00302 
00304         int previouscount;
00305 
00307         int size;
00308 
00309 }; /* class argunit */
00310 
00311 template <class type>
00312 inline argunit<type>::argunit (const char *_name, type &_value):
00313         argelement (_name), value (_value), previousvalue (_value),
00314         table (NULL)
00315 {
00316         return;
00317 } /* argunit<type>::argunit */
00318 
00319 template <class type>
00320 inline argunit<type>::argunit (const char *_name, type &_value,
00321         type _defaultvalue):
00322         argelement (_name), value (_value), defaultvalue (_defaultvalue),
00323         previousvalue (_value), table (NULL)
00324 {
00325         set (argflags::hasdefault);
00326         return;
00327 } /* argunit<type>::argunit */
00328 
00329 template <class type>
00330 inline argunit<type>::argunit (const char *_name, type *_value,
00331         int &_count, int _size):
00332         argelement (_name), value (*_value), previousvalue (*_value),
00333         table (_value), count (&_count), previouscount (_count),
00334         size (_size)
00335 {
00336         return;
00337 } /* argunit<type>::argunit */
00338 
00339 template <class type>
00340 inline argunit<type>::argunit (const char *_name, type *_value,
00341         int &_count, int _size, type _defaultvalue):
00342         argelement (_name), value (*_value), defaultvalue (_defaultvalue),
00343         previousvalue (*_value), table (_value),
00344         count (&_count), previouscount (_count), size (_size)
00345         
00346 {
00347         set (argflags::hasdefault);
00348         return;
00349 } /* argunit<type>::argunit */
00350 
00353 template <class type>
00354 inline int readfromstring (char *str, type &t)
00355 {
00356         std::istringstream s (str);
00357         try
00358         {
00359                 s >> t;
00360                 if (!s)
00361                         return -1;
00362         }
00363         catch (...)
00364         {
00365                 return -1;
00366         }
00367         return 0;
00368 } /* readfromstring */
00369 
00372 inline int readfromstring (char *str, char *&t)
00373 {
00374         t = str;
00375         return 0;
00376 } /* readfromstring */
00377 
00380 // This function was added by Tomek Kapela. His remark
00381 // justifying this addition: "e.g to replace default constant C strings".
00382 inline int readfromstring (char *str, const char *&t)
00383 {
00384         t = str;
00385         return 0;
00386 } /* readfromstring */
00387 
00389 inline int readfromstring (char *str, bool &t)
00390 {
00391         switch (*str)
00392         {
00393                 case 'T':
00394                 case 't':
00395                 case 'Y':
00396                 case 'y':
00397                 case '1':
00398                         t = true;
00399                         return 0;
00400                 case 'F':
00401                 case 'f':
00402                 case 'N':
00403                 case 'n':
00404                 case '0':
00405                         t = false;
00406                         return 0;
00407                 default:
00408                         return -1;
00409         }
00410 } /* readfromstring */
00411 
00412 template <class type>
00413 inline int argunit<type>::setvalue (char *str, char *next)
00414 {
00415         // determine the string from which the value should be read
00416         int usenext = 0;
00417         char *s;
00418         if (str && *str)
00419                 s = str;
00420         else
00421         {
00422                 if (next && *next && ((*next != '-') ||
00423                         std::isdigit (next [1])))
00424                 {
00425                         s = next;
00426                         usenext = 1;
00427                 }
00428                 else
00429                         s = NULL;
00430         }
00431 
00432         // read the element from the string if available
00433         int result = -1;
00434         type element;
00435         if (s)
00436                 result = readfromstring (s, element);
00437 
00438         // if could not read the string, try the default value
00439         if (result < 0)
00440         {
00441                 if (get (argflags::hasdefault))
00442                 {
00443                         element = defaultvalue;
00444                         usenext = 0;
00445                 }
00446                 else
00447                 {
00448                         if (s)
00449                                 set (argflags::readerror);
00450                         else
00451                                 set (argflags::missingvalue);
00452                         return 0;
00453                 }
00454         }
00455 
00456         // put the element to its place
00457         if (table)
00458                 // if there is still room in the table, put the element there
00459                 if (*count < size)
00460                         table [(*count) ++] = element;
00461                 // if the table is full, indicate it
00462                 else
00463                 {
00464                         set (argflags::toomany);
00465                         set (argflags::filled);
00466                 }
00467         else
00468         {
00469                 value = element;
00470                 set (argflags::filled);
00471         }
00472 
00473         return usenext;
00474 } /* argunit<type>::setvalue */
00475 
00476 template <class type>
00477 void argunit<type>::restore ()
00478 {
00479         if (!table)
00480                 value = previousvalue;
00481         else
00482                 *count = previouscount;
00483         resetflags ();
00484         return;
00485 } /* argunit<type>::restore */
00486 
00487 template <class type>
00488 void argunit<type>::show (std::ostream &out) const
00489 {
00490         if (get (argflags::obligatory))
00491                 out << "Oblig. ";
00492         if (getname () && *getname ())
00493         {
00494                 if (get (argflags::ignorevalue))
00495                         out << "Switch";
00496                 else
00497                         out << "Param.";
00498                 out << " '-" << getname () << "'";
00499         }
00500         else
00501                 out << "Word";
00502         if (!table && get (argflags::filled))
00503                 out << " set to '" << value << "'";
00504         else if (table && *count)
00505         {
00506                 for (int i = 0; i < *count; ++ i)
00507                         out << (i ? ", " : " set to '") << table [i];
00508                 out << "'";
00509                 if (get (argflags::toomany))
00510                         out << " [too many!]";
00511         }
00512         else
00513                 out << " not found";
00514         if (get (argflags::hasdefault))
00515                 out << " (default: '" << defaultvalue << "')";
00516         else
00517                 out << " (no default value)";
00518         out << "." << std::endl;
00519         return;
00520 } /* argunit<type>::show */
00521 
00522 
00523 // --------------------------------------------------
00524 // ------------------- arguments --------------------
00525 // --------------------------------------------------
00526 
00534 class arguments
00535 {
00536 public:
00538         arguments ();
00539 
00541         ~arguments ();
00542 
00544         void add (argelement *p);
00545 
00548         int remove (char *name);
00549 
00556         int analyze (int argc, char *argv [],
00557                 std::ostream &out = std::cerr);
00558 
00561         void reset ();
00562 
00564         friend std::ostream &operator << (std::ostream &out,
00565                 arguments &p);
00566 
00567 private:
00569         int n;
00570 
00572         int length;
00573 
00575         argelement **tab;
00576 
00578         void inctable ();
00579 
00580 }; /* class arguments */
00581 
00582 inline arguments::arguments ()
00583 {
00584         n = 0;
00585         length = 0;
00586         tab = NULL;
00587         return;
00588 } /* arguments::arguments */
00589 
00590 inline void arguments::add (argelement *p)
00591 {
00592         inctable ();
00593         tab [n ++] = p;
00594         return;
00595 } /* arguments::add */
00596 
00597 // --------------------------------------------------
00598 
00604 template <class type>
00605 inline void arg (arguments &a, const char *name, type &value)
00606 {
00607         argunit<type> *p = new argunit<type> (name, value);
00608         a. add (p);
00609         return;
00610 } /* arg */
00611 
00615 template <class type>
00616 inline void arg (arguments &a, const char *name, type &value,
00617         type defaultvalue)
00618 {
00619         argunit<type> *p = new argunit<type> (name, value, defaultvalue);
00620         a. add (p);
00621         return;
00622 } /* arg */
00623 
00625 inline void arg (arguments &a, const char *name, char *&value,
00626         const char *defaultvalue)
00627 {
00628         argunit<char *> *p =
00629                 new argunit<char *> (name, value,
00630                         const_cast<char *> (defaultvalue));
00631         a. add (p);
00632         return;
00633 } /* arg */
00634 
00639 template <class type>
00640 inline void arg (arguments &a, const char *name, type *value,
00641         int &count, int size)
00642 {
00643         argunit<type> *p = new argunit<type> (name, value, count, size);
00644         a. add (p);
00645         return;
00646 } /* arg */
00647 
00649 template <class type>
00650 inline void arg (arguments &a, const char *name, type *value,
00651         int &count, int size, type defaultvalue)
00652 {
00653         argunit<type> *p = new argunit<type> (name, value, count, size,
00654                 defaultvalue);
00655         a. add (p);
00656         return;
00657 } /* argoblig */
00658 
00662 template <class type>
00663 inline void argoblig (arguments &arg, const char *name, type &value)
00664 {
00665         argunit<type> *p = new argunit<type> (name, value);
00666         p -> set (argflags::obligatory);
00667         arg. add (p);
00668         return;
00669 } /* argoblig */
00670 
00672 template <class type>
00673 inline void argoblig (arguments &arg, const char *name, type &value,
00674         type defaultvalue)
00675 {
00676         argunit<type> *p = new argunit<type> (name, value, defaultvalue);
00677         p -> set (argflags::obligatory);
00678         arg. add (p);
00679         return;
00680 } /* argoblig */
00681 
00683 inline void argoblig (arguments &arg, const char *name, char *&value,
00684         const char *defaultvalue)
00685 {
00686         argunit<char *> *p =
00687                 new argunit<char *> (name, value, (char *) defaultvalue);
00688         p -> set (argflags::obligatory);
00689         arg. add (p);
00690         return;
00691 } /* argoblig */
00692 
00697 template <class type>
00698 inline void argbreak (arguments &arg, const char *name, type &value)
00699 {
00700         argunit<type> *p = new argunit<type> (name, value);
00701         p -> set (argflags::breakinterpreting);
00702         p -> set (argflags::ignorevalue);
00703         arg. add (p);
00704         return;
00705 } /* argbreak */
00706 
00708 template <class type>
00709 inline void argbreak (arguments &arg, const char *name, type &value,
00710         type defaultvalue)
00711 {
00712         argunit<type> *p = new argunit<type> (name, value, defaultvalue);
00713         p -> set (argflags::breakinterpreting);
00714         p -> set (argflags::ignorevalue);
00715         arg. add (p);
00716         return;
00717 } /* argbreak */
00718 
00720 inline void argbreak (arguments &arg, const char *name, char *&value,
00721         const char *defaultvalue)
00722 {
00723         argunit<char *> *p =
00724                 new argunit<char *> (name, value, (char *) defaultvalue);
00725         p -> set (argflags::breakinterpreting);
00726         p -> set (argflags::ignorevalue);
00727         arg. add (p);
00728         return;
00729 } /* argbreak */
00730 
00732 inline void argbreak (arguments &arg, const char *name)
00733 {
00734         char *dummystring = NULL;
00735         argunit<char *> *p = new argunit<char *> (name, dummystring);
00736         p -> set (argflags::breakinterpreting);
00737         p -> set (argflags::ignorevalue);
00738         arg. add (p);
00739         return;
00740 } /* argbreak */
00741 
00745 template <class type>
00746 inline void argswitch (arguments &arg, const char *name, type &value,
00747         const type &defaultvalue)
00748 {
00749         argunit<type> *p = new argunit<type> (name, value, defaultvalue);
00750         p -> set (argflags::ignorevalue);
00751         arg. add (p);
00752         return;
00753 } /* argswitch */
00754 
00756 inline void argswitch (arguments &arg, const char *name, char *&value,
00757         const char *defaultvalue)
00758 {
00759         argunit<char *> *p =
00760                 new argunit<char *> (name, value, (char *) defaultvalue);
00761         p -> set (argflags::ignorevalue);
00762         arg. add (p);
00763         return;
00764 } /* argswitch */
00765 
00767 inline void argswitch (arguments &arg, const char *name)
00768 {
00769         char *dummystring = NULL;
00770         argunit<char *> *p = new argunit<char *> (name, dummystring);
00771         p -> set (argflags::ignorevalue);
00772         arg. add (p);
00773         return;
00774 } /* argswitch */
00775 
00779 inline void arghelp (arguments &a)
00780 {
00781         argbreak (a, "?");
00782         argbreak (a, "h");
00783         argbreak (a, "H");
00784         argbreak (a, "-help");
00785         return;
00786 } /* arghelp */
00787 
00788 // --------------------------------------------------
00789 
00790 #ifdef OUTPUTSTREAM
00791 
00794 inline void argstreams (arguments &a, char *&logfilename, char *&seqfilename,
00795         bool &quiet, bool &debug)
00796 {
00797         arg (a, "-log", logfilename);
00798         arg (a, "-seq", seqfilename);
00799         argswitch (a, "-quiet", quiet, true);
00800         argswitch (a, "-debug", debug, true);
00801         return;
00802 } /* argstreams */
00803 
00807 inline void setstreams (const char *logfilename, char *seqfilename,
00808         bool quiet, bool debug)
00809 {
00810         if (debug)
00811                 sbug. show = true;
00812         if (quiet)
00813         {
00814                 sout. show = false;
00815                 scon. show = false;
00816                 sbug. show = false;
00817         }
00818         if (logfilename)
00819         {
00820                 slog. logfile (logfilename);
00821                 slog. keepforever ();
00822                 sout. logfile (slog);
00823                 serr. logfile (slog);
00824                 if (debug)
00825                         sbug. logfile (slog);
00826         }
00827         if (seqfilename)
00828                 sseq. logfile (seqfilename);
00829 #ifdef TIMEUSED
00830         program_time = sout;
00831 #endif
00832         return;
00833 } /* setstreams */
00834 
00835 #ifndef algstreamprepare
00836 
00837 
00838 
00839 #define argstreamprepare(a) \
00840 char *arg_logfilename = NULL; \
00841 char *arg_seqfilename = NULL; \
00842 char *arg_computername = NULL; \
00843 bool arg_quiet = false; \
00844 bool arg_debug = false; \
00845 arg (a, "-comp", arg_computername); \
00846 argstreams (a, arg_logfilename, arg_seqfilename, arg_quiet, arg_debug);
00847 #endif
00848 
00849 #ifndef argstreamset
00850 
00851 
00852 
00853 #define argstreamset() \
00854 setstreams (arg_logfilename, arg_seqfilename, arg_quiet, arg_debug); \
00855 slog << commandline (argc, argv) << "\n\n"; \
00856 if (arg_computername) slog << "Running on " << arg_computername << ". "; \
00857 slog << "Start time: " << currenttime () << '\n';
00858 #endif
00859 
00860 #endif
00861 /* */
00862 
00863 
00864 } // namespace homology
00865 } // namespace chomp
00866 
00867 #endif // _CHOMP_SYSTEM_ARG_H_
00868 
00870