muSED.cxx

Go to the documentation of this file.
00001 #include <cxxtls/muSED.h>
00002 
00003 namespace cxxtls
00004 {
00005 namespace muSED
00006 {
00007 
00009      void expandEscapes(std::string &input)
00010      {
00011         // modify input such that \n is newline.  Do not modify \0-\n
00012 
00013         std::string tmp;
00014 
00015         char const *scan = input.data();
00016         char const *end  = scan + input.size();
00017 
00018         while(scan != end)
00019         {
00020            char c= *scan;
00021 
00022            if(c == '\\')
00023            {
00024               ++scan;
00025 
00026               if(scan == end)
00027               {
00028                 tmp += '\\';
00029 
00030                 break;
00031               }
00032               else
00033               switch(c = *scan++)
00034               {
00035                  case 'n':  tmp += '\n'; break;
00036                  case 'r':  tmp += '\r'; break;
00037                  case 't':  tmp += '\t'; break;
00038                  case 'a':  tmp += '\a'; break;
00039                  case 'b':  tmp += '\b'; break;
00040 
00041                  case 'e':  tmp += char(0x1b); break;
00042 
00043                  default: 
00044                      tmp += '\\';
00045                      tmp += c;
00046 
00047               }
00048 
00049 
00050            }
00051            else
00052            {
00053               tmp += c;
00054               ++scan;
00055            }
00056 
00057 
00058 
00059         }
00060 
00061 
00062         input.swap(tmp);
00063 
00064      }
00065 
00067         bool Filter::passes(size_t lineNo, bool isLast, std::string const &line)
00068         {
00069             switch(type_)
00070             {
00071                 case regex:
00072 
00073                     if(!regex_(line))
00074                       return false;
00075 
00076                     // drop thorugh to true
00077 
00078                     break;
00079 
00080                 case lineNumber:
00081 
00082                    return line_ == lineNo;
00083 
00084                 case lastLine:
00085                     return isLast;
00086 
00087                 default:  
00088                   break;  // drop through
00089 
00090             }
00091 
00092             return true;  // none means true for all lines
00093 
00094         }
00096         std::string Filter::debugString() const
00097         {
00098            switch(type_)
00099            {
00100               case regex:       return std::string("regex(") + std::string(regex_) + ")";
00101               case lastLine:    return std::string("lastLine()");
00102 
00103               case lineNumber:
00104               {
00105                  char buffer[256];
00106 
00107                  snprintf(buffer, sizeof(buffer), "line(%d)", int(line_));
00108 
00109                  return buffer;
00110               }
00111 
00112               default:
00113                 break; // drop through
00114            }
00115 
00116            return "<none>";
00117         }
00119          LineRangeActivationState Statement::activationState() 
00120          {
00121             ActivationMap  *am= 0;
00122 
00123             if(parentStatement_)
00124                am = &parentStatement_->childStatementActivationMap_;
00125             else
00126                am = & childStatementActivationMap_;
00127 
00128             if(am->find(this) == am->end())
00129             {
00130                return neverExecuted;
00131             }
00132             
00133             return (*am)[this];
00134 
00135 
00136          }
00138         void Statement::setActivationState(LineRangeActivationState newState)
00139         {
00140             ActivationMap *am = 0;
00141 
00142             if(parentStatement_)
00143                am = &parentStatement_->childStatementActivationMap_;
00144             else
00145                am = &childStatementActivationMap_;
00146                
00147             ActivationMap::iterator loc = am->find(this);
00148 
00149             if(loc == am->end())
00150             {
00151                 if(newState  == inRange)
00152                 {
00153                    // transition from inactive to active
00154 
00155                    childStatementActivationMap_.clear(); // all my kid's go back to never executed
00156                    
00157                 }
00158 
00159                 (*am)[this] = newState;
00160             }
00161             else
00162             {
00163                 if(newState == inRange && loc->second != inRange)
00164                 {
00165                    childStatementActivationMap_.clear(); // all my kid's go back to never executed
00166                 }
00167 
00168                 loc->second = newState;
00169             }
00170 
00171         }
00173        void ScriptRuntimeContext::print(bool firstLineOnly)
00174        {
00175           char const *start = patternBuffer()->data();
00176           char const *end   = start + patternBuffer()->size();
00177 
00178           for(;;)
00179           {
00180               char const *scan;
00181 
00182               // find the end of the next line to be sent to the output 
00183               // stream.
00184 
00185               for(scan = start; scan != end; ++scan)
00186                  if(*scan == '\n')
00187                     break;
00188 
00189               if(scan == end)
00190               {
00191                   // hit the end of pattern buffer with no newlines.
00192                   // send this line and quit
00193 
00194                   output_->push_back( std::string(start, scan) );
00195                   break;
00196               }
00197               else
00198               {
00199                   // send this line to the output and set up for
00200                   // the next line's processing
00201 
00202                   output_->push_back( std::string(start, scan) );
00203                   start = scan+1;
00204 
00205                   if(firstLineOnly)
00206                   {
00207                      break;  // stop after the first ilne
00208                   }
00209 
00210               }
00211 
00212           }
00213 
00214 
00215        }
00217 
00218     bool SubstStatement::execute(ScriptRuntimeContext *context)
00219     {
00220        
00221        if(!active(context, this))
00222           return false;
00223 
00224        
00225        std::string *pattern = context->patternBuffer();
00226 
00227        std::string rv;
00228 
00229        if(target_(*pattern))
00230        {
00231           std::string rv;
00232 
00233           int replaced;
00234           
00235           if(count_)
00236           {  
00237               replaced = target_.replace(rv, *pattern, replacement_, count_);
00238           }
00239           else
00240           {
00241               // a count_ of 0 means replace all
00242 
00243               replaced = target_.replace(rv, *pattern, replacement_);
00244           }
00245 
00246 
00247           if(replaced)
00248           {
00249             // a substitution actually occurred.
00250 
00251             *pattern = rv;
00252           }
00253 
00254        }
00255 
00256 
00257        return false; 
00258     }
00260 
00261     bool TranslateStatement::execute(ScriptRuntimeContext *context)
00262     {
00263        
00264        if(!active(context, this))
00265           return false;
00266 
00267        std::string *pattern = context->patternBuffer();
00268 
00269        *pattern = translator_.translate(*pattern);
00270 
00271        return false; 
00272     }
00274 
00275     bool BlockStatement::execute(ScriptRuntimeContext *context)
00276     {
00277        if(!active(context, this))
00278           return false;
00279 
00280        int maxCount = context->maxWhileIterations();
00281 
00282        if(whileCondition_.get())
00283        {
00284            SimpleRegex const &condition(*whileCondition_);
00285 
00286            for(;;)
00287            {
00288                --maxCount;
00289 
00290                if(maxCount == 0)
00291                   return true; // something is way wrong if we get to 1M iterations
00292 
00293                if(!condition(*context->patternBuffer()) )
00294                   break;
00295 
00296                CXXTLS_FOREACH(Statement *s, childStatements_)
00297                {
00298                   if(s->execute(context))
00299                      return true;
00300                }
00301            }
00302        }
00303        else
00304        {
00305            CXXTLS_FOREACH(Statement *s, childStatements_)
00306            {
00307               if(s->execute(context))
00308                  return true;
00309            }
00310        }
00311 
00312        return false; 
00313     }
00315 
00316     bool FilterableStatement::active(ScriptRuntimeContext *context, Statement *statement)
00317     {
00318 
00319         if(filters_)
00320         {
00321             // if this line has filters, evaluate them to determine if the current statement is active
00322             // in the current context.
00323 
00324 
00325             if(filters_ == 1)
00326             {
00327 
00328                 // if the statement has only one filter, execute the filter to determine if this
00329                 // statement main body should be executed.
00330 
00331     
00332                 bool f1Passed = 
00333                         filter1_.passes(context->lineNumber_,
00334                                                 context->isLast_,
00335                                                 *context->patternBuffer()
00336                                                 );
00337     
00338                 if(inverted_)
00339                    return !f1Passed;
00340                 else
00341                    return f1Passed;
00342             }
00343             else
00344             {
00345                // there must be 2 filters -- which means that this is line range filter.
00346 
00347                LineRangeActivationState currentState = activationState();
00348 
00349                switch(currentState)
00350                {
00351                    case neverExecuted:
00352                    {
00353                       if(!inverted_)
00354                       {
00355                          // this is the normal logic case -- we are in range only between lines
00356                          // matching the first and second filters.
00357 
00358                          bool passed;
00359 
00360                          passed = 
00361                                filter1_.passes(context->lineNumber_,
00362                                                context->isLast_,
00363                                                *context->patternBuffer()
00364                                               );
00365 
00366                          if(passed)
00367                          {
00368                              // this line puts us in range, but maybe only temporarily
00369 
00370                              passed = 
00371                                filter2_.passes(context->lineNumber_,
00372                                                context->isLast_,
00373                                                *context->patternBuffer()
00374                                               );
00375 
00376                             if(!passed)
00377                             {
00378                                // we are in range and not at the end of the range
00379 
00380                                setActivationState(inRange);
00381                                return true;
00382 
00383                             }
00384                             else
00385                             {
00386                                return true;  // in range but at end thereof, so don't set the state
00387                                              // but do return true for this one line
00388                             }
00389 
00390                          }
00391                          else
00392                          {
00393                             return false;  // not previously in range and this line does not
00394                                            // put us in range.
00395                          }
00396 
00397                       }
00398                       else
00399                       {
00400                          // we are in the inverted case.
00401 
00402                          bool passed;
00403 
00404                          passed = 
00405                                filter1_.passes(context->lineNumber_,
00406                                                context->isLast_,
00407                                                *context->patternBuffer()
00408                                               );
00409 
00410                          if(passed)
00411                          {
00412                             // imaginee are on the first line of the file, we are not yet inRange,
00413                             //
00414                             // the first line matches the first filter, so we are going to the out of range
00415                             // case unless the first line also matches the second filter.
00416                             //
00417 
00418                              passed = 
00419                                filter2_.passes(context->lineNumber_,
00420                                                context->isLast_,
00421                                                *context->patternBuffer()
00422                                               );
00423 
00424                              if(passed)
00425                              {
00426                                 // in the inverted case, the match with the first filter turned us to the 
00427                                 // !inrange sitaution,
00428                                 // but the second filter match turned it back to inrange.
00429 
00430                                 setActivationState(inRange);
00431                                 return true;
00432                              }
00433                              else
00434                              {
00435                                 setActivationState(neverExecuted);
00436                                 return false;
00437                              }
00438                          }
00439                          else
00440                          {
00441                             // we start in the never executed case, and the first filter does not match,
00442                             // so we are going to the inRange case
00443 
00444                             setActivationState(inRange);
00445                             return true;
00446                          }
00447                       }
00448                    }
00449 
00450 
00451                    case inRange:
00452                    {
00453                       if(!inverted_)
00454                       {
00455                           // normal case, we are in range and only need to know if the range
00456                           // ends on this line
00457 
00458                           bool passed;
00459 
00460                            passed = 
00461                                filter2_.passes(context->lineNumber_,
00462                                                context->isLast_,
00463                                                *context->patternBuffer()
00464                                               );
00465 
00466                            if(!passed)
00467                            {
00468                               return true;  // we are still in range
00469                            }
00470                            else
00471                            {
00472                               // this is the last line of the range, this line is
00473                               // executable no more are
00474 
00475                               setActivationState(neverExecuted);
00476                               return true;
00477                            }
00478 
00479                       }
00480                       else
00481                       {
00482                          // inverted filter situation
00483 
00484                           bool passed;
00485 
00486                            passed = 
00487                                filter1_.passes(context->lineNumber_,
00488                                                context->isLast_,
00489                                                *context->patternBuffer()
00490                                               );
00491 
00492                            if(passed)
00493                            {
00494                               // we have encountered the end of the range because
00495                               // the first filter matches the line
00496 
00497                               setActivationState(neverExecuted);
00498                               return true;
00499 
00500 
00501                            }
00502                            else
00503                              return true; // not changing state, but we are still in range
00504 
00505                       }
00506                    }
00507 
00508 
00509 
00510                    default:
00511 
00512                      debugPrint(this);
00513 
00514                      throw int(9);  // we should never get here
00515 
00516                      return false;
00517                }
00518 
00519             }
00520 
00521 
00522             throw float(10);  // we should never get here
00523             return false;
00524         }
00525 
00526         if(inverted_)
00527           return false;
00528 
00529         return true;  // either there are no filters or they both pass.
00530     }
00531 
00533         bool OuterStatement::execute(ScriptRuntimeContext *context)
00534         {
00535             CXXTLS_FOREACH(Statement *s, childStatements_)
00536             {
00537                if(s->execute(context))
00538                   return true;
00539             }
00540      
00541             return false; 
00542         }
00543 
00545         std::string FilterableStatement::debugStringPrefix() const
00546         {
00547            if(filters_ == 0)
00548            {
00549               return debugPrefix();
00550            }
00551            
00552            std::string rv = debugPrefix() + filter1_.debugString();
00553 
00554            if(filters_ > 1)
00555            {
00556              rv += ",";
00557              rv += filter2_.debugString();
00558            }
00559 
00560            if(inverted_)
00561            {
00562                rv += "!";
00563            }
00564 
00565            return rv;
00566 
00567         }
00569 
00570          std::string BlockStatement::debugString() const
00571          {
00572              std::string rv = debugStringPrefix();
00573 
00574              rv += "{";
00575 
00576              CXXTLS_FOREACH(Statement *cur, childStatements_)
00577              {
00578                 rv += cur->debugString();
00579                 rv += ";";
00580              }
00581 
00582              rv += "}";
00583 
00584              return rv;
00585          }
00586 
00588 
00589          std::string SubstStatement::debugString() const
00590          {
00591              std::string rv = debugStringPrefix();
00592 
00593              rv += "s/";
00594              rv += target_;
00595              rv += "/";
00596              rv += replacement_;
00597 
00598              char buffer[40];
00599 
00600              snprintf(buffer, sizeof(buffer), "%d", count_);
00601 
00602              rv += buffer;
00603 
00604              return rv;
00605          }
00606 
00608 
00609          std::string TranslateStatement::debugString() const
00610          {
00611              std::string rv = debugStringPrefix();
00612 
00613              rv += "y/";
00614              rv += target_;
00615              rv += "/";
00616              rv += replacement_;
00617 
00618              return rv;
00619          }
00621 
00622          std::string PrintStatement::debugString() const
00623          {
00624              std::string rv = debugStringPrefix();
00625 
00626              rv += "p";
00627 
00628              return rv;
00629          }
00630 
00632          std::string SwapStatement::debugString() const
00633          {
00634              std::string rv = debugStringPrefix();
00635 
00636              rv += "x";
00637 
00638              return rv;
00639          }
00640 
00641 
00643          std::string DeleteStatement::debugString() const
00644          {
00645              std::string rv = debugStringPrefix();
00646 
00647              rv += "d";
00648 
00649              return rv;
00650          }
00652          std::string QuitStatement::debugString() const
00653          {
00654              std::string rv = debugStringPrefix();
00655 
00656              if(printCurrent_)
00657                  rv += "q";
00658              else
00659                  rv += "Q";
00660 
00661              return rv;
00662          }
00663 
00665          std::string HoldStatement::debugString() const
00666          {
00667              std::string rv = debugStringPrefix();
00668 
00669              if(append_)
00670                  rv += "H";
00671              else
00672                  rv += "h";
00673 
00674              return rv;
00675          }
00676 
00678          std::string GetStatement::debugString() const
00679          {
00680              std::string rv = debugStringPrefix();
00681 
00682              if(append_)
00683                  rv += "G";
00684              else
00685                  rv += "g";
00686 
00687              return rv;
00688          }
00689 
00691 
00692     bool PrintStatement::execute(ScriptRuntimeContext *context)
00693     {
00694        if(!active(context, this))
00695           return false;
00696 
00697        context->print(firstLineOnly_);  
00698 
00699 
00700        return false; 
00701     }
00702 
00704 
00705     bool HoldStatement::execute(ScriptRuntimeContext *context)
00706     {
00707        if(!active(context, this))
00708           return false;
00709 
00710 
00711        if(append_)
00712            context->Hold();  
00713        else
00714            context->hold();  
00715 
00716 
00717        return false; 
00718     }
00719 
00721 
00722     bool SwapStatement::execute(ScriptRuntimeContext *context)
00723     {
00724        if(!active(context, this))
00725           return false;
00726 
00727        context->bufferSwap();
00728 
00729        return false; 
00730     }
00731 
00732 
00734 
00735     bool GetStatement::execute(ScriptRuntimeContext *context)
00736     {
00737        if(!active(context, this))
00738           return false;
00739 
00740        if(append_)
00741            context->Get();  
00742        else
00743            context->get();  
00744 
00745 
00746        return false; 
00747     }
00748 
00750     bool DeleteStatement::execute(ScriptRuntimeContext *context)
00751     {
00752        if(!active(context, this))
00753           return false;
00754 
00755        return true; 
00756     }
00757 
00758 
00760     bool QuitStatement::execute(ScriptRuntimeContext *context)
00761     {
00762        if(!active(context, this))
00763           return false;
00764 
00765        if(printCurrent_)
00766           context->print(false);
00767 
00768        context->stop(); // not just this line but the whole script
00769 
00770        return true; 
00771     }
00772 
00773 
00776 
00777 }; // namespace muSED
00778 }; // namespace cxxtls
00779 
Generated on Wed Feb 29 22:50:05 2012 for CXXUtilities by  doxygen 1.6.3