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

main.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002     main.cpp  -  Main program
00003                              -------------------
00004     begin                : June 21 2002
00005     copyright            : (C) 2003 by Vojtìch Toman
00006     email                : vtoman@lit.cz
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00026 #include <cstdio>
00027 #include <fstream>
00028 
00029 
00030 #include "defs.h"
00031 #include "encodings.h"
00032 #include "exaltcodec.h"
00033 #include "list.h"
00034 #include "options.h"
00035 
00036 
00038 #define PRINT_VERSION                                           \
00039 {                                                               \
00040   OUTPUTNL("This is " << PACKAGE                                \
00041            << ", XML data compressor.");                        \
00042   OUTPUTNL("Version " << VERSION << ", build date: "            \
00043            << __DATE__);                                        \
00044   OUTPUTNL("Built against expat " << EXPAT_VERSION);            \
00045   OUTPUTNL("Copyright 2002 Vojtech Toman");                     \
00046 }
00047 
00048 
00054 #define OPT(_x_)                !strcmp(argv[i], (_x_))
00055 
00056 
00057 
00063 #define OPT_ERROR(_i_)                                          \
00064 {                                                               \
00065   ERR("'" << argv[_i_-1] << "' requires an argument");          \
00066   throw ExaltOptionException();                                 \
00067 }
00068 
00069 
00070 
00076 #define OPT_UNKNOWN(_opt_)                                      \
00077 {                                                               \
00078   ERR("Unknown option: '" << _opt_ << "'.");                    \
00079   throw ExaltOptionException();                                 \
00080 }
00081 
00082 
00083 
00087 #define OPT_NONE                                                \
00088 {                                                               \
00089   ERR("No input files specified.");                             \
00090   throw ExaltOptionException();                                 \
00091 }
00092 
00093 
00094 
00100 #define ENCODING_UNKNOWN(_name_)                                \
00101 {                                                               \
00102   ERR("Unknown encoding: '" << _name_ << "'.");                 \
00103   throw ExaltUnknownEncodingException();                        \
00104 }
00105 
00106 
00107 
00113 #define SET_OUTPUT_ENCODING(_enc_)                              \
00114 {                                                               \
00115   size_t j = 0;                                                 \
00116   Encodings::MIB mib = Encodings::Unknown;                      \
00117                                                                 \
00118   while (encodingNames[j].name)                                 \
00119     {                                                           \
00120       if (!strcmp(_enc_, encodingNames[j].name))                \
00121         mib = encodingNames[j].mib;                             \
00122       j++;                                                      \
00123     }                                                           \
00124   if (mib != Encodings::Unknown)                                \
00125     encodingMIB = mib;                                          \
00126   else                                                          \
00127     {                                                           \
00128       ENCODING_UNKNOWN(_enc_);                                  \
00129     }                                                           \
00130 }
00131 
00132 
00133 
00139 #define ENCODE_DECODE(_action_)                                 \
00140 {                                                               \
00141   bool canContinue = true;                                      \
00142                                                                 \
00143   if (fileName)                                                 \
00144     {                                                           \
00145       ifstream inFile(fileName);                                \
00146                                                                 \
00147       if (inFile)                                               \
00148         inFile.close();                                         \
00149       else                                                      \
00150         {                                                       \
00151           ERR("'" << fileName << "' doesn't exist!");           \
00152           canContinue = false;                                  \
00153         }                                                       \
00154     }                                                           \
00155                                                                 \
00156   if (!useStdout && canContinue)                                \
00157     {                                                           \
00158       if (outputFileNameLength != -1)                           \
00159         {                                                       \
00160           ifstream outFile(outputFileName);                     \
00161                                                                 \
00162           if (outFile && !force)                                \
00163             {                                                   \
00164               char c;                                           \
00165               outFile.close();                                  \
00166                                                                 \
00167               OUTPUTE("File '" << outputFileName                \
00168                       << "' exists. Overwrite (y or n)? ");     \
00169                                                                 \
00170               do { c = getchar(); } while (c == '\n');          \
00171                                                                 \
00172               canContinue = (c == 'y' || c == 'Y');             \
00173                                                                 \
00174               if (!canContinue && verbose)                      \
00175                 OUTPUTENL("Not overwritten.");                  \
00176             }                                                   \
00177         }                                                       \
00178     }                                                           \
00179                                                                 \
00180   if (canContinue && outputFileNameLength != -1)                \
00181     {                                                           \
00182       if (exaltCodec._action_(fileName, outputFileName))        \
00183         {                                                       \
00184           if (erase && fileName)                                \
00185             remove(fileName);                                   \
00186         }                                                       \
00187       else                                                      \
00188         throw ExaltIOException();                               \
00189     }                                                           \
00190 }
00191 
00192 
00193 
00201 static int testFileNameSuffix(const char *str, const char *suf)
00202 {
00203   int i = strlen(str)-1;
00204   int j = strlen(suf)-1;
00205 
00206   while (j > -1)
00207     {
00208       if (str[i] != suf[j])
00209         return -1;
00210 
00211       i--;
00212       j--;
00213     }
00214 
00215   return i+1;
00216 }
00217 
00218 
00219 
00220 
00224 static void usage(void)
00225 {
00226   OUTPUTNL("Usage: " << PACKAGE << " [options and files in any order]");
00227   OUTPUTNL("where options are:");
00228   OUTPUTENDLINE;
00229   OUTPUTNL("  -s|--suffix .suf      use suffix .suf on compressed files");
00230   OUTPUTNL("  -d|--decompress       decompress");
00231   OUTPUTNL("  -f|--force            overwrite files, don't stop on errors");
00232   OUTPUTNL("  -c|--stdout           write on standard output");
00233   OUTPUTNL("  -a|--adaptive         use the adaptive model");
00234   OUTPUTNL("  -x|--erase            erase source files after (de)compression");
00235   OUTPUTNL("  -e|--encoding enc     set decompressed output encoding (to be implemented)");
00236   OUTPUTNL("  -l|--list-encodings   list recognized encodings");
00237   OUTPUTNL("  -v|--verbose          be verbose");
00238   OUTPUTNL("  -m|--print-models     display the models of the elements (requires the adaptive model)");
00239   OUTPUTNL("                        (warning: the models may be huge!)");
00240   OUTPUTNL("  -g|--print-grammar    display the content of the resulting grammar");
00241   OUTPUTNL("                        (warning: the grammar may be huge!)");
00242   OUTPUTNL("  -V|--version          display version number");
00243   OUTPUTNL("  -L|--license          display version number and software license");
00244   OUTPUTNL("  -h|--help             show this help");
00245 
00246   OUTPUTENDLINE;
00247   OUTPUTNL("The default action is to compress. If no file names are given,");
00248   OUTPUTNL("or if a file name is '-', " << PACKAGE << " compresses or decompresses");
00249   OUTPUTNL("from standard input to standard output.");
00250   
00251 }
00252 
00253 
00254 
00258 
00259 
00260 
00271 int main(int argc, char **argv)
00272 {
00273 
00274   UserAction selectedAction = Compress;         //the action of the user
00275   char *outputFileSuffix = 0;                   //user supported suffix of output files
00276   bool force = false;                           //overwrite files?
00277   bool verbose = false;                         //be verbose?
00278   bool printGrammar = false;                    //the resulting grammar is not printed by default
00279   bool printModels = false;                     //the resulting models are not printed by default
00280   bool useStdout = false;                       //use standard output?
00281   bool adaptiveModel = false;                   //use adaptive model?
00282   bool erase = false;                           //erase source files after (de)compression?
00283 
00284   //list of recognized encodings (not necessarily supported!)
00285   Encodings::EncodingName encodingNames[] = { ENCODING_NAMES };
00286 
00287   //default output encoding dependent on expat (UTF_8 or UTF_16)
00288   Encodings::MIB encodingMIB = DEFAULT_OUTPUT_ENCODING;
00289 
00290 
00291   List<char> unrecognizedParamList;             //list of unrecognized command line arguments
00292   List<char> filesToProcess;                    //list of file do process
00293 
00294   ExaltOptions::resetOptions();
00295 
00296   try
00297     {
00298       for (int i = 1; i < argc; ++i)
00299         {
00300           if (OPT("--suffix") || OPT("-s"))
00301             {
00302               //set compressed files suffix
00303               if ((++i) >= argc)
00304                 OPT_ERROR(i);
00305 
00306               outputFileSuffix = argv[i];
00307             }
00308 
00309           else if (OPT("--force") || OPT("-f"))
00310             {
00311               //force (overwrite files, don't stop on errors)
00312               force = true;
00313             }
00314 
00315           else if (OPT("--verbose") || OPT("-v"))
00316             {
00317               verbose = true;
00318             }
00319 
00320           else if (OPT("--print-models") || OPT("-m"))
00321             {
00322               printModels = true;
00323             }
00324 
00325           else if (OPT("--print-grammar") || OPT("-g"))
00326             {
00327               printGrammar = true;
00328             }
00329 
00330           else if (OPT("--stdout") || OPT("-c"))
00331             {
00332               useStdout = true;
00333             }
00334 
00335           else if (OPT("--decompress") || OPT("-d"))
00336             {
00337               selectedAction = Decompress;
00338             }
00339 
00340           else if (OPT("--adaptive") || OPT("-a"))
00341             {
00342               adaptiveModel = true;
00343             }
00344 
00345           else if (OPT("--encoding") || OPT("-e"))
00346             {
00347               //set compressed files suffix
00348               if ((++i) >= argc)
00349                 OPT_ERROR(i);
00350 
00351               SET_OUTPUT_ENCODING(argv[i]);
00352             }
00353 
00354           else if (OPT("--list-encodings") || OPT("-l"))
00355             {
00356               OUTPUTNL("List of recognized input/output encodings (not necessarily supported!):");
00357               OUTPUTENDLINE;
00358               LIST_ENCODINGS;
00359               exit(EXIT_SUCCESS);
00360             }
00361 
00362           else if (OPT("--erase") || OPT("-x"))
00363             {
00364               erase = true;
00365             }
00366 
00367           else if (OPT("--version") || OPT("-V"))
00368             {
00369               //print version info
00370               PRINT_VERSION;
00371               exit(EXIT_SUCCESS);
00372             }
00373 
00374           else if (OPT("--license") || OPT("-L"))
00375             {
00376               //print version info
00377               PRINT_VERSION;
00378 
00379               //print the license
00380               OUTPUTENDLINE;
00381               OUTPUTNL("This program comes with ABSOLUTELY NO WARRANTY. You may redistribute");
00382               OUTPUTNL("copies of this program under the terms of the GNU General Public License.");
00383               OUTPUTNL("For more information about these matters, see the file named COPYING.");
00384 
00385               OUTPUTENDLINE;
00386               OUTPUTNL("Arithmetic coding routines are based on the sources originally written");
00387               OUTPUTNL("by Alistair Moffat. Their use is restricted by the following license:");
00388               OUTPUTENDLINE;
00389 
00390               OUTPUTNL("These programs are supplied free of charge for research purposes only,");
00391               OUTPUTNL("and may not sold or incorporated into any commercial product. There is");
00392               OUTPUTNL("ABSOLUTELY NO WARRANTY of any sort, nor any undertaking that they are");
00393               OUTPUTNL("fit for ANY PURPOSE WHATSOEVER. Use them at your own risk. If you do");
00394               OUTPUTNL("happen to find a bug, or have modifications to suggest, please report");
00395               OUTPUTNL("the same to Alistair Moffat, alistair@cs.mu.oz.au. The copyright");
00396               OUTPUTNL("notice above and this statement of conditions must remain an integral");
00397               OUTPUTNL("part of each and every copy made of these files.");
00398 
00399               OUTPUTNL("(Search for the license text in the sources to find the concrete files.)");
00400               OUTPUTEENDLINE;
00401 
00402               exit(EXIT_SUCCESS);
00403             }
00404 
00405           else if (OPT("--help") || OPT("-h"))
00406             {
00407               throw ExaltOptionException();
00408             }
00409 
00410           else
00411             {
00412               //collect unrecognized parameters/options
00413               unrecognizedParamList.append(argv[i]);
00414             }
00415         }
00416       
00417       for (char *unrecognized = unrecognizedParamList.first(); unrecognized; unrecognized = unrecognizedParamList.next())
00418         {
00419           if (strcmp(unrecognized, "-") && unrecognized[0] == '-')
00420             {
00421               OPT_UNKNOWN(unrecognized);
00422             }
00423           else
00424             filesToProcess.append(unrecognized);
00425         }
00426     }
00427 
00428   catch (ExaltException)
00429     {
00430       usage();
00431       exit(EXIT_FAILURE);
00432     }
00433 
00434 
00435   //set the options
00436   if (verbose)
00437     ExaltOptions::setOption(ExaltOptions::Verbose, ExaltOptions::Yes);
00438   else
00439     ExaltOptions::setOption(ExaltOptions::Verbose, ExaltOptions::No);
00440 
00441   if (printModels)
00442     ExaltOptions::setOption(ExaltOptions::PrintModels, ExaltOptions::Yes);
00443   else
00444     ExaltOptions::setOption(ExaltOptions::PrintModels, ExaltOptions::No);
00445 
00446   if (printGrammar)
00447     ExaltOptions::setOption(ExaltOptions::PrintGrammar, ExaltOptions::Yes);
00448   else
00449     ExaltOptions::setOption(ExaltOptions::PrintGrammar, ExaltOptions::No);
00450 
00451   if (adaptiveModel)
00452     ExaltOptions::setOption(ExaltOptions::Model, ExaltOptions::AdaptiveModel);
00453   else
00454     ExaltOptions::setOption(ExaltOptions::Model, ExaltOptions::SimpleModel);
00455 
00456   //set output encoding
00457   ExaltOptions::setOption(ExaltOptions::Encoding, encodingMIB);
00458 
00459 
00460   //perform selected action
00461   switch (selectedAction)
00462     {
00463     case Compress:
00464       if (filesToProcess.isEmpty())
00465         //if no files have been specified, use stdin and stdout
00466         filesToProcess.append("-");
00467 
00468       for (char *fileName = filesToProcess.first(); fileName; fileName = filesToProcess.next())
00469         {
00470           char *outputFileName = 0;
00471           int outputFileNameLength = 0;
00472               
00473           if (!strcmp(fileName, "-"))
00474             {
00475               OUTPUTENL("Compressing standard input to standard output.");
00476               fileName = 0;
00477             }
00478 
00479           if (useStdout)
00480             {
00481               if (fileName)
00482                 {
00483                   //NULL means stdout for output
00484                   outputFileName = 0;
00485                       
00486                   if (verbose)
00487                     OUTPUTENL("Encoding '" << fileName << "' to standard output.");
00488                 }
00489             }
00490           else
00491             {
00492               if (fileName)
00493                 {
00494                   outputFileNameLength = strlen(fileName);
00495                   if (outputFileSuffix)
00496                     outputFileNameLength += strlen(outputFileSuffix);
00497                   else
00498                     outputFileNameLength += strlen(DEFAULT_FILE_SUFFIX);
00499 
00500                   NEW(outputFileName, char[outputFileNameLength+1]);
00501                       
00502                   strcpy(outputFileName, fileName);
00503                   if (outputFileSuffix)
00504                     strcat(outputFileName, outputFileSuffix);
00505                   else
00506                     strcat(outputFileName, DEFAULT_FILE_SUFFIX);
00507                       
00508                   if (verbose)
00509                     OUTPUTENL("Encoding '" << fileName << "' to '" << outputFileName << "'.");
00510                 }
00511             }
00512 
00513           //create the exalt codec
00514 //        ExaltCodec exaltCodec;
00515           try
00516             {
00517               ExaltCodec exaltCodec;
00518               ENCODE_DECODE(encode);
00519             }
00520 
00521           catch (ExaltContextNotInitializedException)
00522             {
00523               DBG("Use of uninitialized context!");
00524             }
00525           catch (ExaltException)
00526             {
00527               if (fileName)
00528                 ERR("Failed to compress '" << fileName << "'!");
00529               else
00530                 ERR("Failed to compress standard input!");
00531 
00532               if (outputFileName)
00533                 remove(outputFileName);
00534 
00535               if (!force)
00536                 exit(EXIT_FAILURE);
00537             }
00538 
00539 
00540           if (outputFileName)
00541             DELETE(outputFileName);
00542 
00543         }
00544       break;
00545 
00546     case Decompress:
00547       if (filesToProcess.isEmpty())
00548         //if no files have been specified, use stdin and stdout
00549         filesToProcess.append("-");
00550 
00551       for (char *fileName = filesToProcess.first(); fileName; fileName = filesToProcess.next())
00552         {
00553           char *outputFileName = 0;
00554           int outputFileNameLength = 0;
00555 
00556           if (!strcmp(fileName, "-"))
00557             {
00558               OUTPUTENL("Decompressing standard input to standard output.");
00559               fileName = 0;
00560             }
00561           else
00562             {
00563               if ((outputFileNameLength = testFileNameSuffix(fileName, DEFAULT_FILE_SUFFIX)) == -1)
00564                 if (outputFileSuffix)
00565                   outputFileNameLength = testFileNameSuffix(fileName, outputFileSuffix);
00566 
00567               if (outputFileNameLength == -1)
00568                 {
00569                   ERR("Unknown suffix, ignoring.");
00570                 }
00571             }
00572           
00573           
00574           if (useStdout)
00575             {
00576               if (fileName)
00577                 {
00578                   if (outputFileNameLength != -1)
00579                     {
00580                       //NULL means stdout for output
00581                       outputFileName = 0;
00582                       
00583                       if (verbose)
00584                         OUTPUTENL("Decompressing '" << fileName << "' to standard output.");
00585                     }
00586                 }
00587             }
00588           else
00589             {
00590               if (outputFileNameLength != -1)
00591                 {
00592                   if (fileName)
00593                     {
00594                       NEW(outputFileName, char[outputFileNameLength+1]);
00595                       strncpy(outputFileName, fileName, outputFileNameLength);
00596                       outputFileName[outputFileNameLength] = 0;
00597                       
00598                       if (verbose)
00599                         OUTPUTENL("Decoding '" << fileName << "' to '" << outputFileName << "'.");
00600                     }
00601                 }
00602             }
00603 
00604 
00605           //construct an exalt codec
00606           ExaltCodec exaltCodec;        //instance of the codec
00607           
00608           try
00609             {
00610               ENCODE_DECODE(decode);
00611             }
00612           
00613           catch (ExaltException)
00614             {
00615               if (fileName)
00616                 ERR("Failed to decompress '" << fileName << "'!");
00617               else
00618                 ERR("Failed to decompress standard input!");
00619 
00620               if (outputFileName)
00621                 remove(outputFileName);
00622 
00623               if (!force)
00624                 exit(EXIT_FAILURE);
00625             }
00626           
00627           if (outputFileName)
00628             DELETE(outputFileName);
00629         }
00630       
00631       break;
00632 
00633     default:
00634       ERR("Don't know what to do!");
00635       return EXIT_FAILURE;
00636     }
00637   
00638   return EXIT_SUCCESS;
00639 }

Generated on Wed Feb 5 10:43:02 2003 for Exalt by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002