bincimap

Log | Files | Refs | LICENSE

recursivedescent.cc (29357B)


      1 /* -*- Mode: c++; -*- */
      2 /*  --------------------------------------------------------------------
      3  *  Filename:
      4  *    recursivedescent.cc
      5  *  
      6  *  Description:
      7  *    Implementation of a recursive descent IMAP command
      8  *    parser.
      9  *
     10  *  Authors:
     11  *    Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
     12  *
     13  *  Bugs:
     14  *
     15  *  ChangeLog:
     16  *
     17  *  --------------------------------------------------------------------
     18  *  Copyright 2002-2005 Andreas Aardal Hanssen
     19  *
     20  *  This program is free software; you can redistribute it and/or modify
     21  *  it under the terms of the GNU General Public License as published by
     22  *  the Free Software Foundation; either version 2 of the License, or
     23  *  (at your option) any later version.
     24  *
     25  *  This program is distributed in the hope that it will be useful,
     26  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     27  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     28  *  GNU General Public License for more details.
     29  *
     30  *  You should have received a copy of the GNU General Public License
     31  *  along with this program; if not, write to the Free Software
     32  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
     33  *  --------------------------------------------------------------------
     34  */
     35 #ifdef HAVE_CONFIG_H
     36 #include <config.h>
     37 #endif
     38 
     39 // #define DEBUG
     40 
     41 #include "imapparser.h"
     42 #include "recursivedescent.h"
     43 #include "io.h"
     44 #include "convert.h"
     45 #include "session.h"
     46 
     47 #include <stdio.h>
     48 #include <ctype.h>
     49 #include <stack>
     50 #include <iostream>
     51 #include <iomanip>
     52 
     53 using namespace ::std;
     54 using namespace Binc;
     55 
     56 stack<int> Binc::inputBuffer;
     57 int Binc::charnr = 0;
     58 
     59 
     60 //----------------------------------------------------------------------
     61 Operator::ParseResult Binc::expectThisString(const string &s_in)
     62 {
     63   IO &com = IOFactory::getInstance().get(1);
     64   Session &session = Session::getInstance();
     65 
     66   string tmp;
     67 
     68   bool match = true;
     69   for (string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
     70 
     71     int c = com.readChar(session.timeout());
     72     if (c == -1) {
     73       session.setLastError(com.getLastError());
     74       return Operator::ERROR;
     75     } else if (c == -2)
     76       return Operator::TIMEOUT;
     77 
     78 
     79     tmp += c;
     80     
     81     if (toupper(*i) != toupper(c)) {
     82       match = false;
     83       break;
     84     }
     85   }
     86   
     87   if (!match) {
     88     com.unReadChar(tmp);
     89     return Operator::REJECT;
     90   } else
     91     return Operator::ACCEPT;
     92 }
     93 
     94 //----------------------------------------------------------------------
     95 Operator::ParseResult Binc::expectDateTime(string &s_in)
     96 {
     97   Session &session = Session::getInstance();
     98 
     99   if (expectThisString("\"") != Operator::ACCEPT)
    100     return Operator::REJECT;
    101 
    102   unsigned int digit1, digit2;
    103   if (expectSPACE() == Operator::ACCEPT) {
    104     digit1 = 0;
    105     Operator::ParseResult res;
    106     if ((res = expectDigit(digit2)) != Operator::ACCEPT) {
    107       session.setLastError("expected digit (day) after \" and a SPACE.");
    108       return res;
    109     }
    110   } else {
    111     Operator::ParseResult res;
    112     if ((res = expectDigit(digit1)) != Operator::ACCEPT) {
    113       session.setLastError("expected first digit of day");
    114       return res;
    115     }
    116     if ((res = expectDigit(digit2)) != Operator::ACCEPT) {
    117       session.setLastError("expected second digit of day");
    118       return res;
    119     }
    120   }
    121 
    122   int day = digit1 * 10 + digit2;
    123 
    124   BincStream daystr;
    125 
    126   if (day < 10)
    127     daystr << '0';
    128   daystr << day;
    129 
    130   s_in += daystr.str();
    131 
    132   Operator::ParseResult res;
    133   if ((res = expectThisString("-")) != Operator::ACCEPT) {
    134     session.setLastError("expected -");
    135     return res;
    136   }
    137 
    138   s_in += "-";
    139 
    140   /* month */
    141   if ((res = expectThisString("Jan")) == Operator::ACCEPT) s_in += "Jan";
    142   else if ((res = expectThisString("Feb")) == Operator::ACCEPT) s_in += "Feb";
    143   else if ((res = expectThisString("Mar")) == Operator::ACCEPT) s_in += "Mar";
    144   else if ((res = expectThisString("Apr")) == Operator::ACCEPT) s_in += "Apr";
    145   else if ((res = expectThisString("May")) == Operator::ACCEPT) s_in += "May";
    146   else if ((res = expectThisString("Jun")) == Operator::ACCEPT) s_in += "Jun";
    147   else if ((res = expectThisString("Jul")) == Operator::ACCEPT) s_in += "Jul";
    148   else if ((res = expectThisString("Aug")) == Operator::ACCEPT) s_in += "Aug";
    149   else if ((res = expectThisString("Sep")) == Operator::ACCEPT) s_in += "Sep";
    150   else if ((res = expectThisString("Oct")) == Operator::ACCEPT) s_in += "Oct";
    151   else if ((res = expectThisString("Nov")) == Operator::ACCEPT) s_in += "Nov";
    152   else if ((res = expectThisString("Dec")) == Operator::ACCEPT) s_in += "Dec";
    153   else {
    154     session.setLastError("expected month");
    155     return res;
    156   }
    157 
    158   if ((res = expectThisString("-")) != Operator::ACCEPT) {
    159     session.setLastError("expected -");
    160     return res;
    161   }
    162 
    163   s_in += "-";    
    164 
    165   /* year */
    166   unsigned int year, c;
    167   if ((res = expectDigit(year)) != Operator::ACCEPT) {
    168     session.setLastError("expected digit (first digit of year)");
    169     return res;
    170   }
    171 
    172   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    173     session.setLastError("expected digit (second digit of year)");
    174     return res;
    175   }
    176 
    177   year = (year * 10) + c;
    178 
    179   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    180     session.setLastError("expected digit (third digit of year)");
    181     return res;
    182   }
    183 
    184   year = (year * 10) + c;
    185 
    186   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    187     session.setLastError("expected digit (last digit of year)");
    188     return res;
    189   }
    190 
    191   year = (year * 10) + c;
    192 
    193   BincStream yearstr;
    194     
    195   yearstr << year;
    196 
    197   s_in += yearstr.str();
    198 
    199   if ((res = expectSPACE()) != Operator::ACCEPT) {
    200     session.setLastError("expected SPACE");
    201     return res;
    202   }
    203 
    204   s_in += " ";
    205 
    206   if ((res = expectTime(s_in)) != Operator::ACCEPT) {
    207     session.setLastError("expected time");
    208     return res;
    209   }
    210 
    211   if ((res = expectSPACE()) != Operator::ACCEPT) {
    212     session.setLastError("expected SPACE");
    213     return res;
    214   }
    215 
    216   s_in += " ";
    217 
    218   if ((res = expectZone(s_in)) != Operator::ACCEPT) {
    219     session.setLastError("expected zone");
    220     return res;
    221   }
    222 
    223   if ((res = expectThisString("\"")) != Operator::ACCEPT) {
    224     session.setLastError("expected \"");
    225     return res;
    226   }
    227 
    228   return Operator::ACCEPT;
    229 }
    230 
    231 //----------------------------------------------------------------------
    232 Operator::ParseResult Binc::expectTime(string &s_in)
    233 {
    234   Session &session = Session::getInstance();
    235 
    236   unsigned int c, t;
    237   Operator::ParseResult res;
    238   if ((res = expectDigit(t)) != Operator::ACCEPT)
    239     return res;
    240 
    241   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    242     session.setLastError("expected digit");
    243     return res;
    244   }
    245 
    246   t = (t * 10) + c;
    247 
    248   BincStream tstr;
    249 
    250   tstr << t;
    251 
    252   s_in += tstr.str();
    253 
    254   if ((res = expectThisString(":")) != Operator::ACCEPT) {
    255     session.setLastError("expected colon");
    256     return res;
    257   }
    258 
    259   s_in += ":";
    260 
    261   if ((res = expectDigit(t)) != Operator::ACCEPT) {
    262     session.setLastError("expected digit");
    263     return res;
    264   }
    265 
    266   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    267     session.setLastError("expected digit");
    268     return res;
    269   }
    270 
    271   t = (t * 10) + c;
    272 
    273   tstr.clear();
    274 
    275   tstr << t;
    276 
    277   s_in += tstr.str();
    278 
    279   if ((res = expectThisString(":")) != Operator::ACCEPT) {
    280     session.setLastError("expected colon");
    281     return res;
    282   }
    283 
    284   s_in += ":";
    285 
    286   if ((res = expectDigit(t)) != Operator::ACCEPT) {
    287     session.setLastError("expected digit");
    288     return res;
    289   }
    290 
    291   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    292     session.setLastError("expected digit");
    293     return res;
    294   }
    295 
    296   t = (t * 10) + c;
    297 
    298   tstr.clear();
    299 
    300   tstr << t;
    301 
    302   s_in += tstr.str();
    303 
    304   return Operator::ACCEPT;
    305 }
    306 
    307 //----------------------------------------------------------------------
    308 Operator::ParseResult Binc::expectZone(string &s_in)
    309 {
    310   Session &session = Session::getInstance();
    311 
    312   Operator::ParseResult res;
    313   if ((res = expectThisString("-")) == Operator::ACCEPT)
    314     s_in += "-";
    315   else if ((res = expectThisString("+")) == Operator::ACCEPT)
    316     s_in += "+";
    317   else
    318     return res;
    319 
    320   unsigned int c, t;
    321   if ((res = expectDigit(t)) != Operator::ACCEPT) {
    322     session.setLastError("expected digit");
    323     return res;
    324   }
    325 
    326   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    327     session.setLastError("expected digit");
    328     return res;
    329   }
    330 
    331   t = (t * 10) + c;
    332 
    333   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    334     session.setLastError("expected digit");
    335     return res;
    336   }
    337 
    338   t = (t * 10) + c;
    339 
    340   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    341     session.setLastError("expected digit");
    342     return res;
    343   }
    344 
    345   t = (t * 10) + c;
    346 
    347   BincStream tstr;
    348 
    349   tstr << t;
    350 
    351   s_in += tstr.str();
    352     
    353   return Operator::ACCEPT;
    354 }
    355 
    356 //----------------------------------------------------------------------
    357 Operator::ParseResult Binc::expectListWildcards(int &c_in)
    358 {
    359   Operator::ParseResult res;
    360   if ((res = expectThisString("%")) == Operator::ACCEPT) {
    361     c_in = '%';
    362     return Operator::ACCEPT;
    363   } else if ((res = expectThisString("*")) == Operator::ACCEPT) {
    364     c_in = '*';
    365     return Operator::ACCEPT;
    366   } else
    367     return res;
    368 }
    369 
    370 //----------------------------------------------------------------------
    371 Operator::ParseResult Binc::expectListMailbox(string &s_in)
    372 {
    373   IO &com = IOFactory::getInstance().get(1);
    374 
    375   Operator::ParseResult res;
    376   if ((res = expectString(s_in)) == Operator::ACCEPT)
    377     return Operator::ACCEPT;
    378     
    379   int c;
    380   if ((res = expectAtomChar(c)) == Operator::ACCEPT
    381       || (res = expectListWildcards(c)) == Operator::ACCEPT
    382       || (res = expectThisString("]")) == Operator::ACCEPT) {
    383     do {
    384       s_in += (char) c;
    385       if ((res = expectAtomChar(c)) != Operator::ACCEPT
    386 	  && (res = expectListWildcards(c)) != Operator::ACCEPT
    387 	  && (res = expectThisString("]")) != Operator::ACCEPT)
    388 	return Operator::ACCEPT;
    389     } while (1);
    390   }
    391 
    392   com.unReadChar(s_in);
    393   
    394   return res;
    395 }
    396 
    397 //----------------------------------------------------------------------
    398 Operator::ParseResult Binc::expectFlag(vector<string> &v_in)
    399 {
    400   Session &session = Session::getInstance();
    401 
    402   Operator::ParseResult res;
    403   string flag;
    404   if ((res = expectThisString("\\Answered")) == Operator::ACCEPT)
    405     v_in.push_back("\\Answered");
    406   else if ((res = expectThisString("\\Flagged")) == Operator::ACCEPT)
    407     v_in.push_back("\\Flagged");
    408   else if ((res = expectThisString("\\Deleted")) == Operator::ACCEPT) 
    409     v_in.push_back("\\Deleted");
    410   else if ((res = expectThisString("\\Seen")) == Operator::ACCEPT) 
    411     v_in.push_back("\\Seen");
    412   else if ((res = expectThisString("\\Draft")) == Operator::ACCEPT)
    413     v_in.push_back("\\Draft");
    414   else if ((res = expectThisString("\\Answered")) == Operator::ACCEPT)
    415     v_in.push_back("\\Answered");
    416   else {
    417     if ((res = expectThisString("\\")) == Operator::ACCEPT) {
    418       if ((res = expectAtom(flag)) == Operator::ACCEPT)
    419 	v_in.push_back("\\" + flag);
    420       else {
    421 	session.setLastError("expected atom");
    422 	return res;
    423       }
    424 
    425     } else if (expectAtom(flag) == Operator::ACCEPT) {
    426       v_in.push_back(flag);
    427     } else
    428       return res;
    429   }
    430 
    431   return Operator::ACCEPT;
    432 }
    433 
    434 //----------------------------------------------------------------------
    435 Operator::ParseResult Binc::expectDate(string &s_in)
    436 {
    437   Session &session = Session::getInstance();
    438 
    439   Operator::ParseResult res;
    440   bool quoted = false;
    441   if ((res = expectThisString("\"")) == Operator::ACCEPT)
    442     quoted = true;
    443 
    444   /* day */
    445   unsigned int day, c;
    446   if ((res = expectDigit(c)) == Operator::ACCEPT) {
    447     day = c;
    448     if ((res = expectDigit(c)) == Operator::ACCEPT)
    449       day = (day * 10) + c;
    450 
    451     BincStream daystr;
    452 
    453     daystr << day;
    454 
    455     s_in += daystr.str();
    456   } else {
    457     session.setLastError("expected digit");
    458     return res;
    459   }
    460 
    461   /* - */
    462   if ((res = expectThisString("-")) != Operator::ACCEPT) {
    463     session.setLastError("expected -");
    464     return res;
    465   }
    466 
    467   s_in += '-';
    468 
    469   /* month */
    470   if ((res = expectThisString("Jan")) == Operator::ACCEPT) s_in += "Jan";
    471   else if ((res = expectThisString("Feb")) == Operator::ACCEPT) s_in += "Feb";
    472   else if ((res = expectThisString("Mar")) == Operator::ACCEPT) s_in += "Mar";
    473   else if ((res = expectThisString("Apr")) == Operator::ACCEPT) s_in += "Apr";
    474   else if ((res = expectThisString("May")) == Operator::ACCEPT) s_in += "May";
    475   else if ((res = expectThisString("Jun")) == Operator::ACCEPT) s_in += "Jun";
    476   else if ((res = expectThisString("Jul")) == Operator::ACCEPT) s_in += "Jul";
    477   else if ((res = expectThisString("Aug")) == Operator::ACCEPT) s_in += "Aug";
    478   else if ((res = expectThisString("Sep")) == Operator::ACCEPT) s_in += "Sep";
    479   else if ((res = expectThisString("Oct")) == Operator::ACCEPT) s_in += "Oct";
    480   else if ((res = expectThisString("Nov")) == Operator::ACCEPT) s_in += "Nov";
    481   else if ((res = expectThisString("Dec")) == Operator::ACCEPT) s_in += "Dec";
    482   else {
    483     session.setLastError("expected month");
    484     return res;
    485   }
    486       
    487   /* - */
    488   if ((res = expectThisString("-")) != Operator::ACCEPT) {
    489     session.setLastError("expected -");
    490     return res;
    491   }
    492 
    493   s_in += '-';
    494 
    495   /* year */
    496   unsigned int year;
    497   if ((res = expectDigit(year)) != Operator::ACCEPT) {
    498     session.setLastError("expected digit");
    499     return res;
    500   }
    501 
    502   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    503     session.setLastError("expected digit");
    504     return res;
    505   }
    506 
    507   year = (year * 10) + c;
    508 
    509   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    510     session.setLastError("expected digit");
    511     return res;
    512   }
    513 
    514   year = (year * 10) + c;
    515 
    516   if ((res = expectDigit(c)) != Operator::ACCEPT) {
    517     session.setLastError("expected digit");
    518     return res;
    519   }
    520 
    521   year = (year * 10) + c;
    522 
    523   BincStream yearstr;
    524 
    525   yearstr << year;
    526 
    527   s_in += yearstr.str();
    528 
    529   if (quoted)
    530     if ((res = expectThisString("\"")) != Operator::ACCEPT) {
    531       session.setLastError("expected \"");
    532       return res;
    533     }
    534     
    535   return Operator::ACCEPT;
    536 }
    537 
    538 //----------------------------------------------------------------------
    539 Operator::ParseResult Binc::expectCRLF(void)
    540 {
    541   Operator::ParseResult res;
    542   if ((res = expectCR()) == Operator::ACCEPT
    543       && (res = expectLF()) == Operator::ACCEPT)
    544     return Operator::ACCEPT;
    545   else
    546     return res;
    547 }
    548 
    549 //----------------------------------------------------------------------
    550 Operator::ParseResult Binc::expectCR(void)
    551 {
    552   IO &com = IOFactory::getInstance().get(1);
    553   Session &session = Session::getInstance();
    554 
    555   int c = com.readChar(session.timeout());
    556   if (c == -1) {
    557     session.setLastError(com.getLastError());
    558     return Operator::ERROR;
    559   } else if (c == -2)
    560     return Operator::TIMEOUT;
    561 
    562   if (c == 0x0d)
    563     return Operator::ACCEPT;
    564   else {
    565     com.unReadChar(c);
    566     return Operator::REJECT;
    567   }
    568 }
    569 
    570 //----------------------------------------------------------------------
    571 Operator::ParseResult Binc::expectLF(void)
    572 {
    573   IO &com = IOFactory::getInstance().get(1);
    574   Session &session = Session::getInstance();
    575 
    576   int c = com.readChar(session.timeout());
    577   if (c == -1) {
    578     session.setLastError(com.getLastError());
    579     return Operator::ERROR;
    580   } else if (c == -2)
    581       return Operator::TIMEOUT;
    582 
    583   if (c == 0x0a)
    584     return Operator::ACCEPT;
    585   else {
    586     com.unReadChar(c);
    587     return Operator::REJECT;
    588   }
    589 }
    590 
    591 //----------------------------------------------------------------------
    592 Operator::ParseResult Binc::expectTagChar(int &c_in)
    593 {
    594   IO &com = IOFactory::getInstance().get(1);
    595   Session &session = Session::getInstance();
    596  
    597   int c = com.readChar(session.timeout());
    598   if (c == -1) {
    599     session.setLastError(com.getLastError());
    600     return Operator::ERROR;
    601   } else if (c == -2)
    602     return Operator::TIMEOUT;
    603 
    604   switch (c) {
    605   case 041:    case 043:    case 044:    case 046:    case 047:    case 054:
    606   case 055:    case 056:    case 057:    case 060:    case 061:    case 062:
    607   case 063:    case 064:    case 065:    case 066:    case 067:    case 070:
    608   case 071:    case 072:    case 073:    case 074:    case 075:    case 076:
    609   case 077:    case 0100:   case 0101:   case 0102:   case 0103:   case 0104:
    610   case 0105:   case 0106:   case 0107:   case 0110:   case 0111:   case 0112:
    611   case 0113:   case 0114:   case 0115:   case 0116:   case 0117:   case 0120:
    612   case 0121:   case 0122:   case 0123:   case 0124:   case 0125:   case 0126:
    613   case 0127:   case 0130:   case 0131:   case 0132:   case 0133:   case 0135:
    614   case 0136:   case 0137:   case 0140:   case 0141:   case 0142:   case 0143:
    615   case 0144:   case 0145:   case 0146:   case 0147:   case 0150:   case 0151:
    616   case 0152:   case 0153:   case 0154:   case 0155:   case 0156:   case 0157:
    617   case 0160:   case 0161:   case 0162:   case 0163:   case 0164:   case 0165:
    618   case 0166:   case 0167:   case 0170:   case 0171:   case 0172:   case 0174:
    619   case 0175:   case 0176:
    620     c_in = c;
    621     return Operator::ACCEPT;
    622   default:
    623     break;
    624   }
    625   
    626   com.unReadChar(c);
    627 
    628   return Operator::REJECT;
    629 }
    630 
    631 //----------------------------------------------------------------------
    632 Operator::ParseResult Binc::expectTag(string &s_in)
    633 {
    634   string tag;
    635   int tagchar;
    636 
    637   int eres = expectTagChar(tagchar);
    638   if (eres == Operator::REJECT)
    639     return Operator::REJECT;
    640   else if (eres == Operator::ERROR)
    641     return Operator::ERROR;
    642   else if (eres == Operator::TIMEOUT)
    643     return Operator::TIMEOUT;
    644   else {
    645     tag += tagchar;
    646 
    647     bool done = false;
    648 
    649     while (!done) {
    650       switch (expectTagChar(tagchar)) {
    651       case Operator::ACCEPT:
    652 	tag += tagchar;
    653 	break;
    654       case Operator::REJECT:
    655 	done = true;
    656 	break;
    657       case Operator::ERROR:
    658 	return Operator::ERROR;
    659       case Operator::TIMEOUT:
    660 	return Operator::TIMEOUT;
    661       }
    662     }
    663   }
    664 
    665   s_in = tag;
    666 
    667   return Operator::ACCEPT;
    668 }
    669 
    670 //----------------------------------------------------------------------
    671 Operator::ParseResult Binc::expectSPACE(void)
    672 {
    673   IO &com = IOFactory::getInstance().get(1);
    674   Session &session = Session::getInstance();
    675 
    676   int c = com.readChar(session.timeout());
    677   if (c == -1) {
    678     session.setLastError(com.getLastError());
    679     return Operator::ERROR;
    680   } else if (c == -2)
    681     return Operator::TIMEOUT;
    682 
    683   if (c == ' ')
    684     return Operator::ACCEPT;
    685   else {
    686     com.unReadChar(c);
    687     return Operator::REJECT;
    688   }
    689 }
    690 
    691 //----------------------------------------------------------------------
    692 Operator::ParseResult Binc::expectMailbox(string &s_in)
    693 {
    694   return expectAstring(s_in);
    695 }
    696 
    697 //----------------------------------------------------------------------
    698 Operator::ParseResult Binc::expectAstring(string &s_in)
    699 {
    700   Operator::ParseResult res;
    701   if ((res = expectAtom(s_in)) == Operator::ACCEPT)
    702     return Operator::ACCEPT;
    703   
    704   if ((res = expectString(s_in)) == Operator::ACCEPT)
    705     return Operator::ACCEPT;
    706   
    707   return res;
    708 }
    709 
    710 //----------------------------------------------------------------------
    711 Operator::ParseResult Binc::expectAtomChar(int &c_in)
    712 {
    713   IO &com = IOFactory::getInstance().get(1);
    714   Session &session = Session::getInstance();
    715 
    716   int c = com.readChar(session.timeout());
    717   if (c == -1) {
    718     session.setLastError(com.getLastError());
    719     return Operator::ERROR;
    720   } else if (c == -2)
    721     return Operator::TIMEOUT;
    722 
    723   switch (c) {
    724   case 041:    case 043:    case 044:    case 046:    case 047:    case 053:
    725   case 054:    case 055:    case 056:    case 057:    case 060:    case 061:
    726   case 062:    case 063:    case 064:    case 065:    case 066:    case 067:
    727   case 070:    case 071:    case 072:    case 073:    case 074:    case 075:
    728   case 076:    case 077:    case 0100:   case 0101:   case 0102:   case 0103:
    729   case 0104:   case 0105:   case 0106:   case 0107:   case 0110:   case 0111:
    730   case 0112:   case 0113:   case 0114:   case 0115:   case 0116:   case 0117:
    731   case 0120:   case 0121:   case 0122:   case 0123:   case 0124:   case 0125:
    732   case 0126:   case 0127:   case 0130:   case 0131:   case 0132:   case 0133:
    733   case 0135:   case 0136:   case 0137:   case 0140:   case 0141:   case 0142:
    734   case 0143:   case 0144:   case 0145:   case 0146:   case 0147:   case 0150:
    735   case 0151:   case 0152:   case 0153:   case 0154:   case 0155:   case 0156:
    736   case 0157:   case 0160:   case 0161:   case 0162:   case 0163:   case 0164:
    737   case 0165:   case 0166:   case 0167:   case 0170:   case 0171:   case 0172:
    738   case 0174:   case 0175:   case 0176:
    739     c_in = c;
    740     return Operator::ACCEPT;
    741   default:
    742     break;
    743   }
    744   
    745   com.unReadChar(c);
    746   return Operator::REJECT;
    747 }
    748 
    749 //----------------------------------------------------------------------
    750 Operator::ParseResult Binc::expectAtom(string &s_in)
    751 {
    752   IO &com = IOFactory::getInstance().get(1);
    753 
    754   string atom;
    755   int atomchar;
    756 
    757   Operator::ParseResult res;
    758   while ((res = expectAtomChar(atomchar)) == Operator::ACCEPT)
    759     atom += atomchar;
    760 
    761   if (atom == "") {
    762     com.unReadChar(atom);
    763     return res;
    764   } else
    765     s_in = atom;
    766 
    767   return Operator::ACCEPT;
    768 }
    769 
    770 //----------------------------------------------------------------------
    771 Operator::ParseResult Binc::expectString(string &s_in)
    772 {
    773   Operator::ParseResult res;
    774   if ((res = expectQuoted(s_in)) == Operator::ACCEPT)
    775     return Operator::ACCEPT;
    776 
    777   if ((res = expectLiteral(s_in)) == Operator::ACCEPT)
    778     return Operator::ACCEPT;
    779 
    780   return res;
    781 }
    782 
    783 //----------------------------------------------------------------------
    784 Operator::ParseResult Binc::expectQuoted(string &s_in)
    785 {
    786   IO &com = IOFactory::getInstance().get(1);
    787 
    788   string quoted;
    789   int quotedchar;
    790   Operator::ParseResult res;
    791 
    792   if ((res = expectThisString("\"")) != Operator::ACCEPT)
    793     return res;
    794     
    795   while ((res = expectQuotedChar(quotedchar)) == Operator::ACCEPT)
    796     quoted += quotedchar;
    797     
    798   if ((res = expectThisString("\"")) != Operator::ACCEPT) {
    799     com.unReadChar("\"" + quoted);
    800     return res;
    801   }
    802 
    803   s_in = quoted;
    804   return Operator::ACCEPT;
    805 }
    806 
    807 //----------------------------------------------------------------------
    808 Operator::ParseResult Binc::expectQuotedChar(int &c_in)
    809 {
    810   IO &com = IOFactory::getInstance().get(1);
    811   Session &session = Session::getInstance();
    812 
    813   int c = com.readChar(session.timeout());
    814   if (c == -1) {
    815     session.setLastError(com.getLastError());
    816     return Operator::ERROR;
    817   } else if (c == -2)
    818     return Operator::TIMEOUT;
    819 
    820   switch (c) {
    821   case 01:    case 02:    case 03:    case 04:    case 05:    case 06:    case 07:
    822   case 010:   case 011:   case 013:   case 014:   case 016:   case 017:
    823   case 020:   case 021:   case 022:   case 023:   case 024:   case 025:   case 026:   case 027:
    824   case 030:   case 031:   case 032:   case 033:   case 034:   case 035:   case 036:   case 037:
    825   case 040:   case 041:   case 043:   case 044:   case 045:   case 046:   case 047:
    826   case 050:   case 051:   case 052:   case 053:   case 054:   case 055:   case 056:   case 057:
    827   case 060:   case 061:   case 062:   case 063:   case 064:   case 065:   case 066:   case 067:
    828   case 070:   case 071:   case 072:   case 073:   case 074:   case 075:   case 076:   case 077:
    829   case 0100:  case 0101:  case 0102:  case 0103:  case 0104:  case 0105:  case 0106:  case 0107:
    830   case 0110:  case 0111:  case 0112:  case 0113:  case 0114:  case 0115:  case 0116:  case 0117:
    831   case 0120:  case 0121:  case 0122:  case 0123:  case 0124:  case 0125:  case 0126:  case 0127:
    832   case 0130:  case 0131:  case 0132:  case 0133:  case 0135:  case 0136:  case 0137:
    833   case 0140:  case 0141:  case 0142:  case 0143:  case 0144:  case 0145:  case 0146:  case 0147:
    834   case 0150:  case 0151:  case 0152:  case 0153:  case 0154:  case 0155:  case 0156:  case 0157:
    835   case 0160:  case 0161:  case 0162:  case 0163:  case 0164:  case 0165:  case 0166:  case 0167:
    836   case 0170:  case 0171:  case 0172:  case 0173:  case 0174:  case 0175:  case 0176:  case 0177:
    837     c_in = c;
    838     return Operator::ACCEPT;
    839   case '\\': {
    840     int d = com.readChar(session.timeout());
    841     if (d == -1) {
    842       session.setLastError(com.getLastError());
    843       return Operator::ERROR;
    844     } else if (d == -2)
    845       return Operator::TIMEOUT;
    846 
    847     if (d == '\"' || d == '\\') {
    848       c_in = d;
    849       return Operator::ACCEPT;
    850     } else {
    851       com.unReadChar(d);
    852       com.unReadChar(c);
    853       return Operator::REJECT;
    854     }
    855   }
    856   default:
    857     break;
    858   }
    859   
    860   com.unReadChar(c);
    861   return Operator::REJECT;
    862 }
    863 
    864 //----------------------------------------------------------------------
    865 Operator::ParseResult Binc::expectLiteral(string &s_in)
    866 {
    867   IO &com = IOFactory::getInstance().get(1);
    868   Session &session = Session::getInstance();
    869 
    870   string literal;
    871   Operator::ParseResult res;
    872 
    873   if ((res = expectThisString("{")) != Operator::ACCEPT)
    874     return res;
    875 
    876   unsigned int nchar;
    877 
    878   if ((res = expectNumber(nchar)) != Operator::ACCEPT) {
    879     session.setLastError("expected number");
    880     return res;
    881   }
    882 
    883   if ((res = expectThisString("}")) != Operator::ACCEPT) {
    884     session.setLastError("expected }");
    885     return res;
    886   }
    887 
    888   if ((res = expectCRLF()) != Operator::ACCEPT) {
    889     session.setLastError("expected CRLF");
    890     return Operator::ERROR;
    891   }
    892 
    893   com << "+ ok, send " << nchar << " bytes of data." << endl;
    894   com.flushContent();
    895 
    896   for (unsigned int i = 0; i < nchar; ++i) {
    897     int c = com.readChar(session.timeout());
    898     if (c == -1) {
    899       session.setLastError(com.getLastError());
    900       return Operator::ERROR;
    901     } else if (c == -2)
    902       return Operator::TIMEOUT;
    903     else
    904       literal += c;
    905   }
    906 
    907   s_in = literal;
    908 
    909   return Operator::ACCEPT;
    910 }
    911 
    912 //----------------------------------------------------------------------
    913 Operator::ParseResult Binc::expectNumber(unsigned int &i_in)
    914 {
    915   i_in = 0;
    916   unsigned int n;
    917   Operator::ParseResult res;
    918 
    919   while ((res = expectDigit(n)) == Operator::ACCEPT) {
    920     if (i_in == 0)
    921       i_in = n;
    922     else
    923       i_in = (i_in * 10) + n;
    924   }
    925 
    926   if (res == Operator::TIMEOUT)
    927     return res;
    928   
    929   return Operator::ACCEPT;
    930 }
    931 
    932 //----------------------------------------------------------------------
    933 Operator::ParseResult Binc::expectDigit(unsigned int &i_in)
    934 {
    935   IO &com = IOFactory::getInstance().get(1);
    936   Session &session = Session::getInstance();
    937 
    938   int c = com.readChar(session.timeout());
    939   if (c == -1) {
    940     session.setLastError(com.getLastError());
    941     return Operator::ERROR;
    942   } else if (c == -2)
    943     return Operator::TIMEOUT;
    944 
    945   if (c == '0') {
    946     i_in = 0;
    947     return Operator::ACCEPT;
    948   } else
    949     com.unReadChar(c);
    950 
    951   if (expectDigitNZ(i_in) != Operator::ACCEPT)
    952     return Operator::REJECT;
    953 
    954   return Operator::ACCEPT;
    955 }
    956 
    957 //----------------------------------------------------------------------
    958 Operator::ParseResult Binc::expectDigitNZ(unsigned int &i_in)
    959 {
    960   IO &com = IOFactory::getInstance().get(1);
    961   Session &session = Session::getInstance();
    962 
    963   int c;
    964   switch ((c = com.readChar(session.timeout()))) {
    965   case '1': i_in = 1; break;
    966   case '2': i_in = 2; break;
    967   case '3': i_in = 3; break;
    968   case '4': i_in = 4; break;
    969   case '5': i_in = 5; break;
    970   case '6': i_in = 6; break;
    971   case '7': i_in = 7; break;
    972   case '8': i_in = 8; break;
    973   case '9': i_in = 9; break;
    974   case -1: 
    975     session.setLastError(com.getLastError());
    976     return Operator::ERROR;
    977   case -2:
    978     return Operator::TIMEOUT;
    979   default:
    980     com.unReadChar(c);
    981     return Operator::REJECT;
    982   }
    983   
    984   return Operator::ACCEPT;
    985 }
    986 
    987 //----------------------------------------------------------------------
    988 Operator::ParseResult Binc::expectSet(SequenceSet &s_in)
    989 {
    990   Session &session = Session::getInstance();
    991   unsigned int seqnum = (unsigned int) -1;
    992   
    993   Operator::ParseResult res;
    994 
    995   /* if a set does not start with a sequencenum, then it's not a
    996    * set. :-) seqnum == -1 means '*'. */
    997   if ((res = expectSequenceNum(seqnum)) != Operator::ACCEPT)
    998     return res;
    999 
   1000   /* the first number is always a part of the set */
   1001   s_in.addNumber(seqnum);
   1002 
   1003   /* if _after_ a set there is a ':', then there will always be a
   1004    * sequencenum after the colon. if not, it's a syntax error. a
   1005    * colon delimits two numbers in a range. */
   1006   if ((res = expectThisString(":")) == Operator::ACCEPT) {
   1007     unsigned int seqnum2 = (unsigned int) -1;
   1008     if ((res = expectSequenceNum(seqnum2)) != Operator::ACCEPT) {
   1009       session.setLastError("expected sequencenum");
   1010       return res;
   1011     }
   1012 
   1013     s_in.addRange(seqnum, seqnum2);
   1014   }
   1015 
   1016   /* if _after_ a set there is a ',', then there will always be
   1017    * a set after the comma. if not, it's a syntax error. */
   1018   if ((res = expectThisString(",")) == Operator::ACCEPT)
   1019     if ((res = expectSet(s_in)) != Operator::ACCEPT) {
   1020       session.setLastError("expected set");
   1021       return res;
   1022     }
   1023 
   1024   return Operator::ACCEPT;
   1025 }
   1026 
   1027 //----------------------------------------------------------------------
   1028 Operator::ParseResult Binc::expectSequenceNum(unsigned int &i_in)
   1029 {
   1030   IO &com = IOFactory::getInstance().get(1);
   1031   Session &session = Session::getInstance();
   1032 
   1033   int c = com.readChar(session.timeout());
   1034   if (c == -1) {
   1035     session.setLastError(com.getLastError());
   1036     return Operator::ERROR;
   1037   } else if (c == -2)
   1038     return Operator::TIMEOUT;
   1039 
   1040   if (c == '*') {
   1041     i_in = (unsigned int) -1;
   1042     return Operator::ACCEPT;
   1043   } else
   1044     com.unReadChar(c);
   1045 
   1046   if (expectNZNumber(i_in) != Operator::ACCEPT)
   1047     return Operator::REJECT;
   1048   else
   1049     return Operator::ACCEPT;
   1050 }
   1051 
   1052 //----------------------------------------------------------------------
   1053 Operator::ParseResult Binc::expectNZNumber(unsigned int &i_in)
   1054 {
   1055   unsigned int c;
   1056   Operator::ParseResult res;
   1057 
   1058   if ((res = expectDigitNZ(c)) != Operator::ACCEPT)
   1059     return res;
   1060     
   1061   i_in = c;
   1062   while ((res = expectDigit(c)) == Operator::ACCEPT)
   1063     i_in = (i_in * 10) + c;
   1064 
   1065   if (res == Operator::TIMEOUT)
   1066     return res;
   1067 
   1068   return Operator::ACCEPT;
   1069 }