Skip to content

Commit f276025

Browse files
committed
Add support for multiple paths for searching compiler files.
This also adds support for the `FASTBASIC_HOME` environment variable, fixes #67.
1 parent 6366fcc commit f276025

6 files changed

Lines changed: 93 additions & 19 deletions

File tree

compiler/USAGE.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,12 @@ The compilation is a three step process:
8989

9090
- The compiler calls the `CA65` assembler to produce an object file.
9191

92-
- The compiler calls the `LD65` linker to join the object file with the runtime library, generating the `XEX`, `ROM` or `BIN` depending on the target.
92+
- The compiler calls the `LD65` linker to join the object file with the runtime
93+
library, generating the `XEX`, `ROM` or `BIN` depending on the target.
94+
95+
- To search the target, syntax, libraries and other tools, the compiler
96+
searches in the installation path and in the path in the `FASTBASIC_HOME`
97+
environment variable.
9398

9499

95100
Advanced Usage
@@ -187,11 +192,18 @@ an `:` or an `=` to separate the option from the argument.
187192
target will produce a 16kB cartridge binary instead of the 32kB default.
188193

189194
- **-target-path**:*path*
190-
Sets the path where the target definition files are searched. The default is
191-
to search in the same folder as the compiler executable.
195+
Sets the list of paths where the target definition files are searched, as a
196+
list of folder names separated by `:`.
197+
198+
The default is to search in the same folder as the compiler executable, and
199+
in the path in the `FASTBASIC_HOME` environment variable.
192200

193201
- **-syntax-path**:*path*
194-
Sets the path where the syntax grammar files are searched.
202+
Sets the list of paths where the syntax grammar files are searched, as a list
203+
of folder names separated by `:`.
204+
205+
The default path is the same as the target path with `syntax` folder at the
206+
end.
195207

196208
- **-keep**
197209
Do not remove the intermediate files on compilation.

src/compiler/main.cc

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,32 @@ static std::string to_lower(std::string in)
7575
return ret;
7676
}
7777

78+
// Parse path list into a vector of strings
79+
static std::vector<std::string> parse_path_list(const std::string &str)
80+
{
81+
std::vector<std::string> ret;
82+
size_t pos = 0;
83+
while(1)
84+
{
85+
auto nxt = str.find(':', pos);
86+
if(nxt == str.npos)
87+
{
88+
ret.emplace_back(str.substr(pos));
89+
return ret;
90+
}
91+
ret.emplace_back(str.substr(pos, nxt - pos));
92+
pos = nxt + 1;
93+
}
94+
}
95+
7896
int main(int argc, char **argv)
7997
{
8098
// OS specific initializations
8199
os::init(argv[0]);
82100

83101
// Default folders for target and syntax files
84-
auto syntax_folder = os::compiler_path("syntax");
85-
auto target_folder = os::compiler_path("");
102+
auto syntax_folder = os::get_search_path("syntax");
103+
auto target_folder = os::get_search_path("");
86104
std::vector<std::string> args(argv + 1, argv + argc);
87105
std::string out_name;
88106
std::string exe_name;
@@ -217,11 +235,11 @@ int main(int argc, char **argv)
217235
}
218236
else if(arg.rfind("-syntax-path:", 0) == 0 || arg.rfind("-syntax-path=", 0) == 0)
219237
{
220-
syntax_folder = arg.substr(13);
238+
syntax_folder = parse_path_list(arg.substr(13));
221239
}
222240
else if(arg.rfind("-target-path:", 0) == 0 || arg.rfind("-target-path=", 0) == 0)
223241
{
224-
target_folder = arg.substr(13);
242+
target_folder = parse_path_list(arg.substr(13));
225243
}
226244
else if(arg[0] == '-')
227245
return show_error("invalid option '" + arg + "', try -h for help");

src/compiler/os.cc

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// os.cc: Host OS functions
2020
#include "os.h"
2121
#include <memory>
22+
#include <sys/stat.h>
2223

2324
#ifdef _WIN32
2425
#include <windows.h>
@@ -33,7 +34,7 @@ static const char *path_sep = "\\/";
3334
static const char *path_sep = "/";
3435
#endif
3536

36-
static std::string compiler_search_path;
37+
static std::vector<std::string> compiler_search_path;
3738

