📄 program.cpp
字号:
{
std::string::size_type l= name.size ();
if (l < 4)
return false;
std::string ext= name.substr (l - 4);
//#ifdef _Windows
std::transform (ext.begin (), ext.end (), ext.begin (), tolower);
//#endif
if (ext == ".blc" || ext == ".bas")
return true;
return false;
}
void openblassicprogram (std::ifstream & is, const std::string & name)
{
const std::ios::openmode mode= std::ios::binary | std::ios::in;
is.open (name.c_str (), mode);
if (! is)
{
if (! hasblassicextension (name) )
{
std::string namex= name;
namex+= ".blc";
is.clear ();
is.open (namex.c_str (), mode);
if (! is.is_open () )
{
namex= name;
namex+= ".bas";
is.clear ();
is.open (namex.c_str (), mode);
if (! is.is_open () )
throw ErrFileNotFound;
}
}
else
throw ErrFileNotFound;
}
}
const char signature []=
{ 'B', 'l', 'a', 's', 's', 'i', 'c', '\0' };
const size_t lsig= sizeof (signature);
bool isblassicbinary (std::istream & is)
{
char magicstring [lsig];
is.read (magicstring, lsig);
if (! is || memcmp (magicstring, signature, lsig) != 0)
return false;
return true;
}
inline void checkread (std::istream & is, size_t readed)
{
if (! is || size_t (is.gcount () ) != readed)
throw ErrFileRead;
}
const unsigned long endian_mark= 0x12345678;
} // namespace
void Program::Internal::save (const std::string & name) const
{
std::ofstream os (name.c_str (), std::ios::binary | std::ios::out);
if (! os)
return;
os.write (signature, lsig);
COMPILE_ASSERT (sizeof (unsigned long) == 4);
os.write ( (char *) & endian_mark, 4);
BlChar caux [4];
poke32 (caux, size);
os.write ( (char *) caux, 4);
os.write ( (char *) program, size);
if (! os)
throw ErrFileWrite;
}
void Program::Internal::loadtext (std::istream & is)
{
is.clear ();
is.seekg (0);
std::string str;
std::getline (is, str);
if (str [0] == '#')
{
str.erase ();
std::getline (is, str);
}
CodeLine code;
BlLineNumber nextnumline= sysvar::get32 (sysvar::AutoInit);
BlLineNumber incnumline= sysvar::get32 (sysvar::AutoInc);
BlLineNumber maxnumline= BlMaxLineNumber - incnumline;
bool fExhausted= false;
do {
if (!str.empty () && str [str.size () - 1] == '\r')
str.erase (str.size () - 1);
code.scan (str);
if (code.number () == 0)
{
if (fExhausted)
throw ErrLineExhausted;
code.setnumber (nextnumline);
fExhausted= nextnumline > maxnumline;
nextnumline+= incnumline;
}
else
{
fExhausted= code.number () > maxnumline;
nextnumline= code.number () + incnumline;
}
if (code.length () > 0)
insert (code);
std::getline (is, str);
} while (is);
}
void Program::Internal::loadbinary (std::istream & is)
{
// This was intended to check endianess, but is
// currently unused.
COMPILE_ASSERT (sizeof (unsigned long) == 4);
unsigned long endian_check;
is.read ( (char *) & endian_check, 4);
checkread (is, 4);
BlChar caux [4];
is.read ( (char *) caux, 4);
checkread (is, 4);
unsigned long newsize= peek32 (caux);
size_t newblock= blockrounded (newsize);
util::auto_alloc <BlChar> newprog (newblock);
is.read (reinterpret_cast <char *> (newprog.data () ),
newsize);
checkread (is, newsize);
renew ();
program= newprog;
newprog.release ();
size= newsize;
}
void Program::Internal::load (const std::string & name)
{
clear_cache ();
std::ifstream (is);
openblassicprogram (is, name);
if (! isblassicbinary (is) )
{
renew ();
loadtext (is);
}
else
{
loadbinary (is);
}
}
void Program::Internal::merge (const std::string & name)
{
clear_cache ();
std::ifstream is;
openblassicprogram (is, name);
if (! isblassicbinary (is) )
{
loadtext (is);
}
else
{
Program::Internal inload;
inload.loadbinary (is);
for (CodeLine line= inload.getfirstline ();
line.number () != 0;
//line= inload.getnextline (line)
inload.getnextline (line)
)
{
insert (line);
}
}
}
void Program::Internal::renew ()
{
size= 0;
clear_cache ();
if (program)
{
free (program);
program= 0;
}
}
namespace {
typedef MAP <BlLineNumber, BlLineNumber> MapLine;
void showmappedline (const MapLine::value_type & linepair)
{
cerr << linepair.first << " mappped to " << linepair.second << endl;
}
bool iscodewithnumber (BlCode code)
{
return (code == keyGOTO || code == keyGOSUB || code == keyRUN ||
code == keyRESTORE || code == keyRESUME ||
code == keyDELETE || code == keyLIST ||
code == keyEDIT ||
code == keyTHEN || code == keyELSE);
}
void changeline (CodeLine & line, const MapLine & mapline)
{
const BlLineLength l= line.length ();
BlChar * s= line.content ();
BlLineLength p= 0;
BlChar c;
while (p < l)
{
c= s [p];
if (iskey (c) )
{
BlCode code= BlCode ( (BlCode (c) << 8 ) ) |
BlCode (s [p+1] );
p+= 2;
//cerr << "Key " << decodekeyword (code) << flush;
if (iscodewithnumber (code) )
{
//cerr << " analyzing" << flush;
for (;;)
{
while (p < l && isspace (s [p] ) )
++p;
if (p >= l)
break;
c= s [p];
if (c == INTEGER_PREFIX)
{
BlLineNumber old= getLineNumber
(s + p + 1);
//cerr << " Find " << old <<
// flush;
MapLine::const_iterator it=
mapline.find (old);
if (it != mapline.end () )
{
//cerr << " Changed " <<
// it->second <<
// flush;
setLineNumber
(s + p + 1,
it->second);
}
p+= 1 + sizeof (BlInteger);
}
else if (c == ':')
{
++p;
break;
}
else if (c == '"')
{
while (s [++p] != '\0')
continue;
++p;
}
else if (iskey (c) )
p+= 2;
else if (c == '\'')
{
p= l;
break;
}
else ++p;
}
//cerr << endl;
}
//else cerr << endl;
}
else if (c == INTEGER_PREFIX)
p+= 1 + sizeof (BlInteger);
else if (c == '"')
{
while (s [++p] != '\0')
continue;
++p;
}
else if (c == '\'')
break;
else ++p;
}
}
}
void Program::Internal::renum (BlLineNumber blnNew, BlLineNumber blnOld,
BlLineNumber blnInc)
{
clear_cache ();
Position pos= 0;
MapLine mapline;
// Find first line to renum.
BlLineNumber previous= 0;
while (pos < size && numline (pos) < blnOld)
{
previous= numline (pos);
//cerr << "Skipping line " << previous << endl;
pos= nextline (pos);
}
if (previous >= blnNew)
throw ErrMismatch;
// Change the line numbers.
BlLineNumber actual;
BlLineNumber blnMax= BlMaxLineNumber - blnInc;
bool overflow= false;
for ( ; pos < size; pos= nextline (pos) )
{
actual= numline (pos);
if (actual != blnNew)
{
if (overflow)
throw ErrLineExhausted;
mapline [actual]= blnNew;
//setLineNumber (program + pos, blnNew);
}
if (blnNew > blnMax)
overflow= true;
else
blnNew+= blnInc;
}
//for_each (mapline.begin (), mapline.end (), showmappedline);
// Change refereneces to lines.
MapLine::iterator it, mapend= mapline.end ();
CodeLine line;
for (pos= 0; pos < size; pos= nextline (pos) )
{
actual= numline (pos);
getlineinpos (pos, line);
//cerr << "Exploring line " << actual << endl;
it= mapline.find (actual);
if (it != mapend)
{
//cerr << "Changing line " << actual <<
// " by " << it->second << endl;
setLineNumber (program + pos, it->second);
}
changeline (line, mapline);
}
}
//**********************************************************
// Program
//**********************************************************
Program::Program () :
pin (new Internal)
{
}
Program::~Program ()
{
delete pin;
}
BlChar * Program::programptr ()
{
return pin->programptr ();
}
BlLineNumber Program::getlabel (const std::string & str)
{
return pin->getlabel (str);
}
CodeLine Program::getfirstline ()
{
return pin->getfirstline ();
}
//CodeLine Program::getnextline (CodeLine & line)
void Program::getnextline (CodeLine & line)
{
//return pin->getnextline (line);
pin->getnextline (line);
}
#if 0
BlLineNumber Program::getnextnum (CodeLine & line)
{
return pin->getnextnum (line);
}
#endif
#if 0
CodeLine Program::getline (BlLineNumber num)
{
return pin->getline (num);
}
#endif
void Program::getline (BlLineNumber num, CodeLine & line)
{
pin->getline (num, line);
}
void Program::getline (ProgramPos pos, CodeLine & line)
{
BlLineNumber n= pos.getnum ();
pin->getline (n, line);
if (line.number () == n)
{
BlChunk ch= pos.getchunk ();
if (ch != 0)
line.gotochunk (ch);
}
}
void Program::insert (const CodeLine & code)
{
pin->insert (code);
}
void Program::deletelines (BlLineNumber iniline, BlLineNumber endline)
{
pin->deletelines (iniline, endline);
}
void Program::list (BlLineNumber iniline, BlLineNumber endline,
BlFile & out) const
{
pin->list (iniline, endline, out);
}
void Program::save (const std::string & name) const
{
pin->save (name);
}
void Program::load (const std::string & name)
{
pin->load (name);
}
void Program::merge (const std::string & name)
{
pin->merge (name);
}
void Program::renew ()
{
pin->renew ();
}
void Program::renum (BlLineNumber blnNew, BlLineNumber blnOld,
BlLineNumber blnInc)
{
pin->renum (blnNew, blnOld, blnInc);
}
// Fin de program.cpp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -