qasm/qoptions.h

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