mirror of
https://github.com/galaxyhaxz/devilution
synced 2025-02-22 12:34:59 +00:00
426 lines
7.1 KiB
C
426 lines
7.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define MAX_COLUMNS 256
|
|
|
|
int NumCols, NumRows;
|
|
int Columns[MAX_COLUMNS];
|
|
int HasEnum;
|
|
|
|
enum {
|
|
FIELD_INTEGER,
|
|
FIELD_STRING,
|
|
FIELD_ARRAY,
|
|
FIELD_POINTER,
|
|
FIELD_COMMENT
|
|
};
|
|
|
|
unsigned char *LoadBinaryFile(char *file, int *pdwSize)
|
|
{
|
|
unsigned char *p, *p2;
|
|
FILE *fp;
|
|
int bufsize, i, fsize;
|
|
|
|
fp = fopen(file, "rb");
|
|
|
|
if(fp == NULL) {
|
|
fprintf(stderr, "Can't open file %s\n", file);
|
|
exit(-1);
|
|
}
|
|
|
|
fseek(fp, 0L, SEEK_END);
|
|
bufsize = ftell(fp);
|
|
p = (unsigned char *)malloc(sizeof(unsigned char) * (bufsize + 1));
|
|
fseek(fp, 0L, SEEK_SET);
|
|
fread(p, sizeof(char), bufsize, fp);
|
|
fclose(fp);
|
|
|
|
p2 = (unsigned char *)malloc(sizeof(unsigned char) * (bufsize + 1));
|
|
fsize = 0;
|
|
|
|
for(i = 0; i < bufsize; i++) {
|
|
if(p[i] == '\r') {
|
|
p2[fsize++] = '\n';
|
|
if(p[i + 1] == '\n') {
|
|
i++;
|
|
}
|
|
} else {
|
|
p2[fsize++] = p[i];
|
|
}
|
|
}
|
|
p2[fsize++] = '\0';
|
|
|
|
free(p);
|
|
|
|
if(pdwSize != NULL) {
|
|
*pdwSize = fsize;
|
|
}
|
|
|
|
return p2;
|
|
}
|
|
|
|
void WriteField(unsigned char *p, FILE *pFile, int c, int len)
|
|
{
|
|
char BraceL[] = "{ ";
|
|
char BraceR[] = " }";
|
|
char Ptr[] = "&";
|
|
char Str[] = "\"";
|
|
char NoData[] = "0";
|
|
char NoStr[] = "NULL";
|
|
char Sep[] = ", ";
|
|
|
|
switch(Columns[c]) {
|
|
case FIELD_INTEGER:
|
|
if(len != 0) {
|
|
fwrite(p, sizeof(char), len, pFile);
|
|
} else {
|
|
fwrite(NoData, sizeof(char), sizeof(NoData) - 1, pFile);
|
|
}
|
|
break;
|
|
case FIELD_STRING:
|
|
if(len != 0 && strncmp(NoStr, p, sizeof(NoStr) - 1) != 0) {
|
|
if(*p != '"') {
|
|
fwrite(Str, sizeof(char), sizeof(Str) - 1, pFile);
|
|
}
|
|
if(len != 1 || *p != '~') {
|
|
fwrite(p, sizeof(char), len, pFile);
|
|
}
|
|
if(p[len - 1] != '"') {
|
|
fwrite(Str, sizeof(char), sizeof(Str) - 1, pFile);
|
|
}
|
|
} else {
|
|
fwrite(NoStr, sizeof(char), sizeof(NoStr) - 1, pFile);
|
|
}
|
|
break;
|
|
case FIELD_ARRAY:
|
|
fwrite(BraceL, sizeof(char), sizeof(BraceL) - 1, pFile);
|
|
if(len != 0) {
|
|
if(p[0] == '\"' && p[len - 1] == '\"') {
|
|
fwrite(&p[1], sizeof(char), len - 2, pFile);
|
|
} else {
|
|
fwrite(p, sizeof(char), len, pFile);
|
|
}
|
|
} else {
|
|
fwrite(NoData, sizeof(char), sizeof(NoData) - 1, pFile);
|
|
}
|
|
fwrite(BraceR, sizeof(char), sizeof(BraceR) - 1, pFile);
|
|
break;
|
|
case FIELD_POINTER:
|
|
if(len != 0 && strncmp(NoStr, p, sizeof(NoStr) - 1) != 0) {
|
|
fwrite(Ptr, sizeof(char), sizeof(Ptr) - 1, pFile);
|
|
fwrite(p, sizeof(char), len, pFile);
|
|
} else {
|
|
fwrite(NoStr, sizeof(char), sizeof(NoStr) - 1, pFile);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if(c != NumCols - 1) {
|
|
fwrite(Sep, sizeof(char), sizeof(Sep) - 1, pFile);
|
|
}
|
|
}
|
|
|
|
void WriteColumn(unsigned char *p, FILE *pFile, int c)
|
|
{
|
|
unsigned char *p2;
|
|
int cur, len;
|
|
|
|
cur = 0;
|
|
while(cur != c) {
|
|
while(*p != '\t' && *p != '\n') {
|
|
p++;
|
|
}
|
|
p++;
|
|
cur++;
|
|
}
|
|
|
|
p2 = p;
|
|
len = 0;
|
|
while(*p2 != '\t' && *p2 != '\n') {
|
|
p2++;
|
|
len++;
|
|
}
|
|
|
|
WriteField(p, pFile, c, len);
|
|
}
|
|
|
|
void ConvertTextFile(char *name, unsigned char *p, int size)
|
|
{
|
|
unsigned char *p2;
|
|
int c, len;
|
|
FILE *pOutput;
|
|
char Pre[] = "\t{ ";
|
|
char Suf[] = " },\r\n";
|
|
|
|
pOutput = fopen(name, "wb");
|
|
|
|
if(pOutput == NULL) {
|
|
fprintf(stderr, "Can't create file %s\n", name);
|
|
exit(-1);
|
|
}
|
|
|
|
while(*p != '\n') {
|
|
p++;
|
|
}
|
|
p++;
|
|
|
|
while(*p != '\0') {
|
|
p2 = p;
|
|
len = 0;
|
|
while(*p2 != '\n') {
|
|
p2++;
|
|
len++;
|
|
}
|
|
len++;
|
|
fwrite(Pre, sizeof(char), sizeof(Pre) - 1, pOutput);
|
|
for(c = 0; c < NumCols; c++) {
|
|
if(Columns[c] != FIELD_COMMENT) {
|
|
WriteColumn(p, pOutput, c);
|
|
}
|
|
}
|
|
fwrite(Suf, sizeof(char), sizeof(Suf) - 1, pOutput);
|
|
p += len;
|
|
}
|
|
|
|
fclose(pOutput);
|
|
}
|
|
|
|
void SetColumnType(char t, int c)
|
|
{
|
|
switch(t) {
|
|
case 'i':
|
|
Columns[c] = FIELD_INTEGER;
|
|
return;
|
|
case 's':
|
|
Columns[c] = FIELD_STRING;
|
|
return;
|
|
case 'a':
|
|
Columns[c] = FIELD_ARRAY;
|
|
return;
|
|
case 'p':
|
|
Columns[c] = FIELD_POINTER;
|
|
return;
|
|
}
|
|
|
|
fprintf(stderr, "Invalid type '%c' column %d\n", t, c + 1);
|
|
exit(-1);
|
|
}
|
|
|
|
void CheckMaxColumns(unsigned char *p)
|
|
{
|
|
int num_cols;
|
|
|
|
num_cols = 0;
|
|
while(*p != '\n') {
|
|
if(*p == '\t') {
|
|
num_cols++;
|
|
}
|
|
p++;
|
|
}
|
|
num_cols++;
|
|
|
|
if(num_cols >= MAX_COLUMNS) {
|
|
fprintf(stderr, "%d columns exceeds limit of %d\n", num_cols, MAX_COLUMNS - 1);
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
void SetupColumns(unsigned char *p)
|
|
{
|
|
NumCols = 0;
|
|
|
|
while(*p != '\n') {
|
|
if(*p == '\t') {
|
|
fprintf(stderr, "Invalid column %d\n", NumCols + 1);
|
|
exit(-1);
|
|
}
|
|
if(*p == '#') {
|
|
HasEnum = 1;
|
|
}
|
|
if(*p == '*' || p[0] == '#' && (p[1] == '\t' || p[1] == '\n')) {
|
|
Columns[NumCols++] = FIELD_COMMENT;
|
|
p++;
|
|
while(*p != '\t' && *p != '\n') {
|
|
p++;
|
|
}
|
|
if(*p != '\n') {
|
|
p++;
|
|
}
|
|
} else {
|
|
while(*p != '\t' && *p != '\n') {
|
|
p++;
|
|
}
|
|
p -= 3;
|
|
if(p[0] != '(' || p[2] != ')') {
|
|
fprintf(stderr, "No type for column %d\n", NumCols + 1);
|
|
exit(-1);
|
|
}
|
|
SetColumnType(p[1], NumCols++);
|
|
p += 3;
|
|
if(*p != '\n') {
|
|
p++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetNumRows(unsigned char *p)
|
|
{
|
|
NumRows = 0;
|
|
while(*p != '\0') {
|
|
if(*p == '\n') {
|
|
NumRows++;
|
|
}
|
|
p++;
|
|
}
|
|
}
|
|
|
|
void InitColumns(unsigned char *p)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < MAX_COLUMNS; i++) {
|
|
Columns[i] = -1;
|
|
}
|
|
|
|
CheckMaxColumns(p);
|
|
SetupColumns(p);
|
|
}
|
|
|
|
int IsValidEnum(unsigned char *p, int size)
|
|
{
|
|
int i, valid;
|
|
|
|
valid = 1;
|
|
for(i = 0; i < size && valid; i++) {
|
|
if(i != 0 && p[i] >= '0' && p[i] <= '9') {
|
|
continue;
|
|
}
|
|
if(p[i] >= 'A' && p[i] <= 'Z') {
|
|
continue;
|
|
}
|
|
if(p[i] >= 'a' && p[i] <= 'z') {
|
|
continue;
|
|
}
|
|
if(p[i] == '_') {
|
|
continue;
|
|
}
|
|
valid = 0;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
void WriteEnum(unsigned char *p, int c, FILE *pOutput)
|
|
{
|
|
unsigned char *p2;
|
|
int i, cur, size;
|
|
char Pre[] = "enum {\r\n";
|
|
char Tab[] = "\t";
|
|
char Suf[] = ",\r\n";
|
|
char End[] = "};\r\n";
|
|
char tmp[16];
|
|
|
|
while(*p != '\n') {
|
|
p++;
|
|
}
|
|
p++;
|
|
|
|
fwrite(Pre, sizeof(char), sizeof(Pre) - 1, pOutput);
|
|
|
|
for(i = 0; i < NumRows - 1; i++) {
|
|
cur = 0;
|
|
while(cur != c) {
|
|
while(*p != '\t' && *p != '\n') {
|
|
p++;
|
|
}
|
|
p++;
|
|
cur++;
|
|
}
|
|
p2 = p;
|
|
size = 0;
|
|
while(*p2 != '\t' && *p2 != '\n') {
|
|
size++;
|
|
p2++;
|
|
}
|
|
if(IsValidEnum(p, size)) {
|
|
fwrite(Tab, sizeof(char), sizeof(Tab) - 1, pOutput);
|
|
fwrite(p, sizeof(char), size, pOutput);
|
|
sprintf(tmp, " = %d", i);
|
|
fwrite(tmp, sizeof(char), strlen(tmp), pOutput);
|
|
fwrite(Suf, sizeof(char), sizeof(Suf) - 1, pOutput);
|
|
}
|
|
p += size;
|
|
while(*p != '\n') {
|
|
p++;
|
|
}
|
|
p++;
|
|
}
|
|
|
|
fwrite(End, sizeof(char), sizeof(End) - 1, pOutput);
|
|
}
|
|
|
|
void WriteEnumFile(char *name, unsigned char *p, int size)
|
|
{
|
|
int i, cur;
|
|
unsigned char *p2;
|
|
FILE *pOutput;
|
|
|
|
pOutput = fopen(name, "wb");
|
|
|
|
if(pOutput == NULL) {
|
|
fprintf(stderr, "Can't create file %s\n", name);
|
|
exit(-1);
|
|
}
|
|
|
|
for(i = 0; Columns[i] != -1; i++) {
|
|
p2 = p;
|
|
cur = 0;
|
|
while(cur != i) {
|
|
while(*p2 != '\t' && *p2 != '\n') {
|
|
p2++;
|
|
}
|
|
p2++;
|
|
cur++;
|
|
}
|
|
if(*p2 == '#') {
|
|
WriteEnum(p, i, pOutput);
|
|
}
|
|
}
|
|
|
|
fclose(pOutput);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int size;
|
|
unsigned char *p;
|
|
|
|
if(argc != 3 && argc != 4) {
|
|
fprintf(stderr, "Usage: makexl [txt] [cpp] [h]\n");
|
|
return 0;
|
|
}
|
|
|
|
p = LoadBinaryFile(argv[1], &size);
|
|
|
|
GetNumRows(p);
|
|
if(NumRows < 2) {
|
|
fprintf(stderr, "Not enough rows\n");
|
|
free(p);
|
|
return 0;
|
|
}
|
|
|
|
HasEnum = 0;
|
|
InitColumns(p);
|
|
|
|
ConvertTextFile(argv[2], p, size);
|
|
|
|
if(argc == 4 && HasEnum) {
|
|
WriteEnumFile(argv[3], p, size);
|
|
}
|
|
|
|
free(p);
|
|
|
|
return 0;
|
|
}
|