OpenADFortTk (basic)
src/lib/support/sexpostream.cxx
Go to the documentation of this file.
00001 #include <cstring>  // for strlen
00002 
00003 //*************************** User Include Files ****************************
00004 
00005 #include "sexpostream.h"
00006 
00007 //*************************** Forward Declarations ***************************
00008 
00009 //****************************************************************************
00010 
00011 /*
00012   A table showing possible state movements.  The state-state table
00013   indicates whether it is possible to move from one state (in the left
00014   margin) to another state.  Given an initial state (in the left
00015   margin), the state-action table indicates the possible resulting
00016   states after an action
00017 
00018         States/Qalifiers          Actions
00019        |--------------------------------------------------------------------
00020        |          LIST      ATOM| Beg   Beg   End   End   Quot  Beg  End
00021        |INIT DEF  OPEN ERR  OPEN| Lst   Atom  Atom  Lst         Com  Com
00022        |-------------------------------------------------------------------- 
00023   INIT |no   yes  yes  yes  yes | LOPN  DEF   ERR   ERR   DEF  +COM -COM
00024   DEF  |no   yes  yes  yes  yes | LOPN  DEF   DEF   ERR   DEF  +COM -COM
00025   LOPN |no   yes  yes  yes  yes | LOPN  LOPN  LOPN  DEF   LOPN +COM -COM
00026        |                        |                   LOPN    
00027   ERR  |no   no   no   no   no  |+ERR  +ERR  +ERR  +ERR  +ERR  +ERR +ERR
00028   AOPN |no   yes  yes  yes  no  |+ERR  +ERR  -AOPN +ERR  +ERR  +ERR +ERR
00029   COM  |                        |+ERR  +ERR  +ERR  +ERR  +ERR  +ERR -COM
00030 
00031 
00032  */
00033 
00034 // For a comments to public member functions, see the interface file.
00035 
00036 sexp::ostream::ostream(std::streambuf* sb)
00037   : std::ostream(sb)
00038 {
00039   curAtomFlags = IOFlags::NONE;
00040   state = 0;
00041 
00042   SetState(INIT);
00043   indentAmnt = 0;
00044   indentStep = 2;
00045 }
00046 
00047 
00048 sexp::ostream::~ostream()
00049 {
00050 }
00051 
00052 
00053 // Atom: specialization for 'const char*'
00054 template <>
00055 void 
00056 sexp::ostream::Atom(int xflags, const char* const & val)
00057 {
00058   using namespace IOFlags;
00059 
00060   // Sanity check -- rely on BegAtom()
00061   BegAtom(xflags);
00062   const char* outstr = (val) ? val : "";
00063   if (IsFlag(xflags, A_DQUOTE)) {
00064     EscapeString(outstr);
00065   }
00066   else {
00067     (*this) << outstr;
00068   }
00069   EndAtom();
00070 }
00071 
00072 
00073 void
00074 sexp::ostream::BegAtom(int xflags)
00075 {
00076   using namespace IOFlags;
00077  
00078   // Sanity check
00079   if (!IsStateQClear()) {
00080     SetStateError();
00081     throw Exception("BegAtom: Cannot begin atom!");
00082   }
00083 
00084   // Get and check flags
00085   int flags = 0;
00086   if (slistStack.size() != 0) {
00087     int& f = slistStack.front();
00088     flags = f;
00089     SetFlag(f, L_NONEMPTY);
00090   }
00091   
00092   // (note that there can be two sets of atom flags)
00093   AddSpaceIfNecessary(flags);  
00094   if (IsFlag(xflags, A_SQUOTE) || IsFlag(flags, A_SQUOTE)) {
00095     (*this) << "'";
00096   }
00097   if (IsFlag(xflags, A_DQUOTE) || IsFlag(flags, A_DQUOTE)) {
00098     (*this) << '"';
00099   }
00100   if (IsFlag(xflags, A_OCT) || IsFlag(flags, A_OCT)) {
00101     (*this) << std::oct << "0";
00102   }
00103   if (IsFlag(xflags, A_HEX) || IsFlag(flags, A_HEX)) {
00104     (*this) << std::hex << "0x";
00105   }
00106   
00107   curAtomFlags = xflags;
00108   
00109   // Set state and qualifier
00110   if (IsState(INIT)) { SetState(DEFAULT); }
00111   SetStateQ(ATOM_OPEN); 
00112   SetAction(BEG_ATOM);
00113 }
00114 
00115 
00116 void
00117 sexp::ostream::EndAtom()
00118 {
00119   using namespace IOFlags;
00120 
00121   // Sanity check
00122   if (!IsStateQ(ATOM_OPEN)) {
00123     SetStateError();
00124     throw Exception("EndAtom: No currently open atom!");
00125   }
00126   
00127   // Get and check flags
00128   int flags = 0;
00129   if (slistStack.size() != 0) {
00130     flags = slistStack.front();
00131   }
00132   
00133   // (note that there can be two sets of atom flags)
00134   if (IsFlag(curAtomFlags, A_DQUOTE) || IsFlag(flags, A_DQUOTE)) {
00135     (*this) << '"';
00136   }
00137   if (IsFlag(curAtomFlags, A_OCT) || IsFlag(flags, A_OCT) ||
00138       IsFlag(curAtomFlags, A_HEX) || IsFlag(flags, A_HEX)) {
00139     (*this) << std::dec;
00140   }
00141   
00142   curAtomFlags = IOFlags::NONE;
00143   ResetStateQ(ATOM_OPEN); // State remains the same, except for qualifier
00144   SetAction(END_ATOM);
00145 }
00146 
00147 
00148 void
00149 sexp::ostream::BegList(int xflags)
00150   throw (sexp::ostream::Exception)
00151 {
00152   using namespace IOFlags;
00153 
00154   // Sanity check 
00155   if (!IsStateQClear()) {
00156     SetStateError();
00157     throw Exception("BegList: Cannot begin list!");
00158   }
00159 
00160   // Get and check flags
00161   int flags = 0;
00162   if (slistStack.size() != 0) {
00163     int& f = slistStack.front();
00164     flags = f;
00165     SetFlag(f, L_NONEMPTY);
00166   }
00167   
00168   // [FIXME: more checks]
00169   AddSpaceIfNecessary(flags);
00170   
00171   (*this) << '(';
00172   IndentIncr();
00173   
00174   slistStack.push_front(xflags);
00175   SetState(LIST_OPEN);
00176   SetAction(BEG_LIST);
00177 }
00178 
00179 
00180 void
00181 sexp::ostream::EndList()
00182 {
00183   using namespace IOFlags;
00184     
00185   // Sanity check
00186   if (!IsState(LIST_OPEN)) {
00187     SetStateError();
00188     throw Exception("EndList: Cannot end list!");
00189   } 
00190 
00191   int& flags = slistStack.front();
00192   
00193   IndentDecr();
00194   (*this) << ")";
00195   
00196   // Check flags...
00197   
00198   // Determine the appropriate state after an element has been closed
00199   slistStack.pop_front();
00200   if (slistStack.size() == 0) { 
00201     SetState(DEFAULT);
00202   } 
00203   else {
00204     SetState(LIST_OPEN);
00205   }
00206   SetAction(END_LIST);
00207 }
00208 
00209 
00210 void
00211 sexp::ostream::Quote()
00212 {
00213   // Sanity check 
00214   if (!IsStateQClear()) {
00215     SetStateError();
00216     throw Exception("Quote: Cannot quote!");
00217   }
00218   
00219   // Get and check flags
00220   int flags = 0;
00221   if (slistStack.size() != 0) {
00222     flags = slistStack.front();
00223   }
00224   
00225   AddSpaceIfNecessary(flags);
00226 
00227   (*this) << "'";
00228 
00229   // Set state and qualifier
00230   if (IsState(INIT)) { SetState(DEFAULT); }
00231   SetAction(QUOTE);
00232 }
00233 
00234 
00235 //****************************************************************************
00236 
00237 void
00238 sexp::ostream::BegComment()
00239 {
00240   // Sanity check
00241   if (IsStateQ(COMMENT)) {
00242     SetStateError();
00243     throw Exception("BegComment: Already within a comment!");
00244   }
00245   
00246   (*this) << ";; ";
00247 
00248   SetStateQ(COMMENT);
00249   SetAction(BEG_COMMENT);
00250 }
00251 
00252 
00253 void
00254 sexp::ostream::EndComment()
00255 {
00256   // Sanity check
00257   if (!IsStateQ(COMMENT)) {
00258     SetStateError();
00259     throw Exception("EndComment: Not within a comment!");
00260   }
00261   
00262   SetAction(END_COMMENT); // N.B.: this should come before EndLine()
00263   EndLine();
00264   ResetStateQ(COMMENT);
00265 }
00266 
00267 
00268 void
00269 sexp::ostream::Comment(const char* str)
00270 {
00271   // Sanity check -- rely on BegComment()
00272   
00273   BegComment();
00274   (*this) << str;
00275   EndComment();
00276 }
00277 
00278 
00279 //****************************************************************************
00280 
00281 void
00282 sexp::ostream::EscapeString(const char* str)
00283 {
00284   for (int i = 0; i < strlen(str); ++i) {
00285     char c = str[i];
00286     if (c == '\\' || c == '"') { // what about: \n
00287       (*this) << '\\';
00288     }
00289     (*this) << c;    
00290   }
00291 }
00292 
00293 
00294 //****************************************************************************
00295 
00296 void
00297 sexp::ostream::EndLine()
00298 {
00299   (*this) << "\n";
00300   SetAction(END_LINE); // N.B.: this should come before Indent()
00301   Indent();
00302 }
00303 
00304 
00305 void
00306 sexp::ostream::Indent()
00307 {
00308   for (int i = 0; i < indentAmnt; ++i) {
00309     (*this) << ' ';
00310   }
00311   SetAction(INDENT);
00312 }
00313 
00314 //****************************************************************************
00315 
00316 void
00317 sexp::ostream::AddSpaceIfNecessary(int flags)
00318 {
00319   using namespace IOFlags;
00320   
00321   // short-circuit if we just quoted, ended a line, or indented
00322   if (WasAction(QUOTE) || WasAction(END_LINE) || WasAction(INDENT)) {
00323     return;
00324   }
00325   
00326   if (IsFlag(flags, L_NONEMPTY)) {
00327     (*this) << ' ';
00328   }
00329 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines