Преглед изворни кода

progress

feature/dependency-graph
Martin Dørum пре 5 година
родитељ
комит
5341131447
6 измењених фајлова са 204 додато и 92 уклоњено
  1. 9
    0
      example-project/main.c
  2. 68
    67
      src/BBBParser.cc
  3. 6
    3
      src/BBBParser.h
  4. 3
    4
      src/SourceFile.cc
  5. 4
    0
      src/SourceFile.h
  6. 114
    18
      src/main.cc

+ 9
- 0
example-project/main.c Прегледај датотеку

#include <math.h>
#include <stdio.h>

//#bb ldflags := -lm
//#bb pkgs := libsdl cairo

int main() {
printf("sin(PI) is %f\n", sin(M_PI));
}

+ 68
- 67
src/BBBParser.cc Прегледај датотеку



std::string str; std::string str;
switch (peek()) { switch (peek()) {
case '{':
skip();
parseString(vars, str, '}');
skip('}');
appendVariableToArray(vars, str, values);
break;
default:
if (!parseIdentifier(str)) {
error("No identifier after $.");
}
case '{':
skip();
parseString(vars, str, '}');
skip('}');
appendVariableToArray(vars, str, values);
break;
default:
if (!parseIdentifier(str)) {
error("No identifier after $.");
}


appendVariableToArray(vars, str, values);
break;
appendVariableToArray(vars, str, values);
break;
} }
} }




std::string str; std::string str;
switch (peek()) { switch (peek()) {
case '{':
skip();
parseString(vars, str, '}');
skip('}');
appendVariableToString(vars, str, content);
break;

default:
if (!parseIdentifier(str)) {
error("No identifier after $.");
}
case '{':
skip();
parseString(vars, str, '}');
skip('}');
appendVariableToString(vars, str, content);
break;


appendVariableToString(vars, str, content);
break;
default:
if (!parseIdentifier(str)) {
error("No identifier after $.");
}

appendVariableToString(vars, str, content);
break;
} }
} }


int ch; int ch;
while ((ch = peek()) != EOF) { while ((ch = peek()) != EOF) {
switch (ch) { switch (ch) {
case EOF:
error("Unexpected EOF");
case EOF:
error("Unexpected EOF");


case '\\':
content.push_back(parseEscape());
break;
case '\\':
content.push_back(parseEscape());
break;


case '$':
parseQuotedExpansion(vars, content);
break;
case '$':
parseQuotedExpansion(vars, content);
break;


case '"':
skip();
return;
case '"':
skip();
return;


default:
content.push_back(get());
break;
default:
content.push_back(get());
break;
} }
} }
} }
} }


