Remove old script2txt.

This commit is contained in:
lzwdgc 2024-02-03 13:28:30 +03:00
parent 98425912c2
commit 1caa842481
6 changed files with 70 additions and 737 deletions

View file

@ -1,130 +0,0 @@
/*
* AIM script2txt
* Copyright (C) 2015 lzwdgc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <buffer.h>
#include <common.h>
#include <sstream>
template <typename T>
inline bool replace_all(T &str, const T &from, const T &to)
{
bool replaced = false;
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != T::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length();
replaced = true;
}
return replaced;
}
inline bool replace_all(std::string &str, const std::string &from, const std::string &to)
{
return replace_all<std::string>(str, from, to);
}
struct script
{
uint32_t file_size;
uint32_t unk0; // stack size? always 16000? section bits? magic? max size?
uint32_t raw_text_size;
uint32_t nlines;
std::vector<uint8_t> raw_text;
uint32_t line_start_pos_len; // always 800
std::vector<uint32_t> line_start_pos;
//
std::vector<std::string> lines;
void load(const buffer &b)
{
READ(b, file_size);
READ(b, unk0);
READ(b, raw_text_size);
READ(b, nlines);
raw_text.resize(raw_text_size);
if (raw_text_size)
READ_N(b, raw_text[0], raw_text.size());
READ(b, line_start_pos_len);
line_start_pos.resize(line_start_pos_len);
READ_N(b, line_start_pos[0], line_start_pos.size());
if (!b.eof())
{
std::stringstream ss;
ss << std::hex << b.index() << " != " << std::hex << b.size();
throw std::logic_error(ss.str());
}
fix_text();
}
void fix_text()
{
std::string line;
for (size_t i = 0; i < raw_text.size(); i++)
{
if (raw_text[i] == 0)
{
lines.push_back(line);
line.clear();
}
else
line.push_back(raw_text[i]);
}
}
std::string get_text() const
{
std::string s;
for (auto &line : lines)
{
if (line != "\n")
s += line + "\n";
}
replace_all(s, "PROC", "PROC ");
replace_all(s, "ENFD", "END");
replace_all(s, "\nEN\n", "\n");
replace_all(s, "?", " ");
s += "\nEND\n";
// remove wrong braces
int braces = 0;
for (auto &c : s)
{
switch (c)
{
case '{':
braces++;
break;
case '}':
if (braces == 0)
c = ' ';
else
braces--;
break;
}
}
return s;
}
};

View file

@ -1,6 +1,6 @@
/*
* AIM script2txt
* Copyright (C) 2015 lzwdgc
* AIM script2txt2 (simpler version)
* Copyright (C) 2024 lzwdgc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,81 +16,103 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "script.h"
#include <mmap.h>
#include <types.h>
#include <script2txt_parser.h>
#include <primitives/filesystem.h>
#include <primitives/sw/main.h>
#include <primitives/sw/settings.h>
#include <primitives/sw/cl.h>
#include <fstream>
#include <iostream>
#include <stdint.h>
using std::cout;
using std::string;
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
cl::opt<path> p(cl::Positional, cl::desc("<script.scr or scripts dir>"), cl::Required);
cl::ParseCommandLineOptions(argc, argv);
auto func = [](auto filename)
{
// read
buffer b(read_file(filename));
script s;
s.load(b);
auto str = s.get_text();
Script2txtParserDriver driver;
if (driver.parse(str))
{
throw std::runtime_error("error during parsing input file");
auto func = [](auto filename) {
primitives::templates2::mmap_file<uint8_t> f{filename};
stream s{f};
script scr = s;
std::vector<std::string_view> lines;
int sz{};
for (int i = 0; i < scr.nlines; ++i) {
sz += lines.emplace_back((const char *)f.p + sizeof(script) + sz).size() + 1;
}
auto &ctx = driver.getContext();
// write script
{
filename += ".txt";
std::ofstream ofile(filename);
if (ofile)
ofile << ctx.getText();
if (std::ofstream ofile(filename, std::ios::binary); ofile) {
std::string indent, space = " "s;
auto inc = [&]() {
indent += space;
};
auto dec = [&]() {
if (!indent.empty()) {
indent.resize(indent.size() - space.size());
return true;
}
return false;
};
int procs{};
bool prev_newline{};
for (auto &&l : lines) {
auto else_ = l == "ELSE"sv;
auto proc = l.starts_with("PROC"sv);
auto end = l == "END"sv;
auto lbrace = l == "{"sv;
auto rbrace = l == "}"sv;
if (else_ && prev_newline) {
ofile.seekp(-1, std::ios::cur);
}
prev_newline = false;
if (rbrace) {
if (!dec()) {
ofile << "// script2txt2 comment: unbalanced!\n";
}
}
if (end && procs) {
if (!dec()) {
ofile << "// script2txt2 comment: unbalanced!\n";
}
}
// write function calls
{
std::ofstream functions("functions.txt", std::ios::app);
if (functions)
{
for (auto &f : driver.functions)
{
std::string f2(f.size(), 0);
std::transform(f.begin(), f.end(), f2.begin(), tolower);
functions << f2 << "\n";
ofile << indent << l << "\n";
if ((end || rbrace) && indent.empty()) {
ofile << "\n";
prev_newline = true;
}
if (end && procs) {
procs = 0;
}
if (lbrace || proc) {
indent += space;
}
if (proc) {
procs = 1;
}
}
}
}
};
if (fs::is_regular_file(p))
if (fs::is_regular_file(p)) {
func(p.string());
else if (fs::is_directory(p))
{
} else if (fs::is_directory(p)) {
auto files = enumerate_files_like(p, ".*\\.scr", false);
auto files2 = enumerate_files_like(p, ".*\\.QST", false);
files.insert(files2.begin(), files2.end());
for (auto &f : files)
{
for (auto &f : files) {
std::cout << "processing: " << f << "\n";
func(f.string());
}
}
else
} else {
throw std::runtime_error("Bad fs object");
}
return 0;
}

View file

@ -1,100 +0,0 @@
%{
/*
* AIM tm_converter
* Copyright (C) 2015 lzwdgc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <script2txt_parser.h>
%}
%option nounistd
%option yylineno
%option nounput
%option batch
%option never-interactive
%option reentrant
%option noyywrap
DIGIT [0-9]
DIGITS {DIGIT}{DIGIT}*
INTEGER {DIGITS}[Ff]?
STRING [[:alpha:]_-][[:alnum:]_-]*
%x user_string
%%
%{
// Code run each time yylex is called.
loc.step();
%}
#.*/\n ; // ignore comments
[ \t]+ loc.step();
\r loc.step();
\n {
loc.lines(yyleng);
loc.step();
}
";" return MAKE(SEMICOLON);
":" return MAKE(COLON);
"(" return MAKE(L_BRACKET);
")" return MAKE(R_BRACKET);
"{" return MAKE(L_CURLY_BRACKET);
"}" return MAKE(R_CURLY_BRACKET);
"[" return MAKE(L_SQUARE_BRACKET);
"]" return MAKE(R_SQUARE_BRACKET);
"," return MAKE(COMMA);
"\." return MAKE(POINT);
"->" return MAKE(R_ARROW);
"=" return MAKE(EQUAL);
"\*" return MAKE(ASTERISK);
IF { return MAKE(IF); }
ELSE { return MAKE(ELSE); }
"!" { return MAKE(NOT); }
"&" { return MAKE(AND); }
"|" { return MAKE(OR); }
"||" { return MAKE(OR); }
END { return MAKE(END); }
PROC { return MAKE(PROC); }
_PROC { return MAKE(_PROC); }
{INTEGER} { return MAKE_VALUE(INTEGER, std::stoi(yytext)); }
{STRING} { return MAKE_VALUE(STRING, yytext); }
\" { PUSH_STATE(user_string); return MAKE(QUOTE); }
<user_string>\" { POP_STATE(); return MAKE(QUOTE); }
<user_string>(?:[^"\\]|\\.)*/\" {
int n = 0;
char *p = yytext;
while ((p = strstr(p, "\n"))++ != 0)
n++;
if (n)
{
loc.lines(n);
loc.step();
}
return MAKE_VALUE(STRING, yytext);
}
. { /*driver.error(loc, "invalid character");*/ return MAKE(ERROR_SYMBOL); }
<<EOF>> return MAKE(EOQ);
%%

View file

@ -1,332 +0,0 @@
%{
/*
* AIM tm_converter
* Copyright (C) 2015 lzwdgc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <script2txt_parser.h>
%}
////////////////////////////////////////
// general settings
%require "3.0"
//%debug
%start file
%locations
%verbose
//%no-lines
%define parse.error verbose
////////////////////////////////////////
// c++ skeleton and options
%skeleton "lalr1.cc"
%define api.value.type variant
%define api.token.constructor // C++ style of handling variants
%define parse.assert // check C++ variant types
%code provides { #include <primitives/helper/bison_yy.h> }
%parse-param { MY_PARSER_DRIVER &driver } // param to yy::parser() constructor (the parsing context)
%code requires // forward decl of C++ driver (our parser) in HPP
{
#include <Polygon4/DataManager/Schema/Emitter.h>
#include <set>
}
%code provides
{
struct MY_PARSER_DRIVER : MY_PARSER
{
void setContext(Emitter &&ctx) { context = std::move(ctx); }
const Emitter &getContext() const { return context; }
Emitter context;
std::set<std::string> functions;
};
}
////////////////////////////////////////
// tokens and types
%token EOQ 0 "end of file"
%token ERROR_SYMBOL
%token L_BRACKET R_BRACKET COMMA QUOTE SEMICOLON COLON POINT
L_CURLY_BRACKET R_CURLY_BRACKET SHARP R_ARROW EQUAL
L_SQUARE_BRACKET R_SQUARE_BRACKET ASTERISK
%token IF ELSE NOT AND OR
%token END PROC _PROC
%token <std::string> STRING
%token <int> INTEGER
%type <std::string> string integer number
object_variable object
variables variable
function_name procedure_begin
parameters parameter
conds cond condition_body
function_call
%type <Emitter> condition condition_begin
statements statement
proc_statements proc_statement
procedure
global_statements global_statement
script
////////////////////////////////////////
%%
file: script EOQ
{ driver.setContext(std::move($1)); }
;
script: global_statements
{ $$ = std::move($1); }
;
global_statements: global_statement
{ $$ = std::move($1); }
| global_statements global_statement
{
auto &ctx = $1;
ctx.addLine();
ctx.addEmitter(std::move($2));
$$ = std::move(ctx);
}
;
global_statement: function_call
{
Emitter ctx;
ctx.addLine($1);
$$ = std::move(ctx);
}
| condition
{ $$ = std::move($1); }
| procedure
{ $$ = std::move($1); }
| R_CURLY_BRACKET
{ $$ = Emitter(); }
| END
{ $$ = Emitter(); }
| ERROR_SYMBOL
{ $$ = Emitter(); }
| POINT
{ $$ = Emitter(); }
| STRING
{ $$ = Emitter(); }
| R_BRACKET
{ $$ = Emitter(); }
;
procedure: procedure_begin proc_statements END
{
Emitter ctx;
ctx.beginBlock($1);
ctx.addEmitter(std::move($2));
ctx.endBlock();
$$ = std::move(ctx);
}
| procedure_begin END
{
Emitter ctx;
ctx.beginBlock($1);
ctx.endBlock();
$$ = std::move(ctx);
}
| procedure_begin L_CURLY_BRACKET statements R_CURLY_BRACKET
{
Emitter ctx;
ctx.beginBlock($1);
ctx.addEmitter(std::move($3));
ctx.endBlock();
$$ = std::move(ctx);
}
;
procedure_begin: PROC function_name L_BRACKET R_BRACKET
{ $$ = "PROC " + $2 + "()"; }
| PROC function_name
{ $$ = "PROC " + $2 + "()"; }
;
proc_statements: proc_statement
{ $$ = std::move($1); }
| proc_statements proc_statement
{
auto &ctx = $1;
ctx.addEmitter(std::move($2));
$$ = std::move(ctx);
}
;
proc_statement: function_call
{
Emitter ctx;
ctx.addLine($1);
$$ = std::move(ctx);
}
| _PROC function_call
{
Emitter ctx;
ctx.addLine("_PROC " + $2);
$$ = std::move(ctx);
}
| condition
{ $$ = std::move($1); }
| COLON
{ $$ = Emitter(); }
| R_BRACKET
{ $$ = Emitter(); }
| ERROR_SYMBOL
{ $$ = Emitter(); }
;
statements: statement
{ $$ = std::move($1); }
| statements statement
{
auto &ctx = $1;
ctx.addEmitter(std::move($2));
$$ = std::move(ctx);
}
;
statement: proc_statement
{ $$ = std::move($1); }
| END
{
Emitter ctx;
ctx.addLine("END");
$$ = std::move(ctx);
}
;
function_call: function_name L_BRACKET parameters R_BRACKET
{ $$ = $1 + "(" + $3 + ")"; driver.functions.insert($1); }
| function_name L_BRACKET parameters COMMA R_BRACKET
{ $$ = $1 + "(" + $3 + ")"; driver.functions.insert($1); }
| function_name L_BRACKET R_BRACKET
{ $$ = $1 + "()"; driver.functions.insert($1); }
;
parameters: parameter
{ $$ = $1; }
| parameters COMMA parameter
{ $$ = $1 + ", " + $3; }
;
parameter: object
{ $$ = $1; }
| number
{ $$ = $1; }
| object_variable
{ $$ = $1; }
| ASTERISK
{ $$ = "*"; }
;
condition: condition_begin
{ $$ = std::move($1); }
| condition_begin ELSE L_CURLY_BRACKET statements R_CURLY_BRACKET
{
auto &ctx = $1;
ctx.beginBlock("else");
ctx.addEmitter(std::move($4));
ctx.endBlock();
$$ = std::move(ctx);
}
;
condition_begin: IF L_BRACKET condition_body R_BRACKET L_CURLY_BRACKET statements R_CURLY_BRACKET
{
Emitter ctx;
ctx.beginBlock("if (" + $3 + ")");
ctx.addEmitter(std::move($6));
ctx.endBlock();
$$ = std::move(ctx);
}
| IF L_BRACKET condition_body L_CURLY_BRACKET statements R_CURLY_BRACKET
{
Emitter ctx;
ctx.beginBlock("if (" + $3 + ")");
ctx.addEmitter(std::move($5));
ctx.endBlock();
$$ = std::move(ctx);
}
| IF L_BRACKET condition_body R_BRACKET L_CURLY_BRACKET R_CURLY_BRACKET
{
Emitter ctx;
ctx.beginBlock("if (" + $3 + ")");
ctx.endBlock();
$$ = std::move(ctx);
}
;
condition_body: conds
{ $$ = $1; }
;
conds: cond
{ $$ = $1; }
| conds AND cond
{ $$ = $1 + " && " + $3; }
| conds OR cond
{ $$ = $1 + " || " + $3; }
;
cond: object
{ $$ = $1; }
| object_variable
{ $$ = $1; }
| function_call
{ $$ = $1; }
| NOT cond
{ $$ = "!" + $2; }
;
object_variable: object POINT variables
{ $$ = $1 + "." + $3; }
;
variables: /* empty */
{ $$ = ""; }
| variable
{ $$ = $1; }
| variables POINT variable
{ $$ = $1 + "." + $3; }
;
function_name: string
{ $$ = $1; }
;
object: string
{ $$ = $1; }
;
variable: string
{ $$ = $1; }
| integer
{ $$ = $1; }
;
number: integer POINT integer
{ $$ = $1 + "." + $3; }
| integer
{ $$ = $1; }
;
string: STRING
{ $$ = $1; }
;
integer: INTEGER
{ $$ = std::to_string($1); }
;
%%

View file

@ -1,118 +0,0 @@
/*
* AIM script2txt2 (simpler version)
* Copyright (C) 2024 lzwdgc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mmap.h>
#include <types.h>
#include <primitives/sw/main.h>
#include <primitives/sw/settings.h>
#include <primitives/sw/cl.h>
#include <fstream>
int main(int argc, char *argv[]) {
cl::opt<path> p(cl::Positional, cl::desc("<script.scr or scripts dir>"), cl::Required);
cl::ParseCommandLineOptions(argc, argv);
auto func = [](auto filename) {
primitives::templates2::mmap_file<uint8_t> f{filename};
stream s{f};
script scr = s;
std::vector<std::string_view> lines;
int sz{};
for (int i = 0; i < scr.nlines; ++i) {
sz += lines.emplace_back((const char *)f.p + sizeof(script) + sz).size() + 1;
}
// write script
{
filename += ".txt";
if (std::ofstream ofile(filename, std::ios::binary); ofile) {
std::string indent, space = " "s;
auto inc = [&]() {
indent += space;
};
auto dec = [&]() {
if (!indent.empty()) {
indent.resize(indent.size() - space.size());
return true;
}
return false;
};
int procs{};
bool prev_newline{};
for (auto &&l : lines) {
auto else_ = l == "ELSE"sv;
auto proc = l.starts_with("PROC"sv);
auto end = l == "END"sv;
auto lbrace = l == "{"sv;
auto rbrace = l == "}"sv;
if (else_ && prev_newline) {
ofile.seekp(-1, std::ios::cur);
}
prev_newline = false;
if (rbrace) {
if (!dec()) {
ofile << "// script2txt2 comment: unbalanced!\n";
}
}
if (end && procs) {
if (!dec()) {
ofile << "// script2txt2 comment: unbalanced!\n";
}
}
ofile << indent << l << "\n";
if ((end || rbrace) && indent.empty()) {
ofile << "\n";
prev_newline = true;
}
if (end && procs) {
procs = 0;
}
if (lbrace || proc) {
indent += space;
}
if (proc) {
procs = 1;
}
}
}
}
};
if (fs::is_regular_file(p)) {
func(p.string());
} else if (fs::is_directory(p)) {
auto files = enumerate_files_like(p, ".*\\.scr", false);
auto files2 = enumerate_files_like(p, ".*\\.QST", false);
files.insert(files2.begin(), files2.end());
for (auto &f : files) {
std::cout << "processing: " << f << "\n";
func(f.string());
}
} else {
throw std::runtime_error("Bad fs object");
}
return 0;
}

11
sw.cpp
View file

@ -49,7 +49,7 @@ void build(Solution &s)
add_exe_with_common("mmp_extractor") += "org.sw.demo.intel.opencv.highgui"_dep;
add_exe_with_common("mpj_loader");
add_exe_with_common("paker");
add_exe_with_common("script2txt2");
add_exe_with_common("script2txt");
add_exe_with_common("txt2script");
add_exe_with_common("tm_converter");
add_exe("name_generator");
@ -60,15 +60,6 @@ void build(Solution &s)
;
// not so simple targets
auto &script2txt = add_exe_with_common("script2txt");
{
script2txt += ".*"_rr;
script2txt += "pub.lzwdgc.Polygon4.DataManager.schema-master"_dep;
gen_flex_bison_pair("org.sw.demo.lexxmark.winflexbison"_dep, script2txt, "LALR1_CPP_VARIANT_PARSER", "script2txt");
if (script2txt.getCompilerType() == CompilerType::MSVC)
script2txt.CompileOptions.push_back("/Zc:__cplusplus");
}
auto &model = tools.addStaticLibrary("model");
{
model += cppstd;