Files correlati : omnia0.exe omnia.xml Ricompilazione Demo : [ ] Commento : Ultimissima verisione dell'acqua tutte le cose. git-svn-id: svn://10.65.10.50/trunk@11735 c028cbd2-c16b-5b4b-a496-9718f37d4682
543 lines
13 KiB
C++
Executable File
543 lines
13 KiB
C++
Executable File
#include <windows.h>
|
|
#include <fstream.h>
|
|
#include <stdio.h>
|
|
|
|
#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_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* 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(TExpr_omnia& exp) const;
|
|
|
|
TTextRecord() : m_nLines(0), m_nColumns(0) { }
|
|
TTextRecord(const TXmlItem& trc) { SetTrc(trc); }
|
|
};
|
|
|
|
void TTextRecord::SetTrc(const TXmlItem& trc)
|
|
{
|
|
const TXmlItem& input = *trc.FindFirst("Input");
|
|
m_nLines = input.GetIntAttr("Lines");
|
|
if (m_nLines <= 0)
|
|
m_nLines = 1;
|
|
|
|
m_nColumns = input.GetIntAttr("Columns");
|
|
|
|
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)
|
|
{
|
|
CHECKD(i >= 0 && i < m_nLines, "Line out of range ", i);
|
|
CHECKD(size > 0, "Bad record size ", size);
|
|
|
|
TToken_string* str = (TToken_string*)objptr(i);
|
|
if (str == NULL)
|
|
{
|
|
str = new TToken_string(size);
|
|
add(str, i);
|
|
}
|
|
char* buff = str->get_buffer(size);
|
|
*buff = '\0';
|
|
return buff;
|
|
}
|
|
|
|
bool TTextRecord::Read(istream& input)
|
|
{
|
|
bool ok = !input.eof();
|
|
if (ok)
|
|
{
|
|
if (m_nLines <= 1 && m_nColumns > 0) // Record a lunghezza fissa
|
|
{
|
|
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;
|
|
}
|
|
|
|
const TString& TTextRecord::GetFieldValue(const TXmlItem& field) const
|
|
{
|
|
int y = field.GetIntAttr("Y" ) - 1;
|
|
if (y < 0) y = 0;
|
|
|
|
int x = field.GetIntAttr("X" ) - 1;
|
|
if (x < 0) x = 0;
|
|
|
|
const int l = field.GetIntAttr("Length");
|
|
|
|
TString& str = (TString&)m_str;
|
|
str = row(y).mid(x, l);
|
|
|
|
const TString& strTrim = field.GetAttr("Trim");
|
|
int nTrim = 2;
|
|
if (strTrim.not_empty())
|
|
nTrim = atoi(strTrim);
|
|
|
|
switch (nTrim)
|
|
{
|
|
case 0: break;
|
|
case 1: str.ltrim(); break;
|
|
case 2: str.rtrim(); break;
|
|
default: str.trim(); break;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
const TXmlItem* TTextRecord::FindInputField(const TString& name) const
|
|
{
|
|
for (int i = 0; i < m_inrec->GetChildren(); i++)
|
|
{
|
|
const TXmlItem* field = m_inrec->GetChild(i);
|
|
if (field->GetAttr("Name") == name)
|
|
return field;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
const TString& TTextRecord::GetValue(const TString& name) const
|
|
{
|
|
const TXmlItem* f = FindInputField(name);
|
|
if (f != NULL)
|
|
return GetFieldValue(*f);
|
|
|
|
return name;
|
|
}
|
|
|
|
const TString& TTextRecord::Evaluate(TExpr_omnia& exp) const
|
|
{
|
|
TString& str = (TString&)m_str;
|
|
|
|
const int nv = exp.numvar();
|
|
if (nv > 0 || strchr(exp.string(), '(') != NULL)
|
|
{
|
|
for (int i = nv-1; i >= 0; i--)
|
|
{
|
|
const TString& name = exp.varname(i);
|
|
const TString& value = GetValue(name);
|
|
exp.setvar(i, value);
|
|
}
|
|
str = exp.as_string();
|
|
}
|
|
else
|
|
str = exp.string(); // Nessuna variabile = costante!
|
|
|
|
return str;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TScrittore
|
|
///////////////////////////////////////////////////////////
|
|
|
|
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) : _recno(0) { _out = new ofstream(name); }
|
|
virtual~ TScrittore() { delete _out; }
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TCasaEditrice
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TCasaEditrice : public TAssoc_array
|
|
{
|
|
const TXmlItem& m_trc;
|
|
TString m_strPrefix, m_strExt;
|
|
|
|
TExpr_omnia* m_exprSuffix;
|
|
|
|
TString m_strRecHead, m_strRecFoot, m_strFldHead, m_strFldFoot;
|
|
|
|
protected:
|
|
TScrittore& Scrittore(const char* suffix);
|
|
void WriteHeader(ostream& output) const;
|
|
void WriteFooter(ostream& output) const;
|
|
|
|
public:
|
|
const TString& RecHead() const { return m_strRecHead; }
|
|
const TString& RecFoot() const { return m_strRecFoot; }
|
|
const TString& FldHead() const { return m_strFldHead; }
|
|
const TString& FldFoot() const { return m_strFldFoot; }
|
|
|
|
ofstream& ChooseOutput(const TTextRecord& rec);
|
|
TCasaEditrice(const TXmlItem& trc, const char* name);
|
|
virtual ~TCasaEditrice();
|
|
};
|
|
|
|
|
|
void TCasaEditrice::WriteHeader(ostream& output) const
|
|
{
|
|
TXmlItem* pOutput = m_trc.FindFirst("Output");
|
|
CHECK(pOutput, "NULL output file");
|
|
|
|
TXmlItem* pHeader = pOutput->FindFirst("Header");
|
|
|
|
if (pHeader != NULL)
|
|
{
|
|
TString strHeader; pHeader->GetEnclosedText(strHeader);
|
|
if (strHeader[0] == '"')
|
|
{
|
|
strHeader.rtrim(1);
|
|
strHeader.ltrim(1);
|
|
}
|
|
strHeader = esc(strHeader);
|
|
output << strHeader;
|
|
|
|
if (pHeader->GetAttr("Auto") == "1")
|
|
{
|
|
TXmlItem* pRecOut = pOutput->FindFirst("Record");
|
|
CHECK(pRecOut, "NULL output record");
|
|
|
|
output << m_strRecHead;
|
|
for (int i = 0; i < pRecOut->GetChildren(); i++)
|
|
{
|
|
const TXmlItem* outfield = pRecOut->GetChild(i);
|
|
output << m_strFldHead;
|
|
output << outfield->GetAttr("Name");
|
|
output << m_strFldFoot;
|
|
}
|
|
output << m_strRecFoot;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TCasaEditrice::WriteFooter(ostream& output) const
|
|
{
|
|
TXmlItem* pOutput = m_trc.FindFirst("Output");
|
|
CHECK(pOutput, "NULL output file");
|
|
TXmlItem* pFooter = pOutput->FindFirst("Footer");
|
|
if (pFooter != NULL)
|
|
{
|
|
TString strFooter; pFooter->GetEnclosedText(strFooter);
|
|
if (strFooter[0] == '"')
|
|
{
|
|
strFooter.rtrim(1);
|
|
strFooter.ltrim(1);
|
|
}
|
|
strFooter = esc(strFooter);
|
|
output << strFooter;
|
|
}
|
|
}
|
|
|
|
TScrittore& TCasaEditrice::Scrittore(const char* suffix)
|
|
{
|
|
TScrittore* s = (TScrittore*)objptr(suffix);
|
|
if (s == NULL)
|
|
{
|
|
TFilename n;
|
|
n << m_strPrefix << suffix;
|
|
if (m_strExt.not_empty())
|
|
n << '.' << m_strExt;
|
|
s = new TScrittore(n);
|
|
add(suffix, s);
|
|
WriteHeader(s->OutStream());
|
|
}
|
|
return *s;
|
|
}
|
|
|
|
ofstream& TCasaEditrice::ChooseOutput(const TTextRecord& rec)
|
|
{
|
|
TString16 strSuffix;
|
|
if (m_exprSuffix != NULL)
|
|
strSuffix = rec.Evaluate(*m_exprSuffix);
|
|
|
|
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)
|
|
{
|
|
const TFilename path(name);
|
|
const int dot = path.rfind('.');
|
|
if (dot >= 0)
|
|
{
|
|
m_strPrefix = path.left(dot);
|
|
m_strExt = path.mid(dot+1);
|
|
}
|
|
else
|
|
{
|
|
m_strPrefix = path;
|
|
m_strExt.cut(0);
|
|
}
|
|
|
|
const TXmlItem* pOutFile = m_trc.FindFirst("Output");
|
|
CHECK(pOutFile, "NULL Output tag");
|
|
|
|
|
|
const TString strSuffix = pOutFile->GetAttr("Suffix");
|
|
if (strSuffix.not_empty())
|
|
m_exprSuffix = new TExpr_omnia(strSuffix);
|
|
|
|
TXmlItem* pRecOut = pOutFile->FindFirst("Record");
|
|
CHECK(pRecOut, "NULL output record");
|
|
|
|
m_strRecHead = esc(pRecOut->GetAttr("RecHead"));
|
|
m_strRecFoot = esc(pRecOut->GetAttr("RecFoot"));
|
|
m_strFldHead = esc(pRecOut->GetAttr("FldHead"));
|
|
m_strFldFoot = esc(pRecOut->GetAttr("FldFoot"));
|
|
}
|
|
|
|
TCasaEditrice::~TCasaEditrice()
|
|
{
|
|
TAssoc_array& myself = *this;
|
|
FOR_EACH_ASSOC_OBJECT(myself, h, k, o)
|
|
{
|
|
TScrittore* s = (TScrittore*)o;
|
|
WriteFooter(s->OutStream());
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// TLettore
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TLettore : public TObject
|
|
{
|
|
TXmlItem _trc;
|
|
TTextRecord _curr;
|
|
TArray _expressions;
|
|
|
|
protected:
|
|
bool load_trc(const char* trc);
|
|
|
|
const TString& get_field(const TXmlItem& field) const;
|
|
const TXmlItem* find_field(const TXmlItem& record, const TString& name) const;
|
|
const TString& evaluate(int index) const;
|
|
|
|
public:
|
|
int convert(const TFilename& src, const TFilename& trc, const TFilename& dst);
|
|
int convert(const char* cmd);
|
|
};
|
|
|
|
bool TLettore::load_trc(const char* t)
|
|
{
|
|
const TFilename trc = t;
|
|
bool ok = trc.exist();
|
|
if (ok)
|
|
{
|
|
ifstream in(trc);
|
|
ok = _trc.Read(in);
|
|
}
|
|
_curr.destroy(); // reset line sizes
|
|
return ok;
|
|
}
|
|
|
|
const TString& TLettore::evaluate(int index) const
|
|
{
|
|
TExpr_omnia& exp = (TExpr_omnia&)_expressions[index];
|
|
return _curr.Evaluate(exp);
|
|
}
|
|
|
|
int TLettore::convert(const TFilename& src, const TFilename& trc, const TFilename& dst)
|
|
{
|
|
if (!src.exist())
|
|
{
|
|
error_box("Non esiste il file di input\n%s", (const char*)src);
|
|
return 1;
|
|
}
|
|
|
|
if (!load_trc(trc))
|
|
{
|
|
error_box("Non esiste il tracciato record\n%s", (const char*)trc);
|
|
return 2;
|
|
}
|
|
|
|
if (dst.blank())
|
|
{
|
|
error_box("File di output non valido:\n%s", (const char*)dst);
|
|
return 3;
|
|
}
|
|
|
|
const TXmlItem* infile = _trc.FindFirst("Input");
|
|
const TXmlItem* outfile = _trc.FindFirst("Output");
|
|
if (infile == NULL || outfile == NULL)
|
|
{
|
|
error_box("Tracciato record non valido:\nNon esiste il tag <Input> o <Output>");
|
|
return 4;
|
|
}
|
|
|
|
const TXmlItem* recin = infile->FindFirst("Record");
|
|
const TXmlItem* recout = outfile->FindFirst("Record");
|
|
if (recin == NULL || recout == NULL)
|
|
{
|
|
error_box("Tracciato record non valido:\nNon esiste il tag <Record>");
|
|
return 4;
|
|
}
|
|
|
|
_curr.SetTrc(_trc);
|
|
|
|
const int inmode = infile->GetIntAttr("Binary") != 0 ? (ios::in|ios::binary) : ios::in;
|
|
ifstream input(src, inmode);
|
|
|
|
TCasaEditrice mondadori(_trc, dst);
|
|
|
|
TString expr;
|
|
for (int i = 0; i < recout->GetChildren(); i++)
|
|
{
|
|
const TXmlItem* outfield = recout->GetChild(i);
|
|
outfield->GetEnclosedText(expr);
|
|
_expressions.add(new TExpr_omnia(expr));
|
|
}
|
|
|
|
while (_curr.Read(input))
|
|
{
|
|
ofstream& output = mondadori.ChooseOutput(_curr);
|
|
output << mondadori.RecHead();
|
|
for (int i = 0; i < recout->GetChildren(); i++)
|
|
{
|
|
TXmlItem* outfield = recout->GetChild(i);
|
|
outfield->GetEnclosedText(expr);
|
|
const TString& val = evaluate(i);
|
|
output << mondadori.FldHead() << val << mondadori.FldFoot();
|
|
}
|
|
output << mondadori.RecFoot();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TLettore::convert(const char* cmd)
|
|
{
|
|
TToken_string str(cmd, ' ');
|
|
str.strip_d_spaces();
|
|
const TFilename src = str.get();
|
|
const TFilename trc = str.get();
|
|
const TFilename dst = str.get();
|
|
return convert(src, trc, dst);
|
|
}
|
|
|
|
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int)
|
|
{
|
|
TLettore app;
|
|
const int err = app.convert(lpCmdLine);
|
|
return err;
|
|
} |