aboutsummaryrefslogblamecommitdiffstats
path: root/gencharset.cpp
blob: 716c2acd36ecc8e65feb9a480dd89ba0e6b06fd3 (plain) (tree)




























































































































































































































                                                                             
// gencharset.cpp
// Revision 31-jul-2004

#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <sstream>
// bitset in gcc 2.95 uses min whithout defining it.
// Then we include something that does.
#include <algorithm>
#include <bitset>

using std::istream;
using std::ostream;
using std::cerr;
using std::endl;
using std::string;
using std::runtime_error;

void gencharset (const string & fin, const string & fout,
	const std::string & name);
void readcharset (istream & in);
void writecharset (ostream & out, const std::string & name);

size_t linenumber= 0;

int main (int argc, char * * argv)
{
	try
	{
		string fin, fout, name;
		if (argc > 1) fin= argv [1];
		if (argc > 2) fout= argv [2];
		if (argc > 3) name= argv [3];
		gencharset (fin, fout, name);
	}
	catch (std::exception & e)
	{
		cerr << e.what ();
		if (linenumber != 0)
			cerr << " in line " << linenumber;
		cerr << endl;
	}
}

typedef unsigned char chardata [8];

chardata default_data;
bool default_defined= false;
chardata data [256];
bool data_defined [256]= { false };

void gencharset (const string & fin, const string & fout,
	const std::string & name)
{
	istream * pin;
	if (fin.empty () )
		pin= & std::cin;
	else
	{
		std::ifstream * pinf= new std::ifstream (fin.c_str () );
		if (! pinf->is_open () )
			throw runtime_error ("File not found");
		pin= pinf;
	}

	readcharset (* pin);

	if (! fin.empty () )
		delete pin;

	linenumber= 0;

	ostream * pout;
	if (fout.empty () )
		pout= & std::cout;
	else
	{
		std::ofstream * poutf= new std::ofstream (fout.c_str () );
		if (! poutf->is_open () )
			throw runtime_error ("Cannot create output file");
		pout= poutf;
	}

	writecharset (* pout, name);

	if (! fout.empty () )
		delete pout;
}

bool readline (istream & in, string & str)
{
	do {
		std::getline (in, str);
		if (! in)
			return false;
		++ linenumber;
		string::size_type l= str.size ();
		if (l > 0 && str [l - 1] == '\r')
			str= str.substr (0, l - 1);
	} while (str.empty () || str [0] == '#');
	return true;
}

void readchar (istream & in, chardata & chd)
{
	string str;
	bool invert= false;
	for (int i= 0; i < 8; ++i)
	{
		if (! readline (in, str) )
			throw runtime_error ("Unexpected eof");
		if (str == "INVERT")
		{
			invert= true;
			if (! readline (in, str) )
				throw runtime_error ("Unexpected eof");
		}
		std::bitset <8> b (str);
		unsigned long l= b.to_ulong ();
		if (invert)
			l= ~ l;
		chd [i]= static_cast <unsigned char> (l);
	}
}

unsigned char getcharcode (const string & str)
{
	if (str.size () == 1)
		return str [0];
	std::istringstream iss (str);
	unsigned int u;
	iss >> u;
	if (! iss)
		throw runtime_error ("Syntax error");
	char c;
	iss >> c;
	if (! iss.eof () )
		throw runtime_error ("Syntax error");
	if (u > 255)
		throw runtime_error ("Invalid char number");
	return static_cast <unsigned char> (u);
}

void readcharset (istream & in)
{
	string str;
	while (readline (in, str) )
	{
		//cerr << str << endl;
		if (str == "DEFAULT")
		{
			if (default_defined)
				throw runtime_error
					("Default already defined");
			//cerr << "Defining default" << endl;
			readchar (in, default_data);
			default_defined= true;
		}
		else
		{
			unsigned char ch= getcharcode (str);
			//cerr << "Defining char: ";
			//if (ch >= 32) cerr << ch;
			//else cerr << static_cast <unsigned int> (ch);
			//cerr << endl;
			if (data_defined [ch] )
				throw runtime_error ("Char already defined");
			readchar (in, data [ch] );
			data_defined [ch]= true;
		}
	}
}

void writecharset (ostream & out, const std::string & name)
{
	if (name.empty () )
		out <<
			"// charset.cpp\n";
	else
		out <<
			"// charset_" << name << ".cpp\n";

	out <<
		"// Automatically generated, do not edit.\n"
		"\n"
		"#include \"charset.h\"\n"
		"\n"
		"const charset::chardataset charset::";

	if (name.empty () )
		out << "default";
	else
		out << name;

	out << "_data= {\n"
	;

	for (int i= 0; i < 256; ++i)
	{
		out << "\t// char " << i << "\n\t{ ";
		chardata * pdata;
		if (data_defined [i] ) pdata= & data [i];
		else pdata= & default_data;
		for (int j= 0; j < 8; ++j)
		{
			out << static_cast <unsigned int> ( (* pdata) [j] );
			if (j < 7) out << ", ";
		}
		out << " },\n";
	}
	out <<

"};\n"
"\n"
"//End of charset.cpp\n"
	;
}

// End of gencharset.cpp
Un proyecto texto-plano.xyz