Initial commit

This commit is contained in:
Andrei Solodovnikov
2023-09-07 17:04:37 +03:00
commit f4c0960704
334 changed files with 36105 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
#include <fstream>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
void print_help(const std::string program_name)
{
using namespace std;
cout << "Usage: " << program_name << " [input file] [output file]\n\n";
cout << "Convert CYBERcobra program file into $readmemh acceptable file.\n";
cout << "CYBERcobra program file may contain only comments (starting with \"//\"),\n";
cout << "whitespaces and binary digits '0' or '1'.\n";
cout << "This program will erase this parts from every line and then convert\n";
cout << "32-bits binary strings into 4 little endian 8-bit strings in hex-format.\n\n";
cout << "If output file omitted, the <input_file_base>_converted.<input_file_ext>\n";
cout << "will be produced.\n\n";
cout << "If input file omitted, program.txt will be used.\n\n";
cout << "Example:\n\n";
cout << program_name << " open \"program.txt\" and produce \"program_converted.txt\"\n";
cout << program_name << " test.txt open \"test.txt\" and produce \"test_converted.txt\"\n";
cout << program_name << " test.txt myname.dat open \"test.txt\" and produce \"myname.dat\"\n";
}
int main(int argc, char ** argv)
{
using namespace std;
/*
Parse argument list and print help message if needed
*/
string ifname;
string ofname;
string start;
string end;
string filename = argv[0];
size_t dot_pos;
filename = filename.substr(filename.find_last_of("/\\") + 1);
switch (argc)
{
case 1:
ifname = "program.txt";
ofname = "program_converted.txt";
break;
case 2:
if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))
{
print_help(filename);
return 0;
}
ifname = argv[1];
dot_pos = ifname.find(".");
if(dot_pos != string::npos)
{
start = ifname.substr(0, dot_pos);
end = ifname.substr(dot_pos, ifname.size() - dot_pos);
ofname = start + "_converted" + end;
}
else
{
ofname = ifname + "_converted";
}
break;
case 3:
ifname = argv[1];
ofname = argv[2];
break;
default:
print_help(filename);
return 0;
}
/*
Program body
*/
// Open input and output files
ifstream ifs(ifname);
if(!ifs)
{
cerr << "Unable to open file: \"" << ifname << "\"" << endl;
return -1;
}
ofstream ofs(ofname);
if (!ofs.is_open())
{
cerr << "Unable to open file: \"" << ofname << "\"" << endl;
return -1;
}
string str;
size_t line_counter = 0;
while (getline(ifs, str))
{
line_counter++;
// trim line from comments and whitespaces, skip empty lines after trimming
auto comment_pos = str.find("//");
if(comment_pos != string::npos)
{
str.erase(comment_pos);
}
str.erase(remove_if(str.begin(), str.end(), ::isspace), str.end());
if(!str.size())
{
continue;
}
if(str.size()!=32)
{
cerr << "line " << line_counter << " length is not equal 32 after trimming comments and whitespaces" << endl;
return -2;
}
// split 32-bits binary line into 4 little-endian hex lines and write them into file
for (size_t i = 0; i < 4; i++)
{
// For every 8-bit part of 32-bit line get int representation.
// If illegal character found, throw error.
size_t valid_char_num;
string byte_substr = str.substr(8*(3-i), 8);
int cur_byte = std::stoi(byte_substr, &valid_char_num, 2);
if(valid_char_num != 8)
{
cerr << "Illegal character '" << byte_substr.at(valid_char_num) <<
"' found in line " << line_counter << ": \"" << str << "\"\n";
cerr << "Should be only '0' or '1'." << endl;
return -3;
}
char hex_byte_str[3];
// convert int representation into hex string
snprintf(hex_byte_str, 3, "%02x", cur_byte);
ofs << hex_byte_str << "\n";
}
}
ifs.close();
ofs.close();
return 0;
}