mirror of
https://github.com/marketideas/qasm.git
synced 2024-12-28 06:29:58 +00:00
742 lines
12 KiB
C++
742 lines
12 KiB
C++
#pragma once
|
|
#include "qasm.h"
|
|
|
|
using namespace Poco;
|
|
|
|
#define ENV_QASM "QASM_BASE"
|
|
|
|
#define MAX_PREFIX 32
|
|
|
|
#define MODE_6502 0
|
|
#define MODE_65C02 1
|
|
#define MODE_65816 2
|
|
|
|
#define SYNTAX_MERLIN 0x01
|
|
#define SYNTAX_MERLIN16 0x02
|
|
#define SYNTAX_MERLIN16PLUS 0x04
|
|
#define SYNTAX_MERLIN32 0x08
|
|
#define SYNTAX_APW 0x10
|
|
#define SYNTAX_MPW 0x20
|
|
#define SYNTAX_ORCA 0x40
|
|
#define SYNTAX_CC65 0x80
|
|
#define SYNTAX_LISA 0x100
|
|
#define SYNTAX_QASM (0x200 | SYNTAX_MERLIN)
|
|
|
|
#define OPTION_ALLOW_A_OPERAND 0x0100
|
|
#define OPTION_ALLOW_LOCAL 0x0200
|
|
#define OPTION_ALLOW_COLON 0x0400
|
|
#define OPTION_FORCE_REPSEP 0x0800
|
|
#define OPTION_NO_REPSEP 0x1000
|
|
#define OPTION_CFG_REPSEP 0x2000
|
|
#define OPTION_M32_VARS 0x4000
|
|
#define OPTION_M16_PLUS 0x8000
|
|
|
|
enum
|
|
{
|
|
syn_err = -1, // error - not recognized
|
|
syn_none = 0, // should never be returned 0
|
|
syn_implied, // no operand 1
|
|
syn_s, // expr,s 2
|
|
syn_sy, // (expr,s),y 3
|
|
syn_imm, // #expr 4
|
|
syn_diix, // (expr,x) 5
|
|
syn_diiy, // (expr),y 6
|
|
syn_di, // (expr) 7
|
|
syn_iyl, // [expr],y 8
|
|
syn_dil, // [expr] 9
|
|
syn_absx, // expr,x 10
|
|
syn_absy, // expr,y 11
|
|
syn_bm, // block move 12
|
|
syn_abs, // expr 13
|
|
|
|
syn_MAX
|
|
};
|
|
|
|
|
|
class myLayeredConfiguration : public Poco::Util::LayeredConfiguration
|
|
{
|
|
public:
|
|
myLayeredConfiguration() : Poco::Util::LayeredConfiguration() {};
|
|
~myLayeredConfiguration() {};
|
|
};
|
|
|
|
#undef CLASS
|
|
#define CLASS ConfigOptions
|
|
class CLASS
|
|
{
|
|
protected:
|
|
//vector<shared_ptr<JSONConfiguration>> configs;
|
|
vector<std::string> valid_files;
|
|
public:
|
|
//Poco::JSON::Parser parser;
|
|
//string jsonin;
|
|
//Dynamic::Var jsonobj=NULL;
|
|
uint16_t format_flags;
|
|
|
|
uint16_t cpu_mode;
|
|
string language;
|
|
uint16_t langlevel;
|
|
string prefixes[MAX_PREFIX];
|
|
|
|
uint8_t start_mx;
|
|
bool start_listmode;
|
|
bool listmode;
|
|
|
|
bool casesen;
|
|
bool showmx;
|
|
bool allowDuplicate;
|
|
bool trackrep;
|
|
bool merlinerrors;
|
|
bool m32vars;
|
|
bool allowA;
|
|
bool allowLocal;
|
|
bool allowColon;
|
|
bool oldevaluation;
|
|
int16_t linebytes;
|
|
int16_t overflowbytes;
|
|
|
|
myLayeredConfiguration *config=NULL;
|
|
|
|
bool usecolor;
|
|
|
|
CLASS()
|
|
{
|
|
language="";
|
|
setEnvironment();
|
|
clear();
|
|
setDefaults();
|
|
setLanguage("QASM",true);
|
|
setCurrent();
|
|
}
|
|
~CLASS()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
if (config!=NULL)
|
|
{
|
|
delete config;
|
|
config=NULL;
|
|
}
|
|
config=new myLayeredConfiguration();
|
|
valid_files.clear();
|
|
|
|
}
|
|
|
|
bool useColor(void)
|
|
{
|
|
bool res=false;
|
|
if (PAL::getBool("option.color",false))
|
|
{
|
|
res=true;
|
|
}
|
|
if ((!isatty(STDOUT_FILENO)) || (0))
|
|
{
|
|
res=false;
|
|
}
|
|
|
|
return(res);
|
|
}
|
|
bool isQuiet(void)
|
|
{
|
|
bool res;
|
|
res=PAL::getBool("option.quiet",false);
|
|
if (isDebug()>0)
|
|
{
|
|
res=false;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
bool isList(void)
|
|
{
|
|
bool res;
|
|
res=PAL::getBool("option.list",false);
|
|
//printf("list: %d\n",res);
|
|
return(res);
|
|
}
|
|
|
|
int printDefaults(string lang)
|
|
{
|
|
int res=-1;
|
|
string s;
|
|
int i;
|
|
string l=Poco::toUpper(lang);
|
|
if (l=="")
|
|
{
|
|
l=Poco::toUpper(language);
|
|
}
|
|
if (l!="")
|
|
{
|
|
setLanguage(l,false);
|
|
setCurrent();
|
|
printf("Defaults for language (%s)\n",language.c_str());
|
|
printf("\t\tLanguage:\t\t\t%s\n",language.c_str());
|
|
printf("\t\tlanguageLevel:\t\t\t%d\n",langlevel);
|
|
s="<unknown>";
|
|
switch(cpu_mode)
|
|
{
|
|
case 0:
|
|
s="M6502";
|
|
break;
|
|
case 1:
|
|
s="M65C02";
|
|
break;
|
|
case 2:
|
|
s="M65816";
|
|
break;
|
|
}
|
|
printf("\t\tcpu_mode:\t\t\t%s\n",s.c_str());
|
|
printf("\t\tstart_mx:\t\t\t%%%d%d\n",start_mx&0x02?1:0,start_mx&0x01?1:0);
|
|
//printf("\t\tstart_mx:\t\t\t%d\n",start_mx);
|
|
printf("\t\tPrefixes:\n");
|
|
|
|
for (i=0; i<MAX_PREFIX; i++)
|
|
{
|
|
if (prefixes[i].length()>0)
|
|
{
|
|
printf("\t\t\t%2d:\t%s\n",i,prefixes[i].c_str());
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
for (unsigned long ii=0; ii<valid_files.size(); ii++)
|
|
{
|
|
if (prefixes[ii].length()>0)
|
|
{
|
|
printf("\t\tSettings files read: \t%s\n",valid_files[ii].c_str());
|
|
}
|
|
}
|
|
//uint16_t format_flags;
|
|
|
|
|
|
//bool start_listmode;
|
|
//bool listmode;
|
|
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
string getAppPath()
|
|
{
|
|
char buff[PATH_MAX+1];
|
|
char *x;
|
|
|
|
string res="";
|
|
res=Poco::Util::Application::instance().commandPath();
|
|
x=realpath(res.c_str(),buff);
|
|
if (x!=NULL)
|
|
{
|
|
res=buff;
|
|
}
|
|
else
|
|
{
|
|
res="";
|
|
}
|
|
return(res);
|
|
}
|
|
int ReadFile(string path, bool backtrack)
|
|
{
|
|
//int levels=0;
|
|
bool done=false;
|
|
int ret=-1;
|
|
unsigned long ii;
|
|
Poco::Util::JSONConfiguration *jc;
|
|
|
|
while(!done)
|
|
{
|
|
Poco::Path pp(path);
|
|
//pp=pp.absolute(Poco::Path("/"));
|
|
pp=pp.absolute();
|
|
|
|
std::string basename=pp.getFileName();
|
|
|
|
Poco::File pf(pp);
|
|
if (isDebug()>1)
|
|
{
|
|
//pf.
|
|
printf(" %d parmsfile: %s ",backtrack,pf.path().c_str());
|
|
}
|
|
if ((pf.exists()) && (pf.canRead()) && ((pf.isFile()) || (pf.isLink())))
|
|
{
|
|
if (isDebug()>1)
|
|
{
|
|
printf("...found!\n");
|
|
}
|
|
//printf("OK: %s\n",pp.toString().c_str());
|
|
done=false;
|
|
for (ii=0; ii<valid_files.size(); ii++)
|
|
{
|
|
if (pf.path()==valid_files[ii])
|
|
{
|
|
done=true;
|
|
}
|
|
}
|
|
if (!done)
|
|
{
|
|
done=true; // we found a valid file
|
|
|
|
jc=new Poco::Util::JSONConfiguration();
|
|
//Poco::FileInputStream fs(path);
|
|
//Poco::StreamCopier::copyToString(fs,jsonin);
|
|
//parser.reset();
|
|
//parser.setAllowComments(true);
|
|
//jsonobj=parser.parse(jsonin);
|
|
if (jc!=NULL)
|
|
{
|
|
bool success=false;
|
|
try
|
|
{
|
|
jc->load(pp.toString());
|
|
success=true;
|
|
}
|
|
catch(...)
|
|
{
|
|
success=false;
|
|
}
|
|
if (success)
|
|
{
|
|
//configs.push_back(shared_ptr<JSONConfiguration>(jc));
|
|
config->add(jc);
|
|
valid_files.push_back(pp.toString());
|
|
ret=0;
|
|
}
|
|
else
|
|
{
|
|
delete jc;
|
|
jc=NULL;
|
|
printf("...unable to load/parts file: %s\n",pp.toString().c_str());
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (isDebug()>1)
|
|
{
|
|
printf("...not found\n");
|
|
}
|
|
}
|
|
if (!backtrack)
|
|
{
|
|
done=true;
|
|
}
|
|
|
|
if (!done)
|
|
{
|
|
//string ss=pp.current();
|
|
string ss=pp.toString();
|
|
pp=pp.popDirectory();
|
|
string ss1=pp.toString();
|
|
|
|
//printf("|%s| |%s|\n",ss.c_str(),ss1.c_str());
|
|
//assert(0);
|
|
path=ss1;
|
|
pp=Path(path);
|
|
if (path=="/")
|
|
{
|
|
done=true;
|
|
}
|
|
//path=path+"/"+basename;
|
|
}
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
bool isMerlin32(void)
|
|
{
|
|
bool res=false;
|
|
if (language=="MERLIN32")
|
|
{
|
|
res=true;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
bool isMerlin(void)
|
|
{
|
|
bool res=false;
|
|
if (language=="MERLIN")
|
|
{
|
|
res=true;
|
|
}
|
|
return(res);
|
|
}
|
|
bool isNative(void) // use this as we are running in 'native/qasm' mode so we can add special options
|
|
{
|
|
bool res=false;
|
|
if (language=="QASM")
|
|
{
|
|
res=true;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
bool isMerlinCompat()
|
|
{
|
|
bool res=false;
|
|
string s=language;
|
|
if (s=="QASM")
|
|
{
|
|
return(true);
|
|
}
|
|
bool b=s.find("MERLIN"); // any of the merlin varieties
|
|
if (b)
|
|
{
|
|
res=true;
|
|
return(res);
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
bool isMerlin16(void)
|
|
{
|
|
bool res=false;
|
|
if (language=="MERLIN16")
|
|
{
|
|
res=true;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
bool isMerlin16plus(void)
|
|
{
|
|
bool res=false;
|
|
if (language=="MERLIN16PLUS")
|
|
{
|
|
res=true;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
void setEnvironment()
|
|
{
|
|
string s="";
|
|
//s=Poco::Environment::get("QASM");
|
|
if (!Poco::Environment::has(ENV_QASM))
|
|
{
|
|
s=Poco::Util::Application::instance().commandPath();
|
|
Poco::Path pp(getAppPath());
|
|
pp=pp.absolute(Poco::Path());
|
|
//pp=pp.absolute(Poco::Path("/"));
|
|
s=pp.toString();
|
|
//printf("program: %s\n",s.c_str());
|
|
Poco::Environment::set(ENV_QASM,s);
|
|
}
|
|
}
|
|
string formatPath(string p)
|
|
{
|
|
string res=p;
|
|
string s;
|
|
Poco::Path pp(p);
|
|
s=pp.expand(pp.toString()); // replace environment variable references
|
|
pp=Poco::Path(s);
|
|
if (s!="")
|
|
{
|
|
|
|
Poco::StringTokenizer toks(s,"/");
|
|
if (toks.count()>0)
|
|
{
|
|
uint32_t n;
|
|
bool success=false;
|
|
try
|
|
{
|
|
n=Poco::NumberParser::parseUnsigned(toks[0]);
|
|
if (n<MAX_PREFIX)
|
|
{
|
|
success=true;
|
|
}
|
|
}
|
|
catch(const std::exception& e)
|
|
{
|
|
success=false;
|
|
}
|
|
if (success)
|
|
{
|
|
s=s.substr(toks[0].length(),s.length());
|
|
s=prefixes[n]+s;
|
|
pp=Poco::Path(s);
|
|
}
|
|
}
|
|
|
|
//pp=pp.absolute(Poco::Path("/"));
|
|
pp=pp.absolute();
|
|
res=pp.toString();
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
void setCurrent(void)
|
|
{
|
|
char buff[1024];
|
|
string s,n;
|
|
int i;
|
|
|
|
start_mx=GetInteger("asm.start_mx",3);
|
|
for (i=0; i<MAX_PREFIX; i++)
|
|
{
|
|
sprintf(buff,"general.prefix[%d].%d",i,i);
|
|
n=buff;
|
|
n=GetString(n,"");
|
|
n=formatPath(n);
|
|
prefixes[i]=n;
|
|
}
|
|
s=GetString("asm.cpu","M6502");
|
|
if (s=="M6502")
|
|
{
|
|
cpu_mode=MODE_6502;
|
|
}
|
|
else if (s=="M65C02")
|
|
{
|
|
cpu_mode=MODE_65C02;
|
|
}
|
|
else if (s=="M65816")
|
|
{
|
|
cpu_mode=MODE_65816;
|
|
}
|
|
else
|
|
{
|
|
printf("unknown cpu_mode in settings (%s) [M6502, M65C02, M65816]\n",s.c_str());
|
|
cpu_mode=MODE_6502;
|
|
}
|
|
|
|
allowDuplicate=GetBool("asm.allowduplicate",false);
|
|
}
|
|
void setDefaults(void)
|
|
{
|
|
cpu_mode=MODE_6502;
|
|
language="QASM";
|
|
langlevel=0;
|
|
for (int i=0; i<MAX_PREFIX; i++)
|
|
{
|
|
prefixes[i]="";
|
|
}
|
|
start_mx=0x03;
|
|
start_listmode=true;
|
|
listmode=start_listmode;
|
|
casesen=true;
|
|
showmx=true;
|
|
allowDuplicate=false;
|
|
trackrep=false;
|
|
merlinerrors=true;
|
|
m32vars=false;
|
|
|
|
allowA=true;
|
|
allowLocal=false;
|
|
allowColon=false;
|
|
oldevaluation=true;
|
|
linebytes=4;
|
|
overflowbytes=6;
|
|
usecolor=true;
|
|
}
|
|
|
|
void setLanguage(string lang, bool force)
|
|
{
|
|
//printf("request language options to %s from %s\n",lang.c_str(),language.c_str());
|
|
|
|
string old=language;
|
|
string pn=Poco::toUpper(lang);
|
|
if ((old!=pn) || (force))
|
|
{
|
|
//printf("setting language options to %s\n",pn.c_str());
|
|
language=pn;
|
|
setCurrent();
|
|
if (pn=="QASM")
|
|
{
|
|
setQASM();
|
|
}
|
|
}
|
|
}
|
|
string convertLanguage(string lang)
|
|
{
|
|
string res;
|
|
res=lang;
|
|
res=trim(res);
|
|
res=toUpper(res);
|
|
if (res=="MERLIN16+")
|
|
{
|
|
res="MERLIN16PLUS";
|
|
}
|
|
if (res=="MERLIN8")
|
|
{
|
|
res="MERLIN";
|
|
}
|
|
|
|
return(res);
|
|
}
|
|
bool supportedLanguage(string lang)
|
|
{
|
|
bool res=false;
|
|
string r=toUpper(lang);
|
|
r=trim(r);
|
|
|
|
r=trim(r);
|
|
if (r=="MERLIN")
|
|
{
|
|
res=true;
|
|
}
|
|
else if (r=="MERLIN8")
|
|
{
|
|
res=true;
|
|
}
|
|
else if (r=="MERLIN16")
|
|
{
|
|
res=true;
|
|
}
|
|
else if (r=="MERLIN16PLUS")
|
|
{
|
|
res=true;
|
|
}
|
|
else if (r=="MERLIN16+")
|
|
{
|
|
res=true;
|
|
}
|
|
else if (r=="MERLIN32")
|
|
{
|
|
res=true;
|
|
}
|
|
else if (r=="QASM")
|
|
{
|
|
res=true;
|
|
}
|
|
|
|
return(res);
|
|
}
|
|
void setQASM()
|
|
{
|
|
|
|
}
|
|
|
|
bool GetBool(string name, bool def)
|
|
{
|
|
bool res=def;
|
|
try
|
|
{
|
|
res=config->getBool(name);
|
|
|
|
//Dynamic::Var jresult=GetObject(name);
|
|
//if (!jresult.isEmpty())
|
|
//{
|
|
// if (jresult.isArray())
|
|
// {
|
|
|
|
// }
|
|
// else if (jresult.isBoolean())
|
|
// {
|
|
// res=jresult;
|
|
// }
|
|
//}
|
|
}
|
|
catch(...)
|
|
{
|
|
res=def;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
string GetString(string name, string def)
|
|
{
|
|
string res=def;
|
|
try
|
|
{
|
|
res=config->getString(name);
|
|
}
|
|
catch(...)
|
|
{
|
|
res=def;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
int32_t GetInteger(string name, int32_t def)
|
|
{
|
|
int32_t res=def;
|
|
|
|
#if 0
|
|
std::vector<std::string> keys;
|
|
config->keys(keys);
|
|
for (unsigned int i=0; i<keys.size(); i++)
|
|
{
|
|
printf("key[%d]: %s\n",i,keys[i].c_str());
|
|
}
|
|
#endif
|
|
|
|
try
|
|
{
|
|
res=config->getInt(name);
|
|
}
|
|
catch(...)
|
|
{
|
|
res=def;
|
|
//throw;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
string addrModeEnglish(int mode)
|
|
{
|
|
string res="<none>";
|
|
switch(mode)
|
|
{
|
|
case syn_err:
|
|
res="error";
|
|
break;
|
|
case syn_none:
|
|
res="<none>";
|
|
break;
|
|
case syn_implied:
|
|
res="impl";
|
|
break;
|
|
case syn_s:
|
|
res="dp,s";
|
|
break;
|
|
case syn_sy:
|
|
res="(dp,s),y";
|
|
break;
|
|
case syn_imm:
|
|
res="#imme";
|
|
break;
|
|
case syn_diix:
|
|
res="(dp,x)";
|
|
break;
|
|
case syn_diiy:
|
|
res="(dp),y";
|
|
break;
|
|
case syn_di:
|
|
res="(dp)";
|
|
break;
|
|
case syn_iyl:
|
|
res="[expr],y";
|
|
break;
|
|
case syn_dil:
|
|
res="[expr]";
|
|
break;
|
|
case syn_absx:
|
|
res="abs,x";
|
|
break;
|
|
case syn_absy:
|
|
res="abs,y";
|
|
break;
|
|
case syn_bm:
|
|
res="blkmv";
|
|
break;
|
|
case syn_abs:
|
|
res="abs";
|
|
break;
|
|
default:
|
|
res="unknown";
|
|
break;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
#undef CLASS |