00001
00002 #include "idep_aliasutil.h"
00003 #include "idep_aliastable.h"
00004 #include "idep_tokeniter.h"
00005 #include "idep_string.h"
00006
00007 #include <fstream>
00008 #include <iostream>
00009 #include <cassert>
00010
00011
00012
00013 static std::ostream& warning(std::ostream& orr, const char *file, int lineno)
00014 {
00015 return orr << "Warning in " << file << '(' << lineno << "): ";
00016 }
00017
00018 static std::ostream& err(std::ostream& orr, const char *file, int lineno)
00019 {
00020 return orr << "Error in " << file << '(' << lineno << "): ";
00021 }
00022
00023 static int tryToAlias(idep_AliasTable *table, std::ostream& orr,
00024 const char *inputName, int lineno,
00025 const char *componentName, const char *alias)
00026 {
00027 if (table->add(alias, componentName) < 0) {
00028 const char *previousName = table->lookup(alias);
00029 err(orr, inputName, lineno) << "two names for alias \""
00030 << alias << "\":" << std::endl << " \"" << previousName
00031 << "\" and \"" << componentName << "\"" << std::endl;
00032 return 1;
00033 }
00034 return 0;
00035 }
00036
00037
00038
00039 int idep_AliasUtil::readAliases(idep_AliasTable *table, std::ostream& orr,
00040 std::istream& in, const char *inputName)
00041 {
00042
00043
00044 enum State {
00045 START,
00046 CONTINUE_0,
00047 IDENT_0,
00048 CONTINUE_1,
00049 CONTINUE_NL,
00050 IDENT_NL,
00051 NEWLINE_BL,
00052 CONTINUE_BL,
00053 IDENT_BL,
00054 NUM_STATES
00055 } state = START;
00056
00057 enum Input {
00058 CONTINUE,
00059 NEWLINE,
00060 IDENT,
00061 NUM_INPUTS
00062 } input;
00063
00064 enum Action {
00065 NOP,
00066 BEG_CUR,
00067 BEG_PRE,
00068 BEG_PRE_CUR,
00069 TRY_CUR,
00070 TRY_PRE,
00071 TRY_PRE_CUR,
00072 END,
00073 NUM_ACTIONS
00074 };
00075
00076 static State nextStateTable[NUM_STATES][NUM_INPUTS] = {
00077
00078 { CONTINUE_0, START, IDENT_0 },
00079 { CONTINUE_1, START, IDENT_NL },
00080 { CONTINUE_1, NEWLINE_BL, IDENT_NL },
00081 { CONTINUE_NL, IDENT_0, IDENT_NL },
00082 { CONTINUE_NL, IDENT_NL, IDENT_NL },
00083 { CONTINUE_NL, START, IDENT_NL },
00084 { CONTINUE_BL, START, IDENT_BL },
00085 { CONTINUE_BL, IDENT_BL, IDENT_BL },
00086 { CONTINUE_BL, NEWLINE_BL, IDENT_BL }
00087 };
00088
00089 static Action actionTable[NUM_STATES][NUM_INPUTS] = {
00090
00091 { NOP, NOP, BEG_CUR },
00092 { BEG_PRE, NOP, BEG_PRE_CUR },
00093 { NOP, NOP, TRY_CUR },
00094 { TRY_PRE, NOP, TRY_PRE_CUR },
00095 { TRY_PRE, NOP, TRY_PRE_CUR },
00096 { NOP, END, TRY_CUR },
00097 { NOP, END, TRY_CUR },
00098 { TRY_PRE, NOP, TRY_PRE_CUR },
00099 { NOP, NOP, TRY_CUR }
00100 };
00101
00102 const char *const EMPTY_NAME = "";
00103 const char NULL_CHAR = *EMPTY_NAME;
00104 const char COMMENT_CHAR = '#';
00105 const char CONTINUE_CHAR = '\\';
00106 const char NEWLINE_CHAR = '\n';
00107
00108 int numBadAliases = 0;
00109 int lineno = 1;
00110
00111 idep_String componentName = EMPTY_NAME;
00112 idep_String lastToken = EMPTY_NAME;
00113 Input lastInput = IDENT;
00114
00115 for (idep_TokenIter it(in); it; ++it) {
00116 if (*it() == COMMENT_CHAR) {
00117 while (*it() != NEWLINE_CHAR) {
00118 ++it;
00119 }
00120 }
00121
00122
00123
00124 switch (*it()) {
00125 case CONTINUE_CHAR: {
00126 input = NULL_CHAR == it()[1] ? CONTINUE : IDENT;
00127 } break;
00128 case NEWLINE_CHAR: {
00129 input = NEWLINE;
00130 } break;
00131 default: {
00132 input = IDENT;
00133 } break;
00134 };
00135
00136
00137
00138 switch (actionTable[state][input]) {
00139 case NOP: {
00140 } break;
00141 case BEG_CUR: {
00142 componentName = it();
00143 } break;
00144 case BEG_PRE: {
00145 componentName = lastToken;
00146 warning(orr, inputName, lineno) << '"' << lastToken
00147 << "\" << used as component name." << std::endl;
00148 } break;
00149 case BEG_PRE_CUR: {
00150 componentName = lastToken;
00151 numBadAliases += tryToAlias(table, orr, inputName, lineno,
00152 componentName, it());
00153 warning(orr, inputName, lineno) << '"' << lastToken
00154 << "\" << used as component name." << std::endl;
00155 } break;
00156 case TRY_CUR: {
00157 numBadAliases += tryToAlias(table, orr, inputName, lineno,
00158 componentName, it());
00159 } break;
00160 case TRY_PRE: {
00161 numBadAliases += tryToAlias(table, orr, inputName, lineno,
00162 componentName, lastToken);
00163 warning(orr, inputName, lineno) << '"' << lastToken
00164 << "\" << used as alias name." << std::endl;
00165 } break;
00166 case TRY_PRE_CUR: {
00167 numBadAliases += tryToAlias(table, orr, inputName, lineno,
00168 componentName, lastToken);
00169 numBadAliases += tryToAlias(table, orr, inputName, lineno,
00170 componentName, it());
00171 warning(orr, inputName, lineno) << '"' << lastToken
00172 << "\" << used as alias name." << std::endl;
00173 } break;
00174 case END: {
00175 componentName = EMPTY_NAME;
00176 } break;
00177 default:
00178 case NUM_ACTIONS: {
00179 assert(0);
00180 }
00181 };
00182
00183
00184
00185 if (NEWLINE == input) {
00186 ++lineno;
00187 }
00188
00189 lastToken = it();
00190 lastInput = input;
00191
00192 state = nextStateTable[state][input];
00193 }
00194
00195 return numBadAliases;
00196 }
00197
00198
00199 int idep_AliasUtil::readAliases(idep_AliasTable *table, std::ostream& orr,
00200 const char *fileName)
00201 {
00202 enum { IOERROR = -1 };
00203 std::ifstream in(fileName);
00204 if (!in) {
00205 return IOERROR;
00206 }
00207 return readAliases(table, orr, in, fileName);
00208 }
00209