2006-05-25 04:32:20 +00:00
|
|
|
/* $Id: main.cc,v 1.53 2006/05/14 13:38:26 helly Exp $ */
|
2006-02-24 04:48:15 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
2006-05-25 04:32:20 +00:00
|
|
|
#elif defined(_WIN32)
|
|
|
|
#include "config_w32.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "globals.h"
|
|
|
|
#include "parser.h"
|
|
|
|
#include "dfa.h"
|
|
|
|
#include "mbo_getopt.h"
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
namespace re2c
|
|
|
|
{
|
|
|
|
|
|
|
|
file_info sourceFileInfo;
|
|
|
|
file_info outputFileInfo;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
bool bFlag = false;
|
2006-05-25 04:32:20 +00:00
|
|
|
bool dFlag = false;
|
|
|
|
bool eFlag = false;
|
|
|
|
bool fFlag = false;
|
|
|
|
bool gFlag = false;
|
|
|
|
bool iFlag = false;
|
|
|
|
bool sFlag = false;
|
|
|
|
bool wFlag = false;
|
|
|
|
|
|
|
|
bool bSinglePass = false;
|
|
|
|
bool bLastPass = false;
|
|
|
|
|
|
|
|
bool bUsedYYAccept = false;
|
|
|
|
bool bUsedYYMaxFill = false;
|
|
|
|
bool bUsedYYMarker = true;
|
|
|
|
|
|
|
|
bool bUseStartLabel= false;
|
|
|
|
bool bUseStateNext = false;
|
|
|
|
bool bUseYYFill = true;
|
|
|
|
|
|
|
|
std::string startLabelName;
|
|
|
|
uint maxFill = 1;
|
|
|
|
uint next_label = 0;
|
|
|
|
uint cGotoThreshold = 9;
|
|
|
|
|
|
|
|
uint topIndent = 0;
|
|
|
|
std::string indString("\t");
|
|
|
|
bool yybmHexTable = false;
|
|
|
|
bool bUseStateAbort = false;
|
|
|
|
bool bWroteGetState = false;
|
|
|
|
|
|
|
|
uint nRealChars = 256;
|
|
|
|
|
|
|
|
uint next_fill_index = 0;
|
|
|
|
uint last_fill_index = 0;
|
|
|
|
std::set<uint> vUsedLabels;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
static char *opt_arg = NULL;
|
|
|
|
static int opt_ind = 1;
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
static const mbo_opt_struct OPTIONS[] =
|
|
|
|
{
|
|
|
|
mbo_opt_struct('?', 0, "help"),
|
|
|
|
mbo_opt_struct('b', 0, "bit-vectors"),
|
|
|
|
mbo_opt_struct('d', 0, "debug-output"),
|
|
|
|
mbo_opt_struct('e', 0, "ecb"),
|
|
|
|
mbo_opt_struct('f', 0, "storable-state"),
|
|
|
|
mbo_opt_struct('g', 0, "computed-gotos"),
|
|
|
|
mbo_opt_struct('h', 0, "help"),
|
|
|
|
mbo_opt_struct('i', 0, "no-debug-info"),
|
|
|
|
mbo_opt_struct('o', 1, "output"),
|
|
|
|
mbo_opt_struct('s', 0, "nested-ifs"),
|
|
|
|
mbo_opt_struct('v', 0, "version"),
|
|
|
|
mbo_opt_struct('V', 0, "vernum"),
|
|
|
|
mbo_opt_struct('w', 0, "wide-chars"),
|
|
|
|
mbo_opt_struct('1', 0, "two-pass"),
|
|
|
|
mbo_opt_struct('-', 0, NULL) /* end of args */
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void usage()
|
|
|
|
{
|
2006-05-25 04:32:20 +00:00
|
|
|
cerr << "usage: re2c [-bdefghisvVw1] [-o file] file\n"
|
|
|
|
"\n"
|
|
|
|
"-? -h --help Display this info.\n"
|
|
|
|
"\n"
|
|
|
|
"-b --bit-vectors Implies -s. Use bit vectors as well in the attempt to\n"
|
|
|
|
" coax better code out of the compiler. Most useful for\n"
|
|
|
|
" specifications with more than a few keywords (e.g. for\n"
|
|
|
|
" most programming languages).\n"
|
|
|
|
"\n"
|
|
|
|
"-d --debug-output Creates a parser that dumps information during\n"
|
|
|
|
" about the current position and in which state the\n"
|
|
|
|
" parser is.\n"
|
|
|
|
"\n"
|
|
|
|
"-e --ecb Cross-compile from an ASCII platform to\n"
|
|
|
|
" an EBCDIC one.\n"
|
|
|
|
"\n"
|
|
|
|
"-f --storable-state Generate a scanner that supports storable states.\n"
|
|
|
|
"\n"
|
|
|
|
"-g --computed-gotos Implies -b. Generate computed goto code (only useable\n"
|
|
|
|
" with gcc).\n"
|
|
|
|
"\n"
|
|
|
|
"-i --no-debug-info Do not generate '#line' info (usefull for versioning).\n"
|
|
|
|
"\n"
|
|
|
|
"-o --output=output Specify the output file instead of stdout\n"
|
|
|
|
" This cannot be used together with -e switch.\n"
|
|
|
|
"\n"
|
|
|
|
"-s --nested-ifs Generate nested ifs for some switches. Many compilers\n"
|
|
|
|
" need this assist to generate better code.\n"
|
|
|
|
"\n"
|
|
|
|
"-v --version Show version information.\n"
|
|
|
|
"-V --vernum Show version as one number.\n"
|
|
|
|
"\n"
|
|
|
|
"-w --wide-chars Create a parser that supports wide chars (UCS-2). This\n"
|
|
|
|
" implies -s and cannot be used together with -e switch.\n"
|
|
|
|
"\n"
|
|
|
|
"-1 --single-pass Force single pass generation, this cannot be combined\n"
|
|
|
|
" with -f and disables YYMAXFILL generation prior to last\n"
|
|
|
|
" re2c block.\n"
|
|
|
|
;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
} // end namespace re2c
|
|
|
|
|
|
|
|
using namespace re2c;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int c;
|
2006-05-25 04:32:20 +00:00
|
|
|
const char *sourceFileName = 0;
|
|
|
|
const char *outputFileName = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
if (argc == 1)
|
|
|
|
{
|
2006-02-24 04:48:15 +00:00
|
|
|
usage();
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
while ((c = mbo_getopt(argc, argv, OPTIONS, &opt_arg, &opt_ind, 0)) != -1)
|
|
|
|
{
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case 'b':
|
2006-05-25 04:32:20 +00:00
|
|
|
bFlag = true;
|
|
|
|
sFlag = true;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case 'e':
|
2006-05-25 04:32:20 +00:00
|
|
|
xlat = asc2ebc;
|
|
|
|
talx = ebc2asc;
|
|
|
|
eFlag = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
dFlag = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'f':
|
|
|
|
fFlag = true;
|
|
|
|
if (bSinglePass) {
|
|
|
|
std::cerr << "re2c: error: cannot combine -1 and -f switch\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
gFlag = true;
|
|
|
|
bFlag = true;
|
|
|
|
sFlag = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
iFlag = true;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case 'o':
|
2006-05-25 04:32:20 +00:00
|
|
|
outputFileName = opt_arg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
sFlag = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '1':
|
|
|
|
if (bFlag) {
|
|
|
|
std::cerr << "re2c: error: cannot combine -1 and -f switch\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
bSinglePass = true;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case 'v':
|
2006-05-25 04:32:20 +00:00
|
|
|
cout << "re2c " << PACKAGE_VERSION << "\n";
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
case 'V': {
|
|
|
|
string vernum(PACKAGE_VERSION);
|
|
|
|
|
|
|
|
if (vernum[1] == '.')
|
|
|
|
{
|
|
|
|
vernum.insert(0, "0");
|
|
|
|
}
|
|
|
|
vernum.erase(2, 1);
|
|
|
|
if (vernum[3] == '.')
|
|
|
|
{
|
|
|
|
vernum.insert(2, "0");
|
|
|
|
}
|
|
|
|
vernum.erase(4, 1);
|
|
|
|
if (vernum.length() < 6 || vernum[5] < '0' || vernum[5] > '9')
|
|
|
|
{
|
|
|
|
vernum.insert(4, "0");
|
|
|
|
}
|
|
|
|
vernum.resize(6);
|
|
|
|
cout << vernum << endl;
|
2006-02-24 04:48:15 +00:00
|
|
|
return 2;
|
2006-05-25 04:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case 'w':
|
|
|
|
nRealChars = (1<<16);
|
|
|
|
sFlag = true;
|
|
|
|
wFlag = true;
|
|
|
|
break;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
case 'h':
|
|
|
|
case '?':
|
|
|
|
default:
|
2006-05-25 04:32:20 +00:00
|
|
|
usage();
|
|
|
|
return 2;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
if (wFlag && eFlag)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-25 04:32:20 +00:00
|
|
|
usage();
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
else if (argc == opt_ind + 1)
|
|
|
|
{
|
|
|
|
sourceFileName = argv[opt_ind];
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
usage();
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
// set up the source stream
|
|
|
|
re2c::ifstream_lc source;
|
|
|
|
|
|
|
|
if (sourceFileName[0] == '-' && sourceFileName[1] == '\0')
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-25 04:32:20 +00:00
|
|
|
if (fFlag)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-25 04:32:20 +00:00
|
|
|
std::cerr << "re2c: error: multiple /*!re2c stdin is not acceptable when -f is specified\n";
|
2006-02-24 04:48:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2006-05-25 04:32:20 +00:00
|
|
|
sourceFileName = "<stdin>";
|
|
|
|
source.open(stdin);
|
|
|
|
}
|
|
|
|
else if (!source.open(sourceFileName).is_open())
|
|
|
|
{
|
|
|
|
cerr << "re2c: error: cannot open " << sourceFileName << "\n";
|
|
|
|
return 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// set up the output stream
|
2006-05-25 04:32:20 +00:00
|
|
|
re2c::ofstream_lc output;
|
|
|
|
|
|
|
|
if (outputFileName == 0 || (sourceFileName[0] == '-' && sourceFileName[1] == '\0'))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
outputFileName = "<stdout>";
|
2006-05-25 04:32:20 +00:00
|
|
|
output.open(stdout);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2006-05-25 04:32:20 +00:00
|
|
|
else if (!output.open(outputFileName).is_open())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-25 04:32:20 +00:00
|
|
|
cerr << "re2c: error: cannot open " << outputFileName << "\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
Scanner scanner(sourceFileName, source, output);
|
|
|
|
sourceFileInfo = file_info(sourceFileName, &scanner);
|
|
|
|
outputFileInfo = file_info(outputFileName, &output);
|
|
|
|
|
|
|
|
if (!bSinglePass)
|
|
|
|
{
|
|
|
|
bUsedYYMarker = false;
|
|
|
|
|
|
|
|
re2c::ifstream_lc null_source;
|
|
|
|
|
|
|
|
if (!null_source.open(sourceFileName).is_open())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-05-25 04:32:20 +00:00
|
|
|
cerr << "re2c: error: cannot re-open " << sourceFileName << "\n";
|
2006-02-24 04:48:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2006-05-25 04:32:20 +00:00
|
|
|
|
|
|
|
null_stream null_dev;
|
|
|
|
Scanner null_scanner(sourceFileName, null_source, null_dev);
|
|
|
|
parse(null_scanner, null_dev);
|
|
|
|
next_label = 0;
|
|
|
|
next_fill_index = 0;
|
|
|
|
Symbol::ClearTable();
|
|
|
|
bWroteGetState = false;
|
|
|
|
bUsedYYMaxFill = false;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-05-25 04:32:20 +00:00
|
|
|
bLastPass = true;
|
|
|
|
parse(scanner, output);
|
2006-02-24 04:48:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|