diff --git a/omnia/Omnia0.cpp b/omnia/Omnia0.cpp index 668a7c7cd..36f2e653a 100755 --- a/omnia/Omnia0.cpp +++ b/omnia/Omnia0.cpp @@ -1,49 +1,133 @@ #include #include +#include +#include "date.h" #include "expr.h" #include "utility.h" #include "xml.h" +class TExpr_omnia : public TExpression +{ + enum { _date2k, _periodlastday, _recno }; + + static int _curr_recno; + +protected: + virtual int parse_user_func(const char* name, int nparms) const; + virtual void evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const; + +public: + static void set_curr_recno(int n) { _curr_recno = n; } + + TExpr_omnia(const char* exp) { set(exp, _strexpr); } +}; + +int TExpr_omnia::_curr_recno = 0; + +int TExpr_omnia::parse_user_func(const char* name, int nparms) const +{ + if (strcmp(name, "DATE2K") == 0) + return nparms == 1 ? _date2k : -1; + + if (strcmp(name, "PERIODLASTDAY") == 0) + return nparms == 1 ? _periodlastday : -1; + + if (strcmp(name, "RECNO") == 0) + return nparms == 0 ? _recno : -1; + + return -1; +} + +void TExpr_omnia::evaluate_user_func(int index, int nparms, TEval_stack& stack, TTypeexp type) const +{ + switch (index) + { + case _date2k: // Acqua Omnia Only + { + TString& str = stack.peek_string(); + TToken_string tok(str, '/'); + const int d = tok.get_int(0); + const int m = tok.get_int(); + int y = tok.get_int(); + if (d > 0 && m > 0 && y < 100) + { + y += 2000; + const TDate milleniumbug(d, m, y); + str = milleniumbug.string(full, '/'); + } + } + break; + case _periodlastday: // Acqua Omnia Only + { + TString& period = stack.peek_string(); + char m1[4], m2[4]; + int year = 0; + sscanf(period, "%3s-%3s/%d", m1, m2, &year); + + const TString4 strMonth = m2; + for (int month = 12; month > 0; month--) + { + if (strMonth.compare(itom(month), 3, true) == 0) + break; + } + if (month > 0) + { + TDate day(1, month, year); + day.set_end_month(); + period = day.string(full, '/'); + } + } + break; + case _recno: + stack.push(_curr_recno); + break; + default: + break; + } +} + /////////////////////////////////////////////////////////// // TTextRecord /////////////////////////////////////////////////////////// class TTextRecord : public TString_array { - const TXmlItem* m_trc; const TXmlItem* m_inrec; + const TXmlItem* m_outrec; int m_nLines, m_nColumns; TString m_str; protected: char* GetLineBuffer(int i, int size); const TString& GetFieldValue(const TXmlItem& field) const; - const TXmlItem* FindField(const TString& name) const; + const TXmlItem* FindInputField(const TString& name) const; public: void SetTrc(const TXmlItem& trc); bool Read(istream& input); const TString& GetValue(const TString& name) const; - const TString& Evaluate(TExpression& exp) const; + const TString& Evaluate(TExpr_omnia& exp) const; - TTextRecord() : m_trc(NULL), m_nLines(0), m_nColumns(0) { } - TTextRecord(const TXmlItem& trc) : m_trc(&trc) { } + TTextRecord() : m_nLines(0), m_nColumns(0) { } + TTextRecord(const TXmlItem& trc) { SetTrc(trc); } }; void TTextRecord::SetTrc(const TXmlItem& trc) { - m_trc = &trc; - - m_nLines = trc.GetIntAttr("Lines"); + const TXmlItem& input = *trc.FindFirst("Input"); + m_nLines = input.GetIntAttr("Lines"); if (m_nLines <= 0) m_nLines = 1; - m_nColumns = trc.GetIntAttr("Columns"); + m_nColumns = input.GetIntAttr("Columns"); - m_inrec = trc.FindFirst("Record"); + m_inrec = input.FindFirst("Record"); CHECK(m_inrec, "Null input record"); + + m_outrec = trc.FindFirst("Output")->FindFirst("Record"); + CHECK(m_outrec, "Null output record"); } char* TTextRecord::GetLineBuffer(int i, int size) @@ -64,23 +148,27 @@ char* TTextRecord::GetLineBuffer(int i, int size) bool TTextRecord::Read(istream& input) { - bool ok = true; - if (m_nLines <= 1 && m_nColumns > 0) // Record a lunghezza fissa + bool ok = !input.eof(); + if (ok) { - char* buff = GetLineBuffer(0, m_nColumns); - input.read(buff, m_nColumns); - buff[m_nColumns] = '\0'; - } - else - { - int size = m_nColumns; - if (size <= 0) - size = 1024*16; - for (int i = 0; i < m_nLines; i++) + if (m_nLines <= 1 && m_nColumns > 0) // Record a lunghezza fissa { - char* buff = GetLineBuffer(i, size); - input.getline(buff, size); - buff[size] = '\0'; + char* buff = GetLineBuffer(0, m_nColumns); + input.read(buff, m_nColumns); + buff[m_nColumns] = '\0'; + ok = *buff != '\0'; + } + else + { + int size = m_nColumns; + if (size <= 0) + size = 1024*16; + for (int i = 0; i < m_nLines; i++) + { + char* buff = GetLineBuffer(i, size); + input.getline(buff, size); + buff[size] = '\0'; + } } } return ok; @@ -114,7 +202,7 @@ const TString& TTextRecord::GetFieldValue(const TXmlItem& field) const return str; } -const TXmlItem* TTextRecord::FindField(const TString& name) const +const TXmlItem* TTextRecord::FindInputField(const TString& name) const { for (int i = 0; i < m_inrec->GetChildren(); i++) { @@ -127,25 +215,19 @@ const TXmlItem* TTextRecord::FindField(const TString& name) const const TString& TTextRecord::GetValue(const TString& name) const { - const TXmlItem* f = FindField(name); + const TXmlItem* f = FindInputField(name); if (f != NULL) return GetFieldValue(*f); + return name; } -const TString& TTextRecord::Evaluate(TExpression& exp) const +const TString& TTextRecord::Evaluate(TExpr_omnia& exp) const { TString& str = (TString&)m_str; - str = exp.string(); - if (str.starts_with("BEFORE(AFTER")) - { - int i = 0; - i++; - } - const int nv = exp.numvar(); - if (nv > 0) + if (nv > 0 || strchr(exp.string(), '(') != NULL) { for (int i = nv-1; i >= 0; i--) { @@ -169,11 +251,14 @@ class TScrittore : public TObject { private: ofstream* _out; + int _recno; public: ofstream& OutStream() { return *_out; } + int inc_recno() { _recno++; return _recno; } + int recno() const { return _recno; } - TScrittore(const char* name) { _out = new ofstream(name); } + TScrittore(const char* name) : _recno(0) { _out = new ofstream(name); } virtual~ TScrittore() { delete _out; } }; @@ -187,12 +272,12 @@ class TCasaEditrice : public TAssoc_array const TXmlItem& m_trc; TString m_strPrefix, m_strExt; - TExpression* m_exprSuffix; + TExpr_omnia* m_exprSuffix; TString m_strRecHead, m_strRecFoot, m_strFldHead, m_strFldFoot; protected: - ofstream& OutStream(const char* suffix); + TScrittore& Scrittore(const char* suffix); void WriteHeader(ostream& output) const; void WriteFooter(ostream& output) const; @@ -262,7 +347,7 @@ void TCasaEditrice::WriteFooter(ostream& output) const } } -ofstream& TCasaEditrice::OutStream(const char* suffix) +TScrittore& TCasaEditrice::Scrittore(const char* suffix) { TScrittore* s = (TScrittore*)objptr(suffix); if (s == NULL) @@ -275,7 +360,7 @@ ofstream& TCasaEditrice::OutStream(const char* suffix) add(suffix, s); WriteHeader(s->OutStream()); } - return s->OutStream(); + return *s; } ofstream& TCasaEditrice::ChooseOutput(const TTextRecord& rec) @@ -283,7 +368,10 @@ ofstream& TCasaEditrice::ChooseOutput(const TTextRecord& rec) TString16 strSuffix; if (m_exprSuffix != NULL) strSuffix = rec.Evaluate(*m_exprSuffix); - return OutStream(strSuffix); + + TScrittore& s = Scrittore(strSuffix); + TExpr_omnia::set_curr_recno(s.inc_recno()); + return s.OutStream(); } TCasaEditrice::TCasaEditrice(const TXmlItem& trc, const char* name) : m_trc(trc), m_exprSuffix(NULL) @@ -307,7 +395,7 @@ TCasaEditrice::TCasaEditrice(const TXmlItem& trc, const char* name) : m_trc(trc) const TString strSuffix = pOutFile->GetAttr("Suffix"); if (strSuffix.not_empty()) - m_exprSuffix = new TExpression(strSuffix, _strexpr); + m_exprSuffix = new TExpr_omnia(strSuffix); TXmlItem* pRecOut = pOutFile->FindFirst("Record"); CHECK(pRecOut, "NULL output record"); @@ -365,7 +453,7 @@ bool TLettore::load_trc(const char* t) const TString& TLettore::evaluate(int index) const { - TExpression& exp = (TExpression&)_expressions[index]; + TExpr_omnia& exp = (TExpr_omnia&)_expressions[index]; return _curr.Evaluate(exp); } @@ -405,7 +493,7 @@ int TLettore::convert(const TFilename& src, const TFilename& trc, const TFilenam return 4; } - _curr.SetTrc(*infile); + _curr.SetTrc(_trc); const int inmode = infile->GetIntAttr("Binary") != 0 ? (ios::in|ios::binary) : ios::in; ifstream input(src, inmode); @@ -417,17 +505,16 @@ int TLettore::convert(const TFilename& src, const TFilename& trc, const TFilenam { const TXmlItem* outfield = recout->GetChild(i); outfield->GetEnclosedText(expr); - _expressions.add(new TExpression(expr, _strexpr)); + _expressions.add(new TExpr_omnia(expr)); } - while (!input.eof()) + while (_curr.Read(input)) { - _curr.Read(input); ofstream& output = mondadori.ChooseOutput(_curr); output << mondadori.RecHead(); for (int i = 0; i < recout->GetChildren(); i++) { - const TXmlItem* outfield = recout->GetChild(i); + TXmlItem* outfield = recout->GetChild(i); outfield->GetEnclosedText(expr); const TString& val = evaluate(i); output << mondadori.FldHead() << val << mondadori.FldFoot(); diff --git a/omnia/expr.cpp b/omnia/expr.cpp index 63f86a189..356f21bac 100755 --- a/omnia/expr.cpp +++ b/omnia/expr.cpp @@ -717,7 +717,7 @@ void TExpression::eval() const TString& s1 = evalstack.pop_string(); TString& s2 = evalstack.peek_string(); const int pos = s2.find(s1); - if (pos > 0) + if (pos >= 0) s2 = s2.mid(pos+s1.len()); else s2.cut(0); @@ -732,6 +732,22 @@ void TExpression::eval() s2.cut(pos); } break; + case _between: + { + const TString& end = evalstack.pop_string(); + const TString& start = evalstack.pop_string(); + TString& str = evalstack.peek_string(); + int from = str.find(start); + if (from >= 0) + { + from += start.len(); + const int to = str.find(end, from); + str = str.sub(from , to); + } + else + str.cut(0); + } + break; case _rfind: { const TString& s1 = evalstack.pop_string(); @@ -759,24 +775,24 @@ HIDDEN char _tok[81]; TCodesym TExpression::tok2fun(const char* tok) const { - const int MAX_TOK = 31; - HIDDEN const char* fnstr[MAX_TOK] = { "AFTER", "ANSI", "BEFORE", "CEIL", - "COS", "EXP", "EXP10", "IF", "LEFT", - "LEN", "LOG", "LOG10", "MAX", "MID", - "MIN", "NUM", "PERC", "POW", "RFIND", - "RIGHT", "ROUND", "SCORP", "SIN", "SQR", - "SQRT", "STR", "SUBSTR", "TAN", "TRIM", - "TRUNC", "UPPER" }; + const int MAX_TOK = 32; + HIDDEN const char* fnstr[MAX_TOK] = { "AFTER", "ANSI", "BEFORE", "BETWEEN", "CEIL", + "COS", "EXP", "EXP10", "IF", + "LEFT", "LEN", "LOG", "LOG10", + "MAX", "MID", "MIN", "NUM", "PERC", "POW", + "RFIND", "RIGHT", "ROUND", "SCORP", "SIN", "SQR", + "SQRT", "STR", "SUBSTR", "TAN", "TRIM", + "TRUNC", "UPPER" }; - HIDDEN TCodesym fntok[MAX_TOK] = { _after, _ansi, _before, _ceil, - _cos, _exp, _exp10, _if, _left, - _len, _log, _log10, _max, _mid, - _min, _num, _perc, _pow, _rfind, - _right, _round, _scorp, _sin, _sqr, - _sqrt, _str, _substr, _tan, _trim, - _trunc, _upper }; + HIDDEN TCodesym fntok[MAX_TOK] = { _after, _ansi, _before, _between, _ceil, + _cos, _exp, _exp10, _if, + _left, _len, _log, _log10, + _max, _mid, _min, _num, _perc, _pow, + _rfind, _right, _round, _scorp, _sin, _sqr, + _sqrt, _str, _substr, _tan, _trim, + _trunc, _upper }; - int f = 0, l = MAX_TOK-1, i = MAX_TOK/2; + int f = 0, l = MAX_TOK-1, i = MAX_TOK/2; while (TRUE) { // i = (f+l)>>1; @@ -1100,6 +1116,7 @@ TCodesym TExpression::__factor(TCodesym startsym) break; case _mid: case _substr: + case _between: sym = __function(3, true, nparms_found); _code.add(startsym); break; @@ -1133,7 +1150,6 @@ TCodesym TExpression::__term(TCodesym startsym) return sym; } - TCodesym TExpression::__expression(TCodesym startsym) { TCodesym sym; diff --git a/omnia/expr.h b/omnia/expr.h index 5507b2966..820bc4232 100755 --- a/omnia/expr.h +++ b/omnia/expr.h @@ -71,6 +71,7 @@ enum TCodesym { _trim, // @emem Elimina spazi iniziali e finali di una stringa _before, // @emem Estrae la parte precedente una stringa fissa data _after, // @emem Estrae la parte seguente una stringa fissa data + _between, // @emem Estrae la parte tra due stringhe fisse date _rfind, // @emem Cerca una stringa all'indietro }; // @doc INTERNAL diff --git a/omnia/omnia.xml b/omnia/omnia.xml index 3093d464d..84fdc172a 100755 --- a/omnia/omnia.xml +++ b/omnia/omnia.xml @@ -21,7 +21,12 @@ - + + + + + + @@ -34,9 +39,9 @@ Impianto 1 000000 - "RECNO()" + RECNO() BEFORE(Indirizzo, ",") - BEFORE(AFTER(Indirizzo, ","), "/") + BETWEEN(Indirizzo, ",", "/") AFTER(Indirizzo, "/") @@ -58,7 +63,7 @@ Impianto 1 1 - "RECNO()" + RECNO() Impianto Progressivo @@ -95,7 +100,7 @@ - BEFORE(AFTER(QuotaFissaContatore, "E/ms."),"=") + BETWEEN(QuotaFissaContatore, "E/ms.", "=") "NO" 4 Contratto @@ -109,16 +114,16 @@ "SI" "SI" - BEFORE(AFTER(DataLettura, "DEL"),"mc.") - AFTER(DataLettura, "mc.") + DATE2K(BETWEEN(LetturaPre, "DEL "," mc.")) + AFTER(LetturaPre, "mc. ") 0 10 CodicePlacca "SI" - "???" - "???" - "???" - "???" + IF(BETWEEN(LetturaAtt, " DEL ", " mc.")=" /==/==", PERIODLASTDAY(Periodo), DATE2K(BETWEEN(LetturaAtt, " DEL ", " mc."))) + IF(AFTER(LetturaAtt,"mc. ")="========", AFTER(LetturaPre, "mc. "), AFTER(LetturaAtt, "mc. ")) + IF(MID(TipoLettura, 1, 13)="Lettura reale", Consumo, ConsumoFatturato) + IF(MID(TipoLettura, 1, 13)="Lettura reale", 0, 3) "SI"