/* Standard Library */
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
/* Supporting Databases */
#include "mob.h"
#include "const.h"
#include "item.h"
#include "skill.h"
/* Script Resources */
typedef struct {
item_w * item_db;
bonus_w * bonus_db;
const_w * const_db;
mob_w * mob_db;
skill_w * skill_db;
} script_r;
typedef struct {
int prefix;
int end;
} arg_r;
arg_r * script_analyzing(char ** subscript, int sub_c, int *bsub_c);
char ** script_parsing(char * buffer, char * script, int * sub_c);
void script_deinit(script_r * db_wraper);
script_r * script_init(char * item_fn, char * bonus_fn, char * const_fn, char * mob_fn, char * skill_fn);
int main() {
/* debug output file stream */
FILE * debug = fopen("debug_dump_simple.txt","w");
FILE * debug2 = fopen("debug_dump_complex.txt","w");
FILE * debug3 = fopen("debug_dump_constff.txt","w");
FILE * debug4 = fopen("debug_dump_constnn.txt","w");
if(debug == NULL || debug2 == NULL || debug3 == NULL || debug4 == NULL) return 0;
/* script_r is the script reading resources. */
script_r * res_db = script_init("db/item_db.txt","db/item_bonus.txt","db/const.txt","db/mob_db.txt","db/skill_db.txt");
/* item_w is the holds the non-modified item database */
item_w * item_db = itemdb_load("db/item_db.txt");
char utility[BUF_SIZE];
char buffer[BUF_SIZE * 2]; // Holds the modify script; holds the subscripts.
char ** subscript; // Points to the buffer containing strings.
int sub_c = 0; // Number of strings in subscript.
arg_r * bscript; // Holds the argument indexes
int bsub_c = 0; // Number of arguments
for(int i = DB_BEGIN; i < item_db->size; i++) {
subscript = script_parsing(buffer, item_db->db[i].script, &sub_c);
bscript = script_analyzing(subscript, sub_c, &bsub_c);
/* Analyze Bonuses: search variables */
int in_field = 0;
int pref_n = 0;
int skil_n = 0;
int const_n = 0;
int skill_n = 0;
int arg_start = 0;
int arg_count = 0;
int subexp_lvl = 0;
int subexp2_lvl = 0;
/* Bonus Database Array + Variables */
int * arg_list = NULL;
int arg_size = 0;
int arg_c = 0;
if(bscript != NULL && subscript != NULL)
for(int n = 0; n < bsub_c; n++)
if(bscript[n].prefix < bscript[n].end) {
in_field = 0;
arg_c = 0;
for(int j = bscript[n].prefix; j < bscript[n].end; j++) {
switch(in_field) {
case 0: // Check bonus prefix; stop analyzing otherwise
pref_n = -1;
for(int k = 0; k < prefix_c; k++)
if(strcmp(subscript[j],prefix_cap[k]) == 0) {
pref_n = k;
break;
}
if(pref_n < 0) {
printf("[Warn]: cannot find %s.\n",subscript[j]);
j = bscript[n].end;
}
break;
case 1: // Check skill identifier; stop analyzing otherwise
skil_n = bsearch_str(res_db->bonus_db[pref_n].bonus, res_db->bonus_db[pref_n].size, subscript[j], bonusdb_skill, bonusdb_getstr);
if(!skil_n) {
printf("[Warn]: cannot find %s\n", subscript[j]);
j = bscript[n].end;
}
// Exact argument list and size
arg_list = res_db->bonus_db[pref_n].bonus[skil_n].argc;
arg_size = res_db->bonus_db[pref_n].bonus[skil_n].argc_count;
break;
default: // Read argument
arg_start = j;
subexp_lvl = 0;
subexp2_lvl = 0;
arg_count = 0;
for(;j < bscript[n].end;j++) {
if((subscript[j][0] == ';' || subscript[j][0] == ',') && !subexp2_lvl && !subexp_lvl) {
arg_c++;
break;
}
if(is_subexp_begin(subscript[j][0]))
subexp_lvl++;
else if(is_subexp_end(subscript[j][0]))
subexp_lvl--;
else if(is_quote(subscript[j][0]) && !subexp2_lvl)
subexp2_lvl++;
else if(is_quote(subscript[j][0]) && subexp2_lvl)
subexp2_lvl--;
else
arg_count++;
}
/* Debug Dump */
if(arg_count == 1) {
fprintf(debug,"\tS[%d][%30s]: ", arg_count, retrieve_bonustype_str(arg_list[arg_c-1]));
for(int k = arg_start; k < j; k++) {
const_n = bsearch_str(res_db->const_db->db, res_db->const_db->size, subscript[k], constdb_ident, constdb_indexstr);
skil_n = bsearch_str(res_db->skill_db->db, res_db->skill_db->size, subscript[k], skilldb_name, skilldb_getstr);
if(const_n) {
sprintf(utility,"%d",res_db->const_db->db[const_n].constant);
strncpy(subscript[k],utility,strlen(subscript[k]));
fprintf(debug3,"%s\n",res_db->const_db->db[const_n].identifer);
} else if(skil_n) {
sprintf(utility,"%d",res_db->skill_db->db[skil_n].id);
strncpy(subscript[k],utility,strlen(subscript[k]));
fprintf(debug3,"%s\n",res_db->const_db->db[skil_n].identifer);
} else {
if(isalpha(subscript[k][0])) {
sprintf(utility,"%d",-1);
strncpy(subscript[k],utility,strlen(subscript[k]));
fprintf(debug4,"%s\n",subscript[k]);
}
}
fprintf(debug,"%s ",subscript[k]);
}
if(arg_count)
fprintf(debug,"\n");
} else if(arg_count > 1) {
fprintf(debug2,"\tC[%d][%30s]: ", arg_count, retrieve_bonustype_str(arg_list[arg_c-1]));
for(int k = arg_start; k < j; k++)
fprintf(debug2,"%s ",subscript[k]);
if(arg_count)
fprintf(debug2,"\n");
}
break;
}
in_field++;
}
}
}
itemdb_unload(item_db);
script_deinit(res_db);
fclose(debug);
fclose(debug2);
fclose(debug3);
fclose(debug4);
return 0;
}
/* Script Functions */
script_r * script_init(char * item_fn, char * bonus_fn, char * const_fn, char * mob_fn, char * skill_fn) {
script_r * db_wraper = malloc(sizeof(script_r));
if(db_wraper == NULL) return NULL;
db_wraper->item_db = itemdb_load(item_fn);
db_wraper->bonus_db = bonusdb_load(bonus_fn);
db_wraper->const_db = constdb_load(const_fn);
db_wraper->mob_db = mobdb_load(mob_fn);
db_wraper->skill_db = skilldb_load(skill_fn);
/* Prep the databases for binary search */
hpsort_int(db_wraper->item_db->db, db_wraper->item_db->size, itemdb_id, itemdb_getint, itemdb_swap);
for(int i = 0; i < prefix_c; i++)
hpsort_str((db_wraper->bonus_db[i]).bonus, (db_wraper->bonus_db[i]).size, bonusdb_skill, bonusdb_getstr, bonusdb_swap);
hpsort_str(db_wraper->const_db->db, db_wraper->const_db->size, constdb_ident, constdb_indexstr, constdb_swap);
hpsort_int(db_wraper->mob_db->db, db_wraper->mob_db->size, mobdb_id, mobdb_getint, mobdb_swap);
hpsort_str(db_wraper->skill_db->db, db_wraper->skill_db->size, skilldb_name, skilldb_getstr, skilldb_swap);
return db_wraper;
}
void script_deinit(script_r * db_wraper) {
bonusdb_unload(db_wraper->bonus_db);
itemdb_unload(db_wraper->item_db);
constdb_unload(db_wraper->const_db);
mobdb_unload(db_wraper->mob_db);
skilldb_unload(db_wraper->skill_db);
free(db_wraper);
}
char ** script_parsing(char * buffer, char * script, int * sub_c) {
if(buffer == NULL || script == NULL) {
printf("[Warn]: buffer / script invalid, unable to process.");
return NULL;
}
char ** subscript = malloc(sizeof(char *) * SUB_SIZE);
int subscript_c = 0;
/* Parse the item script */
int buf_c = 0;
for(int i = 0; i < strlen(script); i++) {
char ch = script[i];
if(!isspace(ch)) {
if(isdigit(ch) || is_score(ch)) {
buffer[buf_c++] = ch;
} else if (isalpha(ch)) {
buffer[buf_c++] = toupper(ch);
} else if(is_operator(ch) || is_special(ch) || is_subexp(ch)) {
buffer[buf_c++] = '\0';
buffer[buf_c++] = ch;
buffer[buf_c++] = '\0';
}
} else {
buffer[buf_c++] = '\0';
}
}
for(int i = 0; i < buf_c - 1; i++)
if(buffer[i] == '\0' && buffer[i+1] != '\0') {
subscript[subscript_c] = &buffer[i+1];
subscript_c++;
}
if(subscript_c == 0) {
free(subscript);
return NULL;
} else {
*sub_c = subscript_c;
return subscript;
}
}
arg_r * script_analyzing(char ** subscript, int sub_c, int *bsub_c) {
arg_r * bscript = malloc(sizeof(arg_r *) * SUB_SIZE);
int bscript_c = 0;
/* Find the number of prefixes */
for(int i = 0; i < sub_c; i++) {
for(int j = 0; j < prefix_c; j++)
if(strlen(prefix_cap[j]) == strlen(subscript[i])) // 'bonus' prefix the other prefixes
if(strcmp(prefix_cap[j],subscript[i]) == 0)
bscript[bscript_c].prefix = i;
if(strcmp(subscript[i],";") == 0 && bscript[bscript_c].prefix)
bscript[bscript_c++].end = i;
}
if(bscript_c == 0) {
free(bscript);
return NULL;
} else {
*bsub_c = bscript_c;
return bscript;
}
}