69f4b04f40
git-svn-id: svn://10.65.10.50/trunk@1609 c028cbd2-c16b-5b4b-a496-9718f37d4682
521 lines
11 KiB
C++
Executable File
521 lines
11 KiB
C++
Executable File
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <files.h>
|
|
#include <utility.h>
|
|
#include <config.h>
|
|
|
|
#ifndef FOXPRO
|
|
#include <expr.h>
|
|
#include <applicat.h>
|
|
#else
|
|
#include <strings.h>
|
|
#endif
|
|
|
|
#include <extcdecl.h>
|
|
|
|
#define BLOCKLEN 512
|
|
#define INVFLD 255
|
|
|
|
// @doc EXTERNAL
|
|
|
|
HIDDEN char _files_tmp_string[128];
|
|
|
|
TFile::TFile (int lenrec, int base)
|
|
|
|
{
|
|
_file = new SecDef;
|
|
// if (_file == NULL) fatal_box ("Can't allocate record file ");
|
|
_file->IOR = NOERR;
|
|
_len = lenrec;
|
|
_base = base;
|
|
_file->LockMode = _manulock;
|
|
_file->lpos = -1;
|
|
_file->name[0] = '\0';
|
|
}
|
|
|
|
TFile::~TFile ()
|
|
|
|
{
|
|
delete _file;
|
|
}
|
|
|
|
// @mfunc Apre il file specificato
|
|
void TFile::open (
|
|
const char *name, // @parm Nome del file da aprire
|
|
TFilelock lockmode) // @parm Tipo di lock da attivare durante l'apertura del file
|
|
// (default _manulock)
|
|
{
|
|
COpen (_file, (char *) name, _len, _base, lockmode);
|
|
}
|
|
|
|
bool TFile::verify (const char *name)
|
|
|
|
{
|
|
CVerify (_file, (char *) name);
|
|
return _file->IOR == NOERR;
|
|
}
|
|
|
|
// @mfunc Crea il file specificato
|
|
void TFile::create (
|
|
const char *name, // @parm Nome del file da creare
|
|
TRecnotype nrecord) // @parm Numero di recird che deve avere il file al momento
|
|
// della creazione (default 0)
|
|
|
|
// @comm Il file creato avra' dimensioni sufficienti a contenere <p nrecord> record
|
|
|
|
{
|
|
CCreate (_file, (char *) name, _len, _base, (nrecord * _len) / BLOCKLEN + 1);
|
|
}
|
|
|
|
void TFile::chsize (const char *name, TRecnotype nrecord)
|
|
|
|
{
|
|
CChsize (_file, (char *) name, _len, _base, (nrecord * _len) / BLOCKLEN + 1);
|
|
}
|
|
|
|
void TFile::close ()
|
|
|
|
{
|
|
CClose (_file);
|
|
}
|
|
|
|
void TFile::unlink (const char *name)
|
|
|
|
{
|
|
CDelete (_file, (char *) name);
|
|
}
|
|
|
|
// @mfunc Legge un record dal file
|
|
void TFile::read (
|
|
char *record, // @parm Record letto
|
|
TRecnotype recnum, // @parm Numero del record da leggere
|
|
TReclock lock) // @parm Tipo di blocco da attivare durante la letture (default _nolock)
|
|
|
|
{
|
|
_file->LenRec = _len;
|
|
_file->BaseFil = _base;
|
|
CRead (_file, record, recnum, lock);
|
|
}
|
|
|
|
// @mfunc Scrive un record sul file
|
|
void TFile::write (
|
|
char *record, // @parm Record da scrivere
|
|
TRecnotype recnum, // @parm Numero del record da scrivere
|
|
TReclock lock) // @parm Tipo di blocco da attivare durante la letture (default _nolock)
|
|
|
|
{
|
|
_file->LenRec = _len;
|
|
_file->BaseFil = _base;
|
|
CWrite (_file, record, recnum, lock);
|
|
}
|
|
|
|
int TFile::status () const
|
|
|
|
{
|
|
return _file->IOR;
|
|
}
|
|
|
|
TDir::TDir () : _num(-1), _com(FALSE)
|
|
|
|
{
|
|
_dir = new FileDes;
|
|
if (_dir == NULL)
|
|
fatal_box ("Can't allocate dir");
|
|
zero ();
|
|
}
|
|
|
|
TDir::~TDir ()
|
|
{
|
|
delete _dir;
|
|
}
|
|
|
|
const char *TDir::name () const
|
|
{
|
|
return _dir->SysName;
|
|
}
|
|
|
|
const char *TDir::filename () const
|
|
{
|
|
strcpy(_files_tmp_string, _dir->SysName);
|
|
strcat(_files_tmp_string, ".dbf");
|
|
return _files_tmp_string;
|
|
}
|
|
|
|
void TDir::set_name (const char * name)
|
|
{
|
|
CHECK(name != NULL, "NULL Filename");
|
|
CHECK(strlen(name) < 42, "Name too long");
|
|
char * p = strchr(name, '.');
|
|
CHECK(p == NULL, "Can't use extension");
|
|
if (p)
|
|
p = '\0';
|
|
strncpy(_dir->SysName, _files_tmp_string, 42);
|
|
_dir->SysName[41] = '\0';
|
|
}
|
|
|
|
const char *TDir::des () const
|
|
{
|
|
return _dir->Des;
|
|
}
|
|
|
|
const char* TDir::tab_des(const char* tab)
|
|
{
|
|
const char* t = tab; if (t[0] == '$' || t[0] == '%') t++;
|
|
|
|
TString256 tmp;
|
|
tmp << DESCDIR << "/d" << t << ".des";
|
|
|
|
#ifndef FOXPRO
|
|
TConfig cnf(tmp, DESCTAB);
|
|
t = cnf.get("Description", NULL, -1, tab);
|
|
#endif
|
|
|
|
return strcpy(__tmp_string, t);
|
|
}
|
|
|
|
|
|
const char *TDir::expr () const
|
|
{
|
|
return _dir->FCalc;
|
|
}
|
|
|
|
TRecnotype & TDir::eod () const
|
|
|
|
{
|
|
return _dir->EOD;
|
|
}
|
|
|
|
TRecnotype & TDir::eox () const
|
|
|
|
{
|
|
return _dir->EOX;
|
|
}
|
|
|
|
TRecnotype & TDir::flags () const
|
|
|
|
{
|
|
return _dir->Flags;
|
|
}
|
|
|
|
word & TDir::len ()
|
|
|
|
{
|
|
return (word &) _dir->LenR;
|
|
}
|
|
|
|
int TDir::status (TDirtype dirop) const
|
|
|
|
{
|
|
return fdir[dirop].IOR;
|
|
}
|
|
|
|
void TDir::set_len (const UINT16 len)
|
|
{
|
|
_dir->LenR = len;
|
|
}
|
|
|
|
void TDir::set_eox (const RecNoType eox)
|
|
{
|
|
_dir->EOX = eox;
|
|
}
|
|
|
|
void TDir::set (const char *name, const RecNoType eod, const RecNoType flag, const char *des, const char *calc)
|
|
{
|
|
strncpy (_dir->SysName, name, sizeof (_dir->SysName));
|
|
_dir->EOD = eod;
|
|
_dir->Flags = flag;
|
|
strncpy (_dir->Des, des, sizeof (_dir->Des));
|
|
strncpy (_dir->FCalc, calc, sizeof (_dir->FCalc));
|
|
}
|
|
|
|
// @mfunc Aggiorna l'oggetto TDir con i parametri del file
|
|
void TDir::get (
|
|
int nfile, // @parm Numero del file con cui aggiornare l'oggetto
|
|
TReclock lock, // @parm Tipo di blocco (default _nolock)
|
|
TDirtype dirtype, // @parm Direttorio nella quale e' contenuto il file (default _nordir)
|
|
TDirop op) // @parm Tipo di operazioni effettuabili sul file (default _nordirop)
|
|
|
|
{
|
|
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
|
|
|
|
if (op == _nordirop)
|
|
COpenFile (nfile, _dir, int (lock), _whichdir);
|
|
else
|
|
CGetFile (nfile, _dir, int (lock), _whichdir);
|
|
_num = nfile;
|
|
_com = _dir->SysName[0] != '$';
|
|
}
|
|
|
|
// @mfunc Aggiorna il file indicato con i parametri passati
|
|
void TDir::put (
|
|
int nfile, // @parm Numero del file da aggiornare
|
|
TDirtype dirtype, // @parm Direttorio nella quale e' contenuto il file (default _nordir)
|
|
TDirop op) // @parm Tipo di operazioni effettuabili sul file (default _nordirop)
|
|
{
|
|
CHECKD(nfile > 0, "Bad file number ", nfile);
|
|
|
|
const int whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
|
|
|
|
if (op == _nordirop)
|
|
CCloseFile (nfile, _dir, whichdir);
|
|
else
|
|
CPutFile (nfile, _dir, whichdir);
|
|
}
|
|
|
|
void TDir::zero ()
|
|
|
|
{
|
|
zerofdes (_dir);
|
|
}
|
|
|
|
int TDir::items (TDirtype dirtype) const
|
|
|
|
{
|
|
FileDes f;
|
|
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
|
|
|
|
CGetFile (1, &f, _nolock, _whichdir);
|
|
return (int) f.EOD;
|
|
}
|
|
|
|
TTrec::TTrec ()
|
|
|
|
{
|
|
_rec = new RecDes;
|
|
zero ();
|
|
_num = -1;
|
|
}
|
|
|
|
TTrec::~TTrec ()
|
|
|
|
{
|
|
delete _rec;
|
|
}
|
|
|
|
int TTrec ::compare (const TSortable & a) const
|
|
|
|
{
|
|
const TTrec & r = (const TTrec &) a;
|
|
const int res = memcmp ((const void *) _rec, (const void *) r._rec, sizeof (*_rec));
|
|
return res;
|
|
}
|
|
|
|
void TTrec::rehash ()
|
|
|
|
{
|
|
setrdes (_rec);
|
|
}
|
|
|
|
TTrec & TTrec::operator = (const TTrec & b)
|
|
|
|
{
|
|
_num = b._num;
|
|
memcpy (_rec, b._rec, sizeof (*_rec));
|
|
return *this;
|
|
}
|
|
|
|
// @mfunc Assegna all'oggetto TTrec il tracciato record del file indicato
|
|
void TTrec::get (
|
|
int nfile, // @parm Numero del file da cui estrarre il tracciato record
|
|
TDirtype dirtype) // @parm Direttorio nella quale e' contenuto il file (default _nordir)
|
|
|
|
{
|
|
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
|
|
|
|
CGetRec (nfile, _rec, _whichdir);
|
|
_num = nfile;
|
|
}
|
|
|
|
// @mfunc Setta il file indicato con il tracciato record dell'oggetto
|
|
void TTrec::put (
|
|
int nfile, // @parm Numero del file di cui settare il tracciato record
|
|
TDirtype dirtype) // @parm Direttorio nella quale e' contenuto il file (default _nordir)
|
|
|
|
{
|
|
int _whichdir = (dirtype == _nordir ? NORDIR : COMDIR);
|
|
|
|
if (nfile <= 0)
|
|
fatal_box ("Bad file number %d", nfile);
|
|
CPutRec (nfile, _rec, _whichdir);
|
|
}
|
|
|
|
void TTrec::zero ()
|
|
|
|
{
|
|
zerordes (_rec);
|
|
}
|
|
|
|
int TTrec::status (TDirtype dirop) const
|
|
|
|
{
|
|
return rdir[dirop].IOR;
|
|
}
|
|
|
|
int TTrec ::field (const char *name) const
|
|
|
|
{
|
|
return findfld (_rec, (char *) name);
|
|
|
|
}
|
|
|
|
const char *TTrec ::fielddef (int fld) const
|
|
|
|
{
|
|
sprintf (_files_tmp_string, "%s|%d|%d|%d", _rec->Fd[fld].Name,
|
|
(int) _rec->Fd[fld].TypeF, (int) _rec->Fd[fld].Len,
|
|
(int) _rec->Fd[fld].Dec);
|
|
return _files_tmp_string;
|
|
}
|
|
|
|
const char *TTrec ::keydef (int key) const
|
|
|
|
{
|
|
TFixed_string s (_files_tmp_string, 128);
|
|
|
|
s = "";
|
|
for (int j = 0; j < _rec->Ky[key].NkFields; j++)
|
|
{
|
|
const bool upper = _rec->Ky[key].FieldSeq[j] > MaxFields;
|
|
const int nfld = _rec->Ky[key].FieldSeq[j] - (upper ? MaxFields : 0);
|
|
|
|
if (j)
|
|
s << "+";
|
|
if (upper)
|
|
s << "UPPER(";
|
|
s << _rec->Fd[nfld].Name;
|
|
if (_rec->Ky[key].FromCh[j] < INVFLD)
|
|
s << format ("[%d,%d]", _rec->Ky[key].FromCh[j] + 1,
|
|
_rec->Ky[key].ToCh[j] + 1);
|
|
if (upper)
|
|
s << ")";
|
|
}
|
|
s << (_rec->Ky[key].DupKeys ? "|X" : "| ");
|
|
return (const char *) s;
|
|
}
|
|
|
|
|
|
#ifndef FOXPRO
|
|
|
|
bool TDir::is_active () const
|
|
{
|
|
const int module = abs((int)flags());
|
|
return main_app().has_module(module, CHK_DONGLE);
|
|
}
|
|
|
|
void TTrec::update_fielddef (int nfld, const char *desc)
|
|
|
|
{
|
|
TToken_string s (desc);
|
|
strcpy (_rec->Fd[nfld].Name, s.get ());
|
|
_rec->Fd[nfld].TypeF = s.get_int ();
|
|
_rec->Fd[nfld].Len = s.get_int ();
|
|
_rec->Fd[nfld].Dec = s.get_int ();
|
|
}
|
|
|
|
void TTrec::update_keydef (int key, const char *desc)
|
|
|
|
{
|
|
TExpression expr ("", _strexpr);
|
|
TToken_string s (desc);
|
|
TString ke (s.get ());
|
|
|
|
if (expr.set ((const char *) ke, _strexpr))
|
|
{
|
|
_rec->Ky[key].DupKeys = (*s.get () != ' ');
|
|
TCodearray & c = expr.code ();
|
|
c.begin ();
|
|
int n = 0;
|
|
while (!c.end ())
|
|
{
|
|
TCode & inst = c.step ();
|
|
TCodesym sym = inst.getsym ();
|
|
|
|
if (sym == _variable)
|
|
{
|
|
const char *s = inst.string ();
|
|
|
|
for (int i = 0; i < _rec->NFields; i++)
|
|
if (strcmp (_rec->Fd[i].Name, s) == 0)
|
|
break;
|
|
|
|
_rec->Ky[key].FieldSeq[n] = i;
|
|
_rec->Ky[key].FromCh[n] = INVFLD;
|
|
_rec->Ky[key].FromCh[n] = INVFLD;
|
|
inst = c.step ();
|
|
sym = inst.getsym ();
|
|
if (sym == _upper)
|
|
_rec->Ky[key].FieldSeq[n] += MaxFields;
|
|
else if (sym == _number)
|
|
{
|
|
_rec->Ky[key].FromCh[n] = (int)inst.number().integer() - 1;
|
|
inst = c.step ();
|
|
_rec->Ky[key].ToCh[n] = _rec->Ky[key].FromCh[n] + (int)inst.number ().integer () - 1;
|
|
inst = c.step ();
|
|
}
|
|
else
|
|
c.backtrace ();
|
|
n++;
|
|
}
|
|
}
|
|
_rec->Ky[key].NkFields = n;
|
|
}
|
|
}
|
|
|
|
void TTrec::print_on (ostream & out) const
|
|
|
|
{
|
|
out << num () << '\n';
|
|
const int nfields = fields ();
|
|
TToken_string s (80);
|
|
|
|
out << nfields << '\n';
|
|
for (int i = 0; i < nfields; i++)
|
|
{
|
|
s = fielddef (i);
|
|
out << s << '\n';
|
|
}
|
|
const int nkeys = keys ();
|
|
|
|
out << nkeys << '\n';
|
|
for (i = 0; i < nkeys; i++)
|
|
{
|
|
s = keydef (i);
|
|
out << s << '\n';
|
|
}
|
|
}
|
|
|
|
void TTrec::read_from (istream & in)
|
|
|
|
{
|
|
int ln;
|
|
|
|
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
|
|
ln = atoi (_files_tmp_string);
|
|
if (ln != num () && !yesno_box ("Descrizione relativa al file n.ro %d.\n Continuo ?", ln))
|
|
return;
|
|
int nfields;
|
|
|
|
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
|
|
nfields = atoi (_files_tmp_string);
|
|
set_fields (nfields);
|
|
for (int i = 0; i < nfields; i++)
|
|
{
|
|
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
|
|
update_fielddef (i, _files_tmp_string);
|
|
}
|
|
int nkeys;
|
|
|
|
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
|
|
nkeys = atoi (_files_tmp_string);
|
|
set_keys (nkeys);
|
|
for (i = 0; i < nkeys; i++)
|
|
{
|
|
in.getline (_files_tmp_string, sizeof (_files_tmp_string), '\n');
|
|
update_keydef (i, _files_tmp_string);
|
|
}
|
|
rehash ();
|
|
}
|
|
|
|
#endif // FOXPRO
|