switch (ch) { switch (ch) {
case EOF:
return success;
case EOF:
return success;


case '\\':
content.push_back(parseEscape());
success = true;
break;
case '\\':
content.push_back(parseEscape());
success = true;
break;


case '$':
parseQuotedExpansion(vars, content);
success = true;
break;
case '$':
parseQuotedExpansion(vars, content);
success = true;
break;


case '"':
parseQuotedString(vars, content);
success = true;
break;
case '"':
parseQuotedString(vars, content);
success = true;
break;


default:
if (ch == ':' && peek2() == '=')
return success;
default:
if (ch == ':' && peek2() == '=')
return success;


content.push_back(get());
success = true;
break;
content.push_back(get());
success = true;
break;
} }
} }
} }
bool BBBParser::parseIdentifier(std::string &content) { bool BBBParser::parseIdentifier(std::string &content) {
int ch = peek(); int ch = peek();
if (!( if (!(
(ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch == '_'))) {
(ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch == '_'))) {
return false; return false;
} }


while (1) { while (1) {
ch = peek(); ch = peek();
if (!( if (!(
(ch >= '0' && ch <= '9') ||
(ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch == '_'))) {
(ch >= '0' && ch <= '9') ||
(ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch == '_'))) {
return true; return true;
} }


return; return;
} }


skipWhitespace();
Operator prevOper = readOperator(); Operator prevOper = readOperator();
if (prevOper == Operator::NONE) { if (prevOper == Operator::NONE) {
error("Expected operator."); error("Expected operator.");

+ 6
- 3
src/BBBParser.h Прегледај датотеку

void skip(char); void skip(char);
void skip() { get(); } void skip() { get(); }


int flags_;
int line_;
int ch_;
int line() const { return line_; }
int ch() const { return ch_; }


private: private:
enum class Operator { enum class Operator {
bool parseString(const Variables &vars, std::string &content, int sep = -1); bool parseString(const Variables &vars, std::string &content, int sep = -1);
bool parseIdentifier(std::string &content); bool parseIdentifier(std::string &content);



int flags_;
int line_;
int ch_;
std::istream &stream_; std::istream &stream_;
}; };

+ 3
- 4
src/SourceFile.cc Прегледај датотеку



static bool startsWith(BBBParser &parser, const char *str) { static bool startsWith(BBBParser &parser, const char *str) {
for (size_t i = 0; str[i] != '\0'; ++i) { for (size_t i = 0; str[i] != '\0'; ++i) {
if (parser.get() != str[i])
if (parser.peek() != str[i])
return false; return false;
parser.skip();
} }


return true; return true;
std::ifstream file(dir_ + "/" + name_); std::ifstream file(dir_ + "/" + name_);
BBBParser parser(file, BBBParser::FLAG_ONE_LINE); BBBParser parser(file, BBBParser::FLAG_ONE_LINE);


bool freshLine = true;
while (file.good()) { while (file.good()) {
if (freshLine && startsWith(parser, "//#bb")) {
if (startsWith(parser, "//#bb")) {
parser.parse(vars_); parser.parse(vars_);
} else { } else {
while (file.good() && parser.get() != '\n'); while (file.good() && parser.get() != '\n');
freshLine = true;
} }
} }
} }

+ 4
- 0
src/SourceFile.h Прегледај датотеку

public: public:
SourceFile(std::string dir, std::string name, BBBParser::Variables vars); SourceFile(std::string dir, std::string name, BBBParser::Variables vars);


const std::string &dir() const { return dir_; }
const std::string &name() const { return name_; }
const BBBParser::Variables &vars() const { return vars_; }

private: private:
std::string dir_; std::string dir_;
std::string name_; std::string name_;

+ 114
- 18
src/main.cc Прегледај датотеку

#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <getopt.h>
#include <dirent.h> #include <dirent.h>
#include <stdexcept> #include <stdexcept>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <fstream> #include <fstream>
#include <iostream>


#include "SourceFile.h" #include "SourceFile.h"
#include "BBBParser.h" #include "BBBParser.h"


void readDir(std::string dir, std::vector<SourceFile> &sources, BBBParser::Variables vars) {
static void readDir(std::string dir, std::vector<SourceFile> &sources,
BBBParser::Variables vars);

static void readPath(std::string dir, std::string name,
std::vector<SourceFile> &sources, BBBParser::Variables vars) {
std::string path = dir + "/" + name;
struct stat st;
if (stat(path.c_str(), &st) < 0) {
throw std::runtime_error("stat '" + path + "': " + strerror(errno));
}

if (S_ISDIR(st.st_mode)) {
// We don't want to send 'files'
BBBParser::Variables subvars = vars;
subvars.erase("files");
readDir(path, sources, std::move(subvars));
} else {
sources.emplace_back(dir, name, vars);
}
}

static void readDir(std::string dir, std::vector<SourceFile> &sources,
BBBParser::Variables vars) {
std::ifstream buildFile(dir + "/build.bbb"); std::ifstream buildFile(dir + "/build.bbb");
std::vector<std::string> files; std::vector<std::string> files;
bool hasFiles = false; bool hasFiles = false;


struct dirent *ent; struct dirent *ent;
while ((ent = readdir(d)) != NULL) { while ((ent = readdir(d)) != NULL) {
if (ent->d_name[0] == '.')
continue;
files.emplace_back(ent->d_name); files.emplace_back(ent->d_name);
} }


// Go through files // Go through files
for (auto &ent: files) { for (auto &ent: files) {
std::string path = dir + "/" + ent; std::string path = dir + "/" + ent;
struct stat st;
if (stat(path.c_str(), &st) < 0) {
throw std::runtime_error("stat '" + path + "': " + strerror(errno));
}
BBBParser::Variables subvars = vars;
readPath(dir, ent, sources, vars);
}
}


if (S_ISDIR(st.st_mode)) {
readDir(path, sources, vars);
} else {
sources.emplace_back(dir, ent, vars);
void printState(const std::vector<SourceFile> &sources) {
for (auto &source: sources) {
std::cout << source.dir() << '/' << source.name() << ":\n";
for (auto &kv: source.vars()) {
std::cout << " " << kv.first << ":\n";
for (auto &val: kv.second) {
std::cout << " " << val << '\n';
}
} }
} }
} }


int main(int argc, char **argv) { int main(int argc, char **argv) {
std::ifstream file("sample.bbb");
BBBParser parser(file, BBBParser::FLAG_NONE);
std::vector<std::string> srcDirs;
std::string outdir = "bbbuild";

enum class Action {
BUILD, PRINT_STATE,
};
Action action = Action::BUILD;


BBBParser::Variables vars;
parser.parse(vars);
const char *shortopts = "o:hp";
const struct option opts[] = {
{ "help", no_argument, NULL, 'h' },
{ "output", required_argument, NULL, 'o' },
{ "print-state", no_argument, NULL, 'p' },
{},
};


std::cout << "\nVariables found:\n";
for (auto &kv: vars) {
std::cout << kv.first << ":\n";
for (auto &val: kv.second) {
std::cout << "\t'" << val << "'\n";
const char usage[] =
"Usage: bbbuild [options...] [sources]\n"
"\n"
" -h, --help "
"Show this help text.\n"
" -o, --output <dir> "
"Set output directory.\n"
" -p, --print-state "
"Print the state instead of building.\n";

// Parse options from argv
while (1) {
int optidx;
int c = getopt_long(argc, argv, shortopts, opts, &optidx);

if (c < 0) {
break;
} }

switch (c) {
case 'h':
puts(usage);
return 0;

case 'o':
outdir = optarg;
break;

case 'p':
action = Action::PRINT_STATE;
break;

default:
printf("Unknown option: '%c'.\n%s", (char)c, usage);
break;
return 1;
}
}

// Parse non-opt argv as source dirs
if (optind < argc) {
while (optind < argc) {
srcDirs.push_back(argv[optind++]);
}
} else {
srcDirs.push_back(".");
}

// Read configs from source dirs
std::vector<SourceFile> sources;
for (std::string &dir: srcDirs) {
readDir(dir, sources, {});
}

switch (action) {
case Action::BUILD:
std::cerr << "Building is not implemented yet.\n";
abort();

case Action::PRINT_STATE:
printState(sources);
break;
} }
} }

Loading…
Откажи
Сачувај