/** * @file lsts2pn.C * TVT LSTS to Maria Petri net translator */ /* * Copyright © 2001 Kimmo Varpaaniemi * Copyright © 2001,2002,2003 Marko Mäkelä * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "InOutStream.hh" #include "Header.hh" #include "ActionNamesAP.hh" #include "TransitionsAP.hh" #include "DivBitsAP.hh" #include "StatePropsAP.hh" #include "StateNamesAP.hh" #if TVT_VERSION >= 2002000L # include "iLSTS_File.hh" # define LSTS_File iLSTS_File # define ActionNamesAP iActionNamesAP # define StatePropsAP iStatePropsAP # define TransitionsAP iTransitionsAP #else # include "LSTS_File.hh" #endif #include using std::string; using std::cout; using std::cerr; static const lsts_index_t lsts_index_magic = lsts_index_t (~lsts_index_t (0)); #define TYPE_PREFIX "\\1_" #define PLACE_PREFIX "\\2_" #define ARRAY_PREFIX "\\3_" #define INVIS_PREFIX "\\4_" /** Encapsulate the special characters in a character string * @param escaped target string for the encapsulated copy * @param source source string to be encapsulated and copied */ static void escape (string& escaped, const string& source) { /** original and escaped length, and an index */ string::size_type len = source.length (), elen, i; for (i = len, elen = 0; i--; elen++) { register const char c = source[i]; if ((c >= 0 && c < 040) || (c >= char (0200) && c < char (0240)) || c == 0177 || c == '^' || c == '\\' || c == '"') elen++; } escaped.assign (elen, 0); for (i = elen = 0; i < len; i++, elen++) { register const char c = source[i]; if ((c >= 0 && c < 040) || (c >= char (0200) && c < char (0240)) || c == 0177 || c == '^') { escaped.replace (elen++, 1, 1, '^'); if (c == '^') escaped.replace (elen, 1, 1, '!'); else if (c >= 0 && c < 040) escaped.replace (elen, 1, 1, c | '@'); else if (c == 0177) escaped.replace (elen, 1, 1, '?'); else if (c == char (0237)) escaped.replace (elen, 1, 1, '#'); else escaped.replace (elen, 1, 1, (c & ~0200) | '`'); continue; } else if (c == '\\' || c == '"') escaped.replace (elen++, 1, 1, '\\'); escaped.replace (elen, 1, 1, c); } } class ActionNamesReader : public ActionNamesAP { public: ActionNamesReader (); void lsts_StartActionNames (class Header& hea); void lsts_ActionName (lsts_index_t action_number, const string& action_name); void lsts_EndActionNames (); void lsts_SetComponent (lsts_index_t component); void lsts_Conclude (); bool lsts_called; lsts_index_t lsts_component; class Header* lsts_header; lsts_index_t lsts_actcnt; string* lsts_actlbls; bool* lsts_actold; }; class StatePropsReader : public StatePropsAP { public: StatePropsReader (); void lsts_StartStateProps (class Header& hea); void lsts_StartPropStates (const string& prop_name); void lsts_PropState (lsts_index_t state); void lsts_EndPropStates (const string& prop_name); void lsts_EndStateProps (); void lsts_SetComponent (lsts_index_t component); void lsts_Conclude (); void lsts_Force (class Header& hea); void lsts_Echo (); bool lsts_called; bool tokenDeclared; lsts_index_t lsts_component; class Header* lsts_header; lsts_index_t lsts_propcnt; bool* lsts_proptruths; string* lsts_proplbls; #ifndef RELABEL_PROPS typedef std::set p_names_t; p_names_t props_passed; #endif }; class TransitionsReader : public TransitionsAP { public: TransitionsReader (); void lsts_StartTransitions (class Header& hea); void lsts_StartTransitionsFromState (lsts_index_t start_state); void lsts_Transition (lsts_index_t start_state, lsts_index_t destination_state, lsts_index_t action); void lsts_EndTransitionsFromState (lsts_index_t start_state); void lsts_EndTransitions (); void lsts_SetComponent (lsts_index_t component); void lsts_Conclude (class ActionNamesReader* act, class StatePropsReader* pro); bool lsts_called; lsts_index_t lsts_component; class Header* lsts_header; lsts_index_t lsts_counter; lsts_index_t lsts_latest_source; lsts_index_t lsts_cumulative; lsts_index_t* lsts_rawtr; lsts_index_t* lsts_movecnts; lsts_index_t** lsts_source; lsts_index_t** lsts_dest; }; ActionNamesReader::ActionNamesReader () : ActionNamesAP (), lsts_called (false), lsts_component (lsts_index_magic), lsts_header (0), lsts_actcnt (0), lsts_actlbls (0), lsts_actold (0) { } void ActionNamesReader::lsts_StartActionNames (class Header& hea) { lsts_called = true; lsts_header = &hea; } void ActionNamesReader::lsts_ActionName (lsts_index_t action_number, const string& action_name) { if (!lsts_actlbls) { const lsts_index_t cnt = lsts_header->GiveActionCnt (); lsts_actlbls = new string[cnt]; lsts_actold = new bool[cnt]; memset (lsts_actold, 0, cnt * sizeof *lsts_actold); } assert (action_number >= 1); assert (action_number <= lsts_header->GiveActionCnt ()); assert (!lsts_actold[action_number - 1]); escape (lsts_actlbls[action_number - 1], action_name); lsts_actold[action_number - 1] = true; lsts_actcnt++; } void ActionNamesReader::lsts_EndActionNames () { assert (lsts_header->GiveActionCnt () == lsts_actcnt); if (lsts_actold) { delete[] lsts_actold; lsts_actold = 0; } } void ActionNamesReader::lsts_SetComponent (lsts_index_t component) { lsts_component = component; } void ActionNamesReader::lsts_Conclude () { if (lsts_called) { lsts_called = false; if (lsts_actlbls) { delete[] lsts_actlbls; lsts_actlbls = 0; } lsts_actcnt = 0; lsts_header = 0; } lsts_component = lsts_index_magic; } StatePropsReader::StatePropsReader () : StatePropsAP (), lsts_called (false), tokenDeclared (false), lsts_component (lsts_index_magic), lsts_header (0), lsts_propcnt (0), lsts_proptruths (0), lsts_proplbls (0) { } void StatePropsReader::lsts_StartStateProps (class Header& hea) { lsts_called = true; lsts_header = &hea; lsts_Echo (); } void StatePropsReader::lsts_StartPropStates (const string& prop_name) { assert (lsts_propcnt < lsts_header->GiveStatePropCnt ()); if (!lsts_proptruths) { lsts_proptruths = new bool[lsts_header->GiveStateCnt ()]; if (!tokenDeclared) { tokenDeclared = true; cout << "#ifdef EXPLICIT\n" "typedef struct {} \"" TYPE_PREFIX "token\";\n" "#endif\n"; } cout << "typedef bool[\"" TYPE_PREFIX << lsts_component << "\"] \"" TYPE_PREFIX "tbl_" << lsts_component << "\";\n"; } for (lsts_index_t staind = lsts_header->GiveStateCnt (); staind;) { staind--; lsts_proptruths[staind] = false; } if (!lsts_proplbls) lsts_proplbls = new string[lsts_header->GiveStatePropCnt ()]; escape (lsts_proplbls[lsts_propcnt], prop_name); #ifndef RELABEL_PROPS std::pair p = props_passed.insert (lsts_proplbls[lsts_propcnt]); if (!p.second) { cerr << "Proposition label \"" << lsts_proplbls[lsts_propcnt] << "\" re-encountered\n"; exit(1); } #endif } void StatePropsReader::lsts_PropState (lsts_index_t state) { assert (lsts_propcnt < lsts_header->GiveStatePropCnt ()); assert (state >= 1); assert (state <= lsts_header->GiveStateCnt ()); lsts_proptruths[state - 1] = true; } void StatePropsReader::lsts_EndPropStates (const string& prop_name) { assert (lsts_propcnt < lsts_header->GiveStatePropCnt ()); assert (lsts_header->GiveInitialState () >= 1); assert (lsts_header->GiveInitialState () <= lsts_header->GiveStateCnt ()); #ifndef NDEBUG { string prop_esc; escape (prop_esc, prop_name); assert (prop_esc == lsts_proplbls[lsts_propcnt]); } #endif // NDEBUG cout << "#ifdef EXPLICIT\n" "place \"" PLACE_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << lsts_proplbls[lsts_propcnt] << "\" (0..1) \"" TYPE_PREFIX "token\""; if (lsts_proptruths[lsts_header->GiveInitialState () - 1]) cout << ": {}"; cout << ";\n" "#endif\n" "\"" TYPE_PREFIX "tbl_" << lsts_component << "\" \"" ARRAY_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << lsts_proplbls[lsts_propcnt] << "\" = {\n"; for (lsts_index_t staind = 0; staind != lsts_header->GiveStateCnt (); staind++) { if (staind) cout << ",\n"; cout << "/* " << staind + 1 << " */ "; if (lsts_proptruths[staind]) cout << "true"; else cout << "false"; } cout << " };\n" "prop \""; #ifdef RELABEL_PROPS cout << '_' << lsts_component << '_'; #endif cout << lsts_proplbls[lsts_propcnt] << "\":\n" "#ifdef EXPLICIT\n" "(is \"" TYPE_PREFIX "token\" {}) equals place \"" PLACE_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << lsts_proplbls[lsts_propcnt] << "\"\n" "#else\n" "true equals map j { place \"" PLACE_PREFIX << lsts_component << "\" } \"" ARRAY_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << lsts_proplbls[lsts_propcnt] << "\"[j]\n" "#endif\n" ";\n"; lsts_propcnt++; } void StatePropsReader::lsts_EndStateProps () { assert (lsts_header->GiveStatePropCnt () == lsts_propcnt); } void StatePropsReader::lsts_SetComponent (lsts_index_t component) { lsts_component = component; } void StatePropsReader::lsts_Conclude () { if (lsts_called) { lsts_called = false; if (lsts_proplbls) { delete[] lsts_proplbls; lsts_proplbls = 0; } if (lsts_proptruths) { delete[] lsts_proptruths; lsts_proptruths = 0; } lsts_header = 0; lsts_propcnt = 0; } lsts_component = lsts_index_magic; } void StatePropsReader::lsts_Force (class Header& hea) { if (!lsts_called) { lsts_header = &hea; assert (0 == lsts_header->GiveStatePropCnt ()); lsts_Echo (); lsts_header = 0; } } void StatePropsReader::lsts_Echo () { assert ((lsts_header->GiveInitialState () >= 1) && (lsts_header->GiveInitialState () <= lsts_header->GiveStateCnt ())); cout << "typedef unsigned (1 .. " << lsts_header->GiveStateCnt () << ") \"" TYPE_PREFIX << lsts_component << "\";\n" "place \"" PLACE_PREFIX << lsts_component << "\" (1) \"" TYPE_PREFIX << lsts_component << "\": " << lsts_header->GiveInitialState () << ";\n"; } TransitionsReader::TransitionsReader () : TransitionsAP (), lsts_called (false), lsts_component (lsts_index_magic), lsts_header (0), lsts_counter (0), lsts_latest_source (lsts_index_magic), lsts_cumulative (0), lsts_rawtr (0), lsts_movecnts (0), lsts_source (0), lsts_dest (0) { } void TransitionsReader::lsts_StartTransitions (class Header& hea) { lsts_called = true; lsts_header = &hea; } void TransitionsReader::lsts_StartTransitionsFromState (lsts_index_t start_state) { assert (lsts_counter < 2 * (lsts_header->GiveStateCnt () + lsts_header->GiveTransitionCnt ())); assert (start_state >= 1); assert (start_state <= lsts_header->GiveStateCnt ()); if (!lsts_rawtr) lsts_rawtr = new lsts_index_t[2 * (lsts_header->GiveStateCnt () + lsts_header->GiveTransitionCnt ())]; lsts_latest_source = start_state; lsts_rawtr[lsts_counter++] = start_state; } void TransitionsReader::lsts_Transition (lsts_index_t start_state, lsts_index_t destination_state, lsts_index_t action) { assert (lsts_counter + 1 < 2 * (lsts_header->GiveStateCnt () + lsts_header->GiveTransitionCnt ())); assert (start_state == lsts_latest_source); assert (destination_state >= 1); assert (destination_state <= lsts_header->GiveStateCnt ()); assert (action <= lsts_header->GiveActionCnt ()); lsts_rawtr[lsts_counter++] = destination_state; lsts_rawtr[lsts_counter++] = action; if (!lsts_movecnts) { lsts_movecnts = new lsts_index_t[lsts_header->GiveActionCnt () + 1]; lsts_source = new lsts_index_t*[lsts_header->GiveActionCnt () + 1]; lsts_dest = new lsts_index_t*[lsts_header->GiveActionCnt () + 1]; for (lsts_index_t actind = lsts_header->GiveActionCnt () + 1; actind;) { actind--; lsts_movecnts[actind] = 0; lsts_source[actind] = 0; lsts_dest[actind] = 0; } } lsts_movecnts[action]++; lsts_cumulative++; } void TransitionsReader::lsts_EndTransitionsFromState (lsts_index_t start_state) { assert ((lsts_counter < 2 * (lsts_header->GiveStateCnt () + lsts_header->GiveTransitionCnt ())) && (start_state == lsts_latest_source)); lsts_rawtr[lsts_counter++] = lsts_index_magic; } void TransitionsReader::lsts_EndTransitions () { lsts_index_t actind; assert (lsts_header->GiveTransitionCnt () == lsts_cumulative); for (actind = lsts_header->GiveActionCnt () + 1; actind;) { actind--; if (lsts_movecnts && lsts_movecnts[actind]) { lsts_source[actind] = new lsts_index_t[lsts_movecnts[actind]]; lsts_dest[actind] = new lsts_index_t[lsts_movecnts[actind]]; lsts_movecnts[actind] = 0; } } for (lsts_index_t trind = 0; trind != lsts_counter; trind++) { lsts_index_t source_state = lsts_rawtr[trind]; for (trind++; lsts_rawtr[trind] != lsts_index_magic; trind += 2) { actind = lsts_rawtr[trind + 1]; lsts_source[actind][lsts_movecnts[actind]] = source_state; lsts_dest[actind][lsts_movecnts[actind]] = lsts_rawtr[trind]; lsts_movecnts[actind]++; } } lsts_counter = 0; if (lsts_rawtr) { delete[] lsts_rawtr; lsts_rawtr = 0; } } void TransitionsReader::lsts_SetComponent (lsts_index_t component) { lsts_component = component; } void TransitionsReader::lsts_Conclude (class ActionNamesReader* act, class StatePropsReader* pro) { if (lsts_called) { lsts_index_t actind; lsts_called = false; assert ((lsts_header->GiveActionCnt () == act->lsts_actcnt) && (lsts_header->GiveStatePropCnt () == pro->lsts_propcnt)); for (actind = 1 /* 0 skipped intentionally */; actind <= act->lsts_actcnt; actind++) { if ((!lsts_movecnts) || !lsts_movecnts[actind]) cout << "trans \"" << act->lsts_actlbls[actind - 1] << "\" gate false;\n"; } if (lsts_movecnts) { unsigned turn; for (actind = 0; actind <= act->lsts_actcnt; actind++) { if (!lsts_movecnts[actind]) continue; cout << "typedef unsigned (0 .. " << lsts_movecnts[actind] - 1 << ") \"" TYPE_PREFIX "ind_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\";\n"; } for (actind = 0; actind <= act->lsts_actcnt; actind++) { if (lsts_movecnts[actind]) { cout << "place \"" PLACE_PREFIX "ref_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\" (#\"" TYPE_PREFIX "ind_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\") \"" TYPE_PREFIX "ind_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\" const: \"" TYPE_PREFIX "ind_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\" k: k;\n"; } } for (actind = 0; actind <= act->lsts_actcnt; actind++) { if (lsts_movecnts[actind]) { cout << "typedef \"" TYPE_PREFIX << lsts_component << "\"[\"" TYPE_PREFIX "ind_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\"] \"" TYPE_PREFIX "arr_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\";\n"; } } for (actind = 0; actind <= act->lsts_actcnt; actind++) { if (lsts_movecnts[actind]) { for (turn = 0; turn < 2; turn++) { cout << "\"" TYPE_PREFIX "arr_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\" \"" ARRAY_PREFIX; if (turn) cout << "target"; else cout << "source"; cout << '_' << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\" = {\n"; for (lsts_index_t trind = 0; trind != lsts_movecnts[actind]; trind++) { if (trind) cout << ",\n"; cout << "/* " << trind << " */ "; if (turn) cout << lsts_dest[actind][trind]; else cout << lsts_source[actind][trind]; } cout << " };\n"; } } } for (actind = 0; actind <= act->lsts_actcnt; actind++) { if (lsts_movecnts[actind]) { cout << "trans \""; if (actind) cout << act->lsts_actlbls[actind - 1]; else cout << INVIS_PREFIX << lsts_component; cout << "\"\n"; if (actind) { cout << " { hide \"" TYPE_PREFIX "ind_" << lsts_component << '_' << act->lsts_actlbls[actind - 1] << "\" k" << lsts_component << "; }\n"; } for (turn = 0; turn < 2; turn++) { if (turn) cout << "\n out"; else cout << " in "; cout << " { \"" PLACE_PREFIX "ref_" << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\": k" << lsts_component << ";\n" " \"" PLACE_PREFIX << lsts_component << "\": \"" ARRAY_PREFIX; if (turn) cout << "target"; else cout << "source"; cout << '_' << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\"[k" << lsts_component << "];"; if (pro->lsts_propcnt) { cout << "\n#ifdef EXPLICIT\n"; for (lsts_index_t propind = 0; propind != pro->lsts_propcnt; propind++) { cout << " \"" PLACE_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << pro->lsts_proplbls[propind] << "\":\n" << " ( \"" ARRAY_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << pro->lsts_proplbls[propind] << "\"[\"" ARRAY_PREFIX; if (turn) cout << "target"; else cout << "source"; cout << '_' << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\"[k" << lsts_component << "]]\n" << " && !\"" ARRAY_PREFIX; #ifdef RELABEL_PROPS cout << lsts_component << '_'; #endif cout << pro->lsts_proplbls[propind] << "\"[\"" ARRAY_PREFIX; if (turn) cout << "source"; else cout << "target"; cout << '_' << lsts_component; if (actind) cout << '_' << act->lsts_actlbls[actind - 1]; cout << "\"[k" << lsts_component << "]]) # {};\n"; } cout << "#endif\n"; } cout << " }"; } if (!actind) cout << " hide true"; cout << ";\n"; delete[] (lsts_source[actind]); lsts_source[actind] = 0; delete[] (lsts_dest[actind]); lsts_dest[actind] = 0; } } delete[] lsts_movecnts; lsts_movecnts = 0; delete[] lsts_source; lsts_source = 0; delete[] lsts_dest; lsts_dest = 0; } lsts_cumulative = 0; lsts_header = 0; } lsts_component = lsts_index_magic; } int main (int argc, char** argv) { class InStream inp; class ActionNamesReader act; class TransitionsReader tra; class StatePropsReader pro; lsts_index_t cnent = 0; for (int k = 1; k < argc; k++, cnent++) { class InStream& is = inp.OpenInputFile (argv[k]); class LSTS_File lsts (is, true); #if TVT_VERSION >= 2002000L lsts.SkipUnwantedSections (true); #else lsts.SkipDivBits (); lsts.SkipAccSets (); lsts.SkipStateNames (); #endif lsts.AddActionNamesReader (act); lsts.AddTransitionsReader (tra); lsts.AddStatePropsReader (pro); act.lsts_SetComponent (cnent); tra.lsts_SetComponent (cnent); pro.lsts_SetComponent (cnent); lsts.ReadFile (); pro.lsts_Force (lsts.GiveHeader ()); is.CloseFile (); tra.lsts_Conclude (&act, &pro); act.lsts_Conclude (); pro.lsts_Conclude (); } return 0; }