Last active
November 12, 2016 08:55
-
-
Save xerpi/eb49b34f7bc43f90194c0a16bbf0e623 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* vitajsonlinker by xerpi | |
* - ./vitajsonlinker db1.json [db2.json, ...] | |
*/ | |
#include <string> | |
#include <list> | |
#include <iostream> | |
#include <jansson.h> | |
typedef uint32_t vita_nid_t; | |
struct vita_function_t { | |
std::string name; | |
vita_nid_t nid; | |
}; | |
struct vita_variable_t { | |
std::string name; | |
vita_nid_t nid; | |
}; | |
struct vita_library_t { | |
std::string name; | |
vita_nid_t nid; | |
bool visibility; | |
std::list<vita_function_t> functions; | |
std::list<vita_variable_t> variables; | |
}; | |
struct vita_module_t { | |
std::string name; | |
vita_nid_t nid; | |
bool privilege; | |
std::list<vita_library_t> libraries; | |
}; | |
struct vita_exports_t { | |
std::list<vita_module_t> modules; | |
}; | |
void vita_exports_remove_empty(vita_exports_t &exports) | |
{ | |
for (std::list<vita_module_t>::iterator mod = exports.modules.begin(); mod != exports.modules.end(); ) { | |
for (std::list<vita_library_t>::iterator lib = mod->libraries.begin(); lib != mod->libraries.end(); ) { | |
if (lib->functions.size() == 0 && lib->variables.size() == 0) { | |
lib = mod->libraries.erase(lib); | |
continue; | |
} | |
lib++; | |
} | |
if (mod->libraries.size() == 0) { | |
mod = exports.modules.erase(mod); | |
continue; | |
} | |
mod++; | |
} | |
} | |
void vita_exports_sort(vita_exports_t &exports) | |
{ | |
std::list<vita_module_t>::iterator mod_it; | |
for (mod_it = exports.modules.begin(); mod_it != exports.modules.end(); mod_it++) { | |
std::list<vita_library_t>::iterator lib_it; | |
for (lib_it = mod_it->libraries.begin(); lib_it != mod_it->libraries.end(); lib_it++) { | |
lib_it->functions.sort([](const vita_function_t &a, const vita_function_t &b) { | |
return a.name < b.name; | |
}); | |
lib_it->variables.sort([](const vita_variable_t &a, const vita_variable_t &b) { | |
return a.name < b.name; | |
}); | |
} | |
mod_it->libraries.sort([](const vita_library_t &a, const vita_library_t &b) { | |
return a.name < b.name; | |
}); | |
} | |
exports.modules.sort([](const vita_module_t &a, const vita_module_t &b) { | |
return a.name < b.name; | |
}); | |
} | |
void vita_json_print(const vita_exports_t &exports) | |
{ | |
std::cout << "{" << std::endl; | |
std::list<vita_module_t>::const_iterator mod_it; | |
for (mod_it = exports.modules.begin(); mod_it != exports.modules.end(); mod_it++) { | |
std::cout << "\t\"" << mod_it->name << "\": {" << std::endl; | |
std::cout << "\t\t\"nid\": " << mod_it->nid << "," << std::endl; | |
std::cout << "\t\t\"" << "modules" << "\": {" << std::endl; | |
std::list<vita_library_t>::const_iterator lib_it; | |
for (lib_it = mod_it->libraries.begin(); lib_it != mod_it->libraries.end(); lib_it++) { | |
std::cout << "\t\t\t\"" << lib_it->name << "\": {" << std::endl; | |
std::cout << "\t\t\t\t\"kernel\": " << (lib_it->visibility ? "true" : "false") << "," << std::endl; | |
std::cout << "\t\t\t\t\"nid\": " << lib_it->nid << "," << std::endl; | |
std::cout << "\t\t\t\t\"" << "functions" << "\": {" << std::endl; | |
std::list<vita_function_t>::const_iterator func_it; | |
for (func_it = lib_it->functions.begin(); func_it != lib_it->functions.end(); func_it++) { | |
std::cout << "\t\t\t\t\t\"" << func_it->name << "\": " << func_it->nid; | |
if (func_it != std::prev(lib_it->functions.end())) | |
std::cout << ","; | |
std::cout << std::endl; | |
} | |
std::cout << "\t\t\t\t}" << std::endl; | |
std::cout << "\t\t\t}"; | |
if (lib_it != std::prev(mod_it->libraries.end())) | |
std::cout << ","; | |
std::cout << std::endl; | |
} | |
std::cout << "\t\t}" << std::endl; | |
std::cout << "\t}"; | |
if (mod_it != std::prev(exports.modules.end())) | |
std::cout << ","; | |
std::cout << std::endl; | |
} | |
std::cout << "}" << std::endl; | |
} | |
bool vita_json_load(vita_exports_t &exports, FILE *file, int verbose) | |
{ | |
json_t *libs, *lib_data; | |
json_error_t error; | |
const char *lib_name, *mod_name, *target_name; | |
libs = json_loadf(file, 0, &error); | |
if (libs == nullptr) { | |
fprintf(stderr, "error: on line %d: %s\n", error.line, error.text); | |
return false; | |
} | |
if (!json_is_object(libs)) { | |
fprintf(stderr, "error: modules is not an object\n"); | |
json_decref(libs); | |
return false; | |
} | |
int i, j, k; | |
i = -1; | |
json_object_foreach(libs, lib_name, lib_data) { | |
json_t *nid, *modules, *mod_data; | |
i++; | |
if (!json_is_object(lib_data)) { | |
fprintf(stderr, "error: library %s is not an object\n", lib_name); | |
json_decref(libs); | |
return false; | |
} | |
nid = json_object_get(lib_data, "nid"); | |
if (!json_is_integer(nid)) { | |
fprintf(stderr, "error: library %s: nid is not an integer\n", lib_name); | |
json_decref(libs); | |
return false; | |
} | |
modules = json_object_get(lib_data, "modules"); | |
if (!json_is_object(modules)) { | |
fprintf(stderr, "error: library %s: module is not an object\n", lib_name); | |
json_decref(libs); | |
return false; | |
} | |
std::string module_name = std::string(lib_name); | |
vita_nid_t module_nid = json_integer_value(nid); | |
std::list<vita_module_t>::iterator mod_it; | |
for (mod_it = exports.modules.begin(); mod_it != exports.modules.end(); mod_it++) { | |
if (mod_it->name.compare(module_name) == 0) { | |
/* | |
* If we have found the *real* NID, update | |
* the fake one (nids from 0 to a few hundreds). | |
*/ | |
if (mod_it->nid < 500 && module_nid > 500) | |
mod_it->nid = module_nid; | |
break; | |
} | |
} | |
if (mod_it == exports.modules.end()) { | |
vita_module_t module; | |
module.name = module_name; | |
module.nid = module_nid; | |
//module.visibility = ?; | |
exports.modules.push_back(module); | |
mod_it = std::prev(exports.modules.end()); | |
} | |
if (verbose) | |
printf("Lib: %s\n", lib_name); | |
j = -1; | |
json_object_foreach(modules, mod_name, mod_data) { | |
json_t *nid, *kernel, *functions, *variables, *target_nid; | |
bool has_variables = true; | |
j++; | |
if (!json_is_object(mod_data)) { | |
fprintf(stderr, "error: module %s is not an object\n", mod_name); | |
json_decref(libs); | |
return false; | |
} | |
nid = json_object_get(mod_data, "nid"); | |
if (!json_is_integer(nid)) { | |
fprintf(stderr, "error: module %s: nid is not an integer\n", mod_name); | |
json_decref(libs); | |
return false; | |
} | |
kernel = json_object_get(mod_data, "kernel"); | |
if (!json_is_boolean(kernel)) { | |
fprintf(stderr, "error: module %s: kernel is not a boolean\n", mod_name); | |
json_decref(libs); | |
return false; | |
} | |
functions = json_object_get(mod_data, "functions"); | |
if (!json_is_object(functions)) { | |
fprintf(stderr, "error: module %s: functions is not an array\n", mod_name); | |
json_decref(libs); | |
return false; | |
} | |
variables = json_object_get(mod_data, "variables"); | |
if (variables == nullptr) { | |
has_variables = false; | |
} | |
if (has_variables && !json_is_object(variables)) { | |
fprintf(stderr, "error: module %s: variables is not an array\n", mod_name); | |
json_decref(libs); | |
return false; | |
} | |
if (verbose) | |
printf("\tModule: %s\n", mod_name); | |
std::string library_name = std::string(mod_name); | |
vita_nid_t library_nid = json_integer_value(nid); | |
std::list<vita_library_t>::iterator lib_it; | |
for (lib_it = mod_it->libraries.begin(); lib_it != mod_it->libraries.end(); lib_it++) { | |
if (lib_it->name.compare(library_name) == 0) | |
break; | |
} | |
if (lib_it == mod_it->libraries.end()) { | |
vita_library_t library; | |
library.name = library_name; | |
library.nid = library_nid; | |
library.visibility = json_boolean_value(kernel); | |
mod_it->libraries.push_back(library); | |
lib_it = std::prev(mod_it->libraries.end()); | |
} | |
k = -1; | |
json_object_foreach(functions, target_name, target_nid) { | |
k++; | |
if (!json_is_integer(target_nid)) { | |
fprintf(stderr, "error: function %s: nid is not an integer\n", target_name); | |
json_decref(libs); | |
return false; | |
} | |
if (verbose) | |
printf("\t\tFunction: %s\n", target_name); | |
std::string function_name = std::string(target_name); | |
vita_nid_t function_nid = json_integer_value(target_nid); | |
std::list<vita_function_t>::iterator func_it; | |
for (func_it = lib_it->functions.begin(); func_it != lib_it->functions.end(); func_it++) { | |
if (func_it->name.compare(function_name) == 0) | |
break; | |
} | |
if (func_it == lib_it->functions.end()) { | |
vita_function_t function; | |
function.name = function_name; | |
function.nid = function_nid; | |
lib_it->functions.push_back(function); | |
} | |
} | |
if (has_variables) { | |
k = -1; | |
json_object_foreach(variables, target_name, target_nid) { | |
k++; | |
if (!json_is_integer(target_nid)) { | |
fprintf(stderr, "error: variable %s: nid is not an integer\n", target_name); | |
json_decref(libs); | |
return false; | |
} | |
if (verbose) | |
printf("\t\tVariable: %s\n", target_name); | |
std::string variable_name = std::string(target_name); | |
vita_nid_t variable_nid = json_integer_value(target_nid); | |
std::list<vita_variable_t>::iterator func_it; | |
for (func_it = lib_it->variables.begin(); func_it != lib_it->variables.end(); func_it++) { | |
if (func_it->name.compare(variable_name) == 0 && func_it->nid == variable_nid) | |
break; | |
} | |
if (func_it == lib_it->variables.end()) { | |
vita_variable_t variable; | |
variable.name = variable_name; | |
variable.nid = variable_nid; | |
lib_it->variables.push_back(variable); | |
} | |
} | |
} | |
} | |
} | |
return true; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
FILE *fp; | |
vita_exports_t exports; | |
if (argc < 2) { | |
std::cerr << "Usage: vitajsonlinker db1.json [db2.json, ...]" << std::endl; | |
return 1; | |
} | |
for (int i = 1; i < argc; i++) { | |
fp = fopen(argv[i], "r"); | |
if (fp == nullptr) { | |
std::cerr << "Error: could not open: " << argv[i] << std::endl; | |
return 1; | |
} | |
vita_json_load(exports, fp, 0); | |
fclose(fp); | |
} | |
vita_exports_remove_empty(exports); | |
vita_exports_sort(exports); | |
vita_json_print(exports); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment