/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* recursivedescent.cc
*
* Description:
* Implementation of a recursive descent IMAP command
* parser.
*
* Authors:
* Andreas Aardal Hanssen <andreas-binc curly bincimap spot org>
*
* Bugs:
*
* ChangeLog:
*
* --------------------------------------------------------------------
* Copyright 2002-2005 Andreas Aardal Hanssen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
// #define DEBUG
#include "imapparser.h"
#include "recursivedescent.h"
#include "io.h"
#include "convert.h"
#include "session.h"
#include <stdio.h>
#include <ctype.h>
#include <stack>
#include <iostream>
#include <iomanip>
using namespace ::std;
using namespace Binc;
stack<int> Binc::inputBuffer;
int Binc::charnr = 0;
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectThisString(const string &s_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
string tmp;
bool match = true;
for (string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
tmp += c;
if (toupper(*i) != toupper(c)) {
match = false;
break;
}
}
if (!match) {
com.unReadChar(tmp);
return Operator::REJECT;
} else
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectDateTime(string &s_in)
{
Session &session = Session::getInstance();
if (expectThisString("\"") != Operator::ACCEPT)
return Operator::REJECT;
unsigned int digit1, digit2;
if (expectSPACE() == Operator::ACCEPT) {
digit1 = 0;
Operator::ParseResult res;
if ((res = expectDigit(digit2)) != Operator::ACCEPT) {
session.setLastError("expected digit (day) after \" and a SPACE.");
return res;
}
} else {
Operator::ParseResult res;
if ((res = expectDigit(digit1)) != Operator::ACCEPT) {
session.setLastError("expected first digit of day");
return res;
}
if ((res = expectDigit(digit2)) != Operator::ACCEPT) {
session.setLastError("expected second digit of day");
return res;
}
}
int day = digit1 * 10 + digit2;
BincStream daystr;
if (day < 10)
daystr << '0';
daystr << day;
s_in += daystr.str();
Operator::ParseResult res;
if ((res = expectThisString("-")) != Operator::ACCEPT) {
session.setLastError("expected -");
return res;
}
s_in += "-";
/* month */
if ((res = expectThisString("Jan")) == Operator::ACCEPT) s_in += "Jan";
else if ((res = expectThisString("Feb")) == Operator::ACCEPT) s_in += "Feb";
else if ((res = expectThisString("Mar")) == Operator::ACCEPT) s_in += "Mar";
else if ((res = expectThisString("Apr")) == Operator::ACCEPT) s_in += "Apr";
else if ((res = expectThisString("May")) == Operator::ACCEPT) s_in += "May";
else if ((res = expectThisString("Jun")) == Operator::ACCEPT) s_in += "Jun";
else if ((res = expectThisString("Jul")) == Operator::ACCEPT) s_in += "Jul";
else if ((res = expectThisString("Aug")) == Operator::ACCEPT) s_in += "Aug";
else if ((res = expectThisString("Sep")) == Operator::ACCEPT) s_in += "Sep";
else if ((res = expectThisString("Oct")) == Operator::ACCEPT) s_in += "Oct";
else if ((res = expectThisString("Nov")) == Operator::ACCEPT) s_in += "Nov";
else if ((res = expectThisString("Dec")) == Operator::ACCEPT) s_in += "Dec";
else {
session.setLastError("expected month");
return res;
}
if ((res = expectThisString("-")) != Operator::ACCEPT) {
session.setLastError("expected -");
return res;
}
s_in += "-";
/* year */
unsigned int year, c;
if ((res = expectDigit(year)) != Operator::ACCEPT) {
session.setLastError("expected digit (first digit of year)");
return res;
}
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit (second digit of year)");
return res;
}
year = (year * 10) + c;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit (third digit of year)");
return res;
}
year = (year * 10) + c;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit (last digit of year)");
return res;
}
year = (year * 10) + c;
BincStream yearstr;
yearstr << year;
s_in += yearstr.str();
if ((res = expectSPACE()) != Operator::ACCEPT) {
session.setLastError("expected SPACE");
return res;
}
s_in += " ";
if ((res = expectTime(s_in)) != Operator::ACCEPT) {
session.setLastError("expected time");
return res;
}
if ((res = expectSPACE()) != Operator::ACCEPT) {
session.setLastError("expected SPACE");
return res;
}
s_in += " ";
if ((res = expectZone(s_in)) != Operator::ACCEPT) {
session.setLastError("expected zone");
return res;
}
if ((res = expectThisString("\"")) != Operator::ACCEPT) {
session.setLastError("expected \"");
return res;
}
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectTime(string &s_in)
{
Session &session = Session::getInstance();
unsigned int c, t;
Operator::ParseResult res;
if ((res = expectDigit(t)) != Operator::ACCEPT)
return res;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
t = (t * 10) + c;
BincStream tstr;
tstr << t;
s_in += tstr.str();
if ((res = expectThisString(":")) != Operator::ACCEPT) {
session.setLastError("expected colon");
return res;
}
s_in += ":";
if ((res = expectDigit(t)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
t = (t * 10) + c;
tstr.clear();
tstr << t;
s_in += tstr.str();
if ((res = expectThisString(":")) != Operator::ACCEPT) {
session.setLastError("expected colon");
return res;
}
s_in += ":";
if ((res = expectDigit(t)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
t = (t * 10) + c;
tstr.clear();
tstr << t;
s_in += tstr.str();
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectZone(string &s_in)
{
Session &session = Session::getInstance();
Operator::ParseResult res;
if ((res = expectThisString("-")) == Operator::ACCEPT)
s_in += "-";
else if ((res = expectThisString("+")) == Operator::ACCEPT)
s_in += "+";
else
return res;
unsigned int c, t;
if ((res = expectDigit(t)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
t = (t * 10) + c;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
t = (t * 10) + c;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
t = (t * 10) + c;
BincStream tstr;
tstr << t;
s_in += tstr.str();
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectListWildcards(int &c_in)
{
Operator::ParseResult res;
if ((res = expectThisString("%")) == Operator::ACCEPT) {
c_in = '%';
return Operator::ACCEPT;
} else if ((res = expectThisString("*")) == Operator::ACCEPT) {
c_in = '*';
return Operator::ACCEPT;
} else
return res;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectListMailbox(string &s_in)
{
IO &com = IOFactory::getInstance().get(1);
Operator::ParseResult res;
if ((res = expectString(s_in)) == Operator::ACCEPT)
return Operator::ACCEPT;
int c;
if ((res = expectAtomChar(c)) == Operator::ACCEPT
|| (res = expectListWildcards(c)) == Operator::ACCEPT
|| (res = expectThisString("]")) == Operator::ACCEPT) {
do {
s_in += (char) c;
if ((res = expectAtomChar(c)) != Operator::ACCEPT
&& (res = expectListWildcards(c)) != Operator::ACCEPT
&& (res = expectThisString("]")) != Operator::ACCEPT)
return Operator::ACCEPT;
} while (1);
}
com.unReadChar(s_in);
return res;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectFlag(vector<string> &v_in)
{
Session &session = Session::getInstance();
Operator::ParseResult res;
string flag;
if ((res = expectThisString("\\Answered")) == Operator::ACCEPT)
v_in.push_back("\\Answered");
else if ((res = expectThisString("\\Flagged")) == Operator::ACCEPT)
v_in.push_back("\\Flagged");
else if ((res = expectThisString("\\Deleted")) == Operator::ACCEPT)
v_in.push_back("\\Deleted");
else if ((res = expectThisString("\\Seen")) == Operator::ACCEPT)
v_in.push_back("\\Seen");
else if ((res = expectThisString("\\Draft")) == Operator::ACCEPT)
v_in.push_back("\\Draft");
else if ((res = expectThisString("\\Answered")) == Operator::ACCEPT)
v_in.push_back("\\Answered");
else {
if ((res = expectThisString("\\")) == Operator::ACCEPT) {
if ((res = expectAtom(flag)) == Operator::ACCEPT)
v_in.push_back("\\" + flag);
else {
session.setLastError("expected atom");
return res;
}
} else if (expectAtom(flag) == Operator::ACCEPT) {
v_in.push_back(flag);
} else
return res;
}
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectDate(string &s_in)
{
Session &session = Session::getInstance();
Operator::ParseResult res;
bool quoted = false;
if ((res = expectThisString("\"")) == Operator::ACCEPT)
quoted = true;
/* day */
unsigned int day, c;
if ((res = expectDigit(c)) == Operator::ACCEPT) {
day = c;
if ((res = expectDigit(c)) == Operator::ACCEPT)
day = (day * 10) + c;
BincStream daystr;
daystr << day;
s_in += daystr.str();
} else {
session.setLastError("expected digit");
return res;
}
/* - */
if ((res = expectThisString("-")) != Operator::ACCEPT) {
session.setLastError("expected -");
return res;
}
s_in += '-';
/* month */
if ((res = expectThisString("Jan")) == Operator::ACCEPT) s_in += "Jan";
else if ((res = expectThisString("Feb")) == Operator::ACCEPT) s_in += "Feb";
else if ((res = expectThisString("Mar")) == Operator::ACCEPT) s_in += "Mar";
else if ((res = expectThisString("Apr")) == Operator::ACCEPT) s_in += "Apr";
else if ((res = expectThisString("May")) == Operator::ACCEPT) s_in += "May";
else if ((res = expectThisString("Jun")) == Operator::ACCEPT) s_in += "Jun";
else if ((res = expectThisString("Jul")) == Operator::ACCEPT) s_in += "Jul";
else if ((res = expectThisString("Aug")) == Operator::ACCEPT) s_in += "Aug";
else if ((res = expectThisString("Sep")) == Operator::ACCEPT) s_in += "Sep";
else if ((res = expectThisString("Oct")) == Operator::ACCEPT) s_in += "Oct";
else if ((res = expectThisString("Nov")) == Operator::ACCEPT) s_in += "Nov";
else if ((res = expectThisString("Dec")) == Operator::ACCEPT) s_in += "Dec";
else {
session.setLastError("expected month");
return res;
}
/* - */
if ((res = expectThisString("-")) != Operator::ACCEPT) {
session.setLastError("expected -");
return res;
}
s_in += '-';
/* year */
unsigned int year;
if ((res = expectDigit(year)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
year = (year * 10) + c;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
year = (year * 10) + c;
if ((res = expectDigit(c)) != Operator::ACCEPT) {
session.setLastError("expected digit");
return res;
}
year = (year * 10) + c;
BincStream yearstr;
yearstr << year;
s_in += yearstr.str();
if (quoted)
if ((res = expectThisString("\"")) != Operator::ACCEPT) {
session.setLastError("expected \"");
return res;
}
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectCRLF(void)
{
Operator::ParseResult res;
if ((res = expectCR()) == Operator::ACCEPT
&& (res = expectLF()) == Operator::ACCEPT)
return Operator::ACCEPT;
else
return res;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectCR(void)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
if (c == 0x0d)
return Operator::ACCEPT;
else {
com.unReadChar(c);
return Operator::REJECT;
}
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectLF(void)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
if (c == 0x0a)
return Operator::ACCEPT;
else {
com.unReadChar(c);
return Operator::REJECT;
}
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectTagChar(int &c_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
switch (c) {
case 041: case 043: case 044: case 046: case 047: case 054:
case 055: case 056: case 057: case 060: case 061: case 062:
case 063: case 064: case 065: case 066: case 067: case 070:
case 071: case 072: case 073: case 074: case 075: case 076:
case 077: case 0100: case 0101: case 0102: case 0103: case 0104:
case 0105: case 0106: case 0107: case 0110: case 0111: case 0112:
case 0113: case 0114: case 0115: case 0116: case 0117: case 0120:
case 0121: case 0122: case 0123: case 0124: case 0125: case 0126:
case 0127: case 0130: case 0131: case 0132: case 0133: case 0135:
case 0136: case 0137: case 0140: case 0141: case 0142: case 0143:
case 0144: case 0145: case 0146: case 0147: case 0150: case 0151:
case 0152: case 0153: case 0154: case 0155: case 0156: case 0157:
case 0160: case 0161: case 0162: case 0163: case 0164: case 0165:
case 0166: case 0167: case 0170: case 0171: case 0172: case 0174:
case 0175: case 0176:
c_in = c;
return Operator::ACCEPT;
default:
break;
}
com.unReadChar(c);
return Operator::REJECT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectTag(string &s_in)
{
string tag;
int tagchar;
int eres = expectTagChar(tagchar);
if (eres == Operator::REJECT)
return Operator::REJECT;
else if (eres == Operator::ERROR)
return Operator::ERROR;
else if (eres == Operator::TIMEOUT)
return Operator::TIMEOUT;
else {
tag += tagchar;
bool done = false;
while (!done) {
switch (expectTagChar(tagchar)) {
case Operator::ACCEPT:
tag += tagchar;
break;
case Operator::REJECT:
done = true;
break;
case Operator::ERROR:
return Operator::ERROR;
case Operator::TIMEOUT:
return Operator::TIMEOUT;
}
}
}
s_in = tag;
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectSPACE(void)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
if (c == ' ')
return Operator::ACCEPT;
else {
com.unReadChar(c);
return Operator::REJECT;
}
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectMailbox(string &s_in)
{
return expectAstring(s_in);
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectAstring(string &s_in)
{
Operator::ParseResult res;
if ((res = expectAtom(s_in)) == Operator::ACCEPT)
return Operator::ACCEPT;
if ((res = expectString(s_in)) == Operator::ACCEPT)
return Operator::ACCEPT;
return res;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectAtomChar(int &c_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
switch (c) {
case 041: case 043: case 044: case 046: case 047: case 053:
case 054: case 055: case 056: case 057: case 060: case 061:
case 062: case 063: case 064: case 065: case 066: case 067:
case 070: case 071: case 072: case 073: case 074: case 075:
case 076: case 077: case 0100: case 0101: case 0102: case 0103:
case 0104: case 0105: case 0106: case 0107: case 0110: case 0111:
case 0112: case 0113: case 0114: case 0115: case 0116: case 0117:
case 0120: case 0121: case 0122: case 0123: case 0124: case 0125:
case 0126: case 0127: case 0130: case 0131: case 0132: case 0133:
case 0135: case 0136: case 0137: case 0140: case 0141: case 0142:
case 0143: case 0144: case 0145: case 0146: case 0147: case 0150:
case 0151: case 0152: case 0153: case 0154: case 0155: case 0156:
case 0157: case 0160: case 0161: case 0162: case 0163: case 0164:
case 0165: case 0166: case 0167: case 0170: case 0171: case 0172:
case 0174: case 0175: case 0176:
c_in = c;
return Operator::ACCEPT;
default:
break;
}
com.unReadChar(c);
return Operator::REJECT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectAtom(string &s_in)
{
IO &com = IOFactory::getInstance().get(1);
string atom;
int atomchar;
Operator::ParseResult res;
while ((res = expectAtomChar(atomchar)) == Operator::ACCEPT)
atom += atomchar;
if (atom == "") {
com.unReadChar(atom);
return res;
} else
s_in = atom;
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectString(string &s_in)
{
Operator::ParseResult res;
if ((res = expectQuoted(s_in)) == Operator::ACCEPT)
return Operator::ACCEPT;
if ((res = expectLiteral(s_in)) == Operator::ACCEPT)
return Operator::ACCEPT;
return res;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectQuoted(string &s_in)
{
IO &com = IOFactory::getInstance().get(1);
string quoted;
int quotedchar;
Operator::ParseResult res;
if ((res = expectThisString("\"")) != Operator::ACCEPT)
return res;
while ((res = expectQuotedChar(quotedchar)) == Operator::ACCEPT)
quoted += quotedchar;
if ((res = expectThisString("\"")) != Operator::ACCEPT) {
com.unReadChar("\"" + quoted);
return res;
}
s_in = quoted;
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectQuotedChar(int &c_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
switch (c) {
case 01: case 02: case 03: case 04: case 05: case 06: case 07:
case 010: case 011: case 013: case 014: case 016: case 017:
case 020: case 021: case 022: case 023: case 024: case 025: case 026: case 027:
case 030: case 031: case 032: case 033: case 034: case 035: case 036: case 037:
case 040: case 041: case 043: case 044: case 045: case 046: case 047:
case 050: case 051: case 052: case 053: case 054: case 055: case 056: case 057:
case 060: case 061: case 062: case 063: case 064: case 065: case 066: case 067:
case 070: case 071: case 072: case 073: case 074: case 075: case 076: case 077:
case 0100: case 0101: case 0102: case 0103: case 0104: case 0105: case 0106: case 0107:
case 0110: case 0111: case 0112: case 0113: case 0114: case 0115: case 0116: case 0117:
case 0120: case 0121: case 0122: case 0123: case 0124: case 0125: case 0126: case 0127:
case 0130: case 0131: case 0132: case 0133: case 0135: case 0136: case 0137:
case 0140: case 0141: case 0142: case 0143: case 0144: case 0145: case 0146: case 0147:
case 0150: case 0151: case 0152: case 0153: case 0154: case 0155: case 0156: case 0157:
case 0160: case 0161: case 0162: case 0163: case 0164: case 0165: case 0166: case 0167:
case 0170: case 0171: case 0172: case 0173: case 0174: case 0175: case 0176: case 0177:
c_in = c;
return Operator::ACCEPT;
case '\\': {
int d = com.readChar(session.timeout());
if (d == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (d == -2)
return Operator::TIMEOUT;
if (d == '\"' || d == '\\') {
c_in = d;
return Operator::ACCEPT;
} else {
com.unReadChar(d);
com.unReadChar(c);
return Operator::REJECT;
}
}
default:
break;
}
com.unReadChar(c);
return Operator::REJECT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectLiteral(string &s_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
string literal;
Operator::ParseResult res;
if ((res = expectThisString("{")) != Operator::ACCEPT)
return res;
unsigned int nchar;
if ((res = expectNumber(nchar)) != Operator::ACCEPT) {
session.setLastError("expected number");
return res;
}
if ((res = expectThisString("}")) != Operator::ACCEPT) {
session.setLastError("expected }");
return res;
}
if ((res = expectCRLF()) != Operator::ACCEPT) {
session.setLastError("expected CRLF");
return Operator::ERROR;
}
com << "+ ok, send " << nchar << " bytes of data." << endl;
com.flushContent();
for (unsigned int i = 0; i < nchar; ++i) {
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
else
literal += c;
}
s_in = literal;
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectNumber(unsigned int &i_in)
{
i_in = 0;
unsigned int n;
Operator::ParseResult res;
while ((res = expectDigit(n)) == Operator::ACCEPT) {
if (i_in == 0)
i_in = n;
else
i_in = (i_in * 10) + n;
}
if (res == Operator::TIMEOUT)
return res;
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectDigit(unsigned int &i_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
if (c == '0') {
i_in = 0;
return Operator::ACCEPT;
} else
com.unReadChar(c);
if (expectDigitNZ(i_in) != Operator::ACCEPT)
return Operator::REJECT;
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectDigitNZ(unsigned int &i_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c;
switch ((c = com.readChar(session.timeout()))) {
case '1': i_in = 1; break;
case '2': i_in = 2; break;
case '3': i_in = 3; break;
case '4': i_in = 4; break;
case '5': i_in = 5; break;
case '6': i_in = 6; break;
case '7': i_in = 7; break;
case '8': i_in = 8; break;
case '9': i_in = 9; break;
case -1:
session.setLastError(com.getLastError());
return Operator::ERROR;
case -2:
return Operator::TIMEOUT;
default:
com.unReadChar(c);
return Operator::REJECT;
}
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectSet(SequenceSet &s_in)
{
Session &session = Session::getInstance();
unsigned int seqnum = (unsigned int) -1;
Operator::ParseResult res;
/* if a set does not start with a sequencenum, then it's not a
* set. :-) seqnum == -1 means '*'. */
if ((res = expectSequenceNum(seqnum)) != Operator::ACCEPT)
return res;
/* the first number is always a part of the set */
s_in.addNumber(seqnum);
/* if _after_ a set there is a ':', then there will always be a
* sequencenum after the colon. if not, it's a syntax error. a
* colon delimits two numbers in a range. */
if ((res = expectThisString(":")) == Operator::ACCEPT) {
unsigned int seqnum2 = (unsigned int) -1;
if ((res = expectSequenceNum(seqnum2)) != Operator::ACCEPT) {
session.setLastError("expected sequencenum");
return res;
}
s_in.addRange(seqnum, seqnum2);
}
/* if _after_ a set there is a ',', then there will always be
* a set after the comma. if not, it's a syntax error. */
if ((res = expectThisString(",")) == Operator::ACCEPT)
if ((res = expectSet(s_in)) != Operator::ACCEPT) {
session.setLastError("expected set");
return res;
}
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectSequenceNum(unsigned int &i_in)
{
IO &com = IOFactory::getInstance().get(1);
Session &session = Session::getInstance();
int c = com.readChar(session.timeout());
if (c == -1) {
session.setLastError(com.getLastError());
return Operator::ERROR;
} else if (c == -2)
return Operator::TIMEOUT;
if (c == '*') {
i_in = (unsigned int) -1;
return Operator::ACCEPT;
} else
com.unReadChar(c);
if (expectNZNumber(i_in) != Operator::ACCEPT)
return Operator::REJECT;
else
return Operator::ACCEPT;
}
//----------------------------------------------------------------------
Operator::ParseResult Binc::expectNZNumber(unsigned int &i_in)
{
unsigned int c;
Operator::ParseResult res;
if ((res = expectDigitNZ(c)) != Operator::ACCEPT)
return res;
i_in = c;
while ((res = expectDigit(c)) == Operator::ACCEPT)
i_in = (i_in * 10) + c;
if (res == Operator::TIMEOUT)
return res;
return Operator::ACCEPT;
}
syntax highlighted by Code2HTML, v. 0.9.1