3839
bool os::path_absolute(const std::string &path)
3940
{
@@ -110,13 +111,49 @@ void os::init(const std::string &prog)
110111
#else
111112
// No init needed.
112113
#endif
113-
// Store out program name
114-
compiler_search_path = dir_name(prog);
114+
// Initialize the compiler search path:
115+
// The FASTBASIC_HOME environment variable:
116+
const char *env = getenv("FASTBASIC_HOME");
117+
if(env)
118+
compiler_search_path.emplace_back(env);
119+
// The directory of the invoked program
120+
compiler_search_path.emplace_back(dir_name(prog));
121+
// And on Linux systems, the instalation path
122+
#ifndef _WIN32
123+
compiler_search_path.emplace_back("/usr/local/share/fastbasic");
124+
compiler_search_path.emplace_back("/usr/share/fastbasic");
125+
#endif
126+
}
127+
128+
std::string os::search_path(const std::vector<std::string> &paths,
129+
const std::string &filename)
130+
{
131+
// Check each possible path:
132+
for(auto &path : paths)
133+
{
134+
struct stat st;
135+
auto f = full_path(path, filename);
136+
auto e = stat(f.c_str(), &st);
137+
if(0 == e)
138+
return f;
139+
}
140+
// Not found, return only file name
141+
return filename;
115142
}
116143

117144
std::string os::compiler_path(const std::string &filename)
118145
{
119-
return full_path(compiler_search_path, filename);
146+
return search_path(compiler_search_path, filename);
147+
}
148+
149+
std::vector<std::string> os::get_search_path(const std::string &filename)
150+
{
151+
if(filename.empty())
152+
return compiler_search_path;
153+
std::vector<std::string> ret;
154+
for(auto &path : compiler_search_path)
155+
ret.emplace_back(full_path(path, filename));
156+
return ret;
120157
}
121158

122159
int os::prog_exec(std::string exe, std::vector<std::string> &args)

src/compiler/os.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,16 @@
2424

2525
namespace os
2626
{
27+
// Returns the current compiler search path for the given base
28+
std::vector<std::string> get_search_path(const std::string &filename);
2729
// Locates a file or folder in the compiler data and
2830
// returns the path
2931
std::string compiler_path(const std::string &filename);
3032
// Appends a file name to a path
3133
std::string full_path(const std::string &path, const std::string &filename);
34+
// Search a file in a list of paths
35+
std::string search_path(const std::vector<std::string> &paths,
36+
const std::string &filename);
3237
// Returns the file name from a full path
3338
std::string file_name(const std::string &path);
3439
// Returns the directory name from a full path

src/compiler/target.cc

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
class target_file
3232
{
3333
public:
34-
std::string target_folder;
34+
std::vector<std::string> target_path;
3535
std::vector<std::string> slist;
3636
std::vector<std::string> ca65_args;
3737
std::string lib_name;
3838
std::string cfg_name;
3939
std::string bin_ext;
40-
target_file(std::string target_folder) : target_folder(target_folder) {}
40+
target_file(std::vector<std::string> target_path) : target_path(target_path) {}
4141
void read_file(std::string fname);
4242
};
4343

@@ -61,7 +61,7 @@ void target_file::read_file(std::string fname)
6161
fname = os::add_extension(fname, ".tgt");
6262

6363
if(!os::path_absolute(fname))
64-
fname = os::full_path(target_folder, fname);
64+
fname = os::search_path(target_path, fname);
6565

6666
std::ifstream f;
6767
f.open(fname);
@@ -127,10 +127,11 @@ void target_file::read_file(std::string fname)
127127

128128
target::target() {}
129129

130-
void target::load(std::string target_folder, std::string syntax_folder, std::string fname)
130+
void target::load(std::vector<std::string> target_path,
131+
std::vector<std::string> syntax_path, std::string fname)
131132
{
132133
// Read target file
133-
target_file f(target_folder);
134+
target_file f(target_path);
134135
f.read_file(fname);
135136
lib_name = f.lib_name;
136137
cfg_name = f.cfg_name;
@@ -143,7 +144,7 @@ void target::load(std::string target_folder, std::string syntax_folder, std::str
143144
for(auto &name : f.slist)
144145
{
145146
std::ifstream ifile;
146-
ifile.open(os::full_path(syntax_folder, name));
147+
ifile.open(os::search_path(syntax_path, name));
147148
if(!ifile.is_open())
148149
throw std::runtime_error("can't open syntax file: '" + name + "'");
149150
auto data = pre.read_input(ifile);

src/compiler/target.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class target
3939

4040
public:
4141
target();
42-
void load(std::string target_folder, std::string syntax_folder, std::string fname);
42+
void load(std::vector<std::string> target_folder,
43+
std::vector<std::string> syntax_folder, std::string fname);
4344
const syntax::sm_list &sl() const { return s; }
4445
std::string lib() const { return lib_name; }
4546
std::string cfg() const { return cfg_name; }

0 commit comments

Comments
 (0)