import java.util.Hashtable; import java.util.Vector; import Jakarta.util.FixDosOutputStream; import java.io.*; class Utility { // this method decides whether to translate the parent state machine file // (and hence regenerate its .ser file. It returns true if a retranslation // (i.e., recursive invocation of parse) is needed public static boolean retranslate( String serfilename, String jakfilename ) { // Step 1: get a handle to both files File ser = null; File jak = null; try { ser = new File( serfilename ); jak = new File( jakfilename ); } catch ( Exception e ) { AstNode.fatalError( e.getMessage() ); } // Step 2: check to see if both exist boolean serExists = false; boolean jakExists = false; try { serExists = ser.exists(); jakExists = jak.exists(); } catch ( Exception e ) { AstNode.fatalError( e.getMessage() ); } // Step 3: get the modification times of both files long serTime = 0; long jakTime = 0; try { if ( serExists ) serTime = ser.lastModified(); if ( jakExists ) jakTime = jak.lastModified(); } catch ( Exception e ) { AstNode.fatalError( e.getMessage() ); } // Step 4: we must retranslate the .jak file (and thus regenerate // the .ser file if (the .ser file does not exist) OR // the jakfile was modified after the serfile boolean retrans = !serExists || jakTime > serTime; // Step 5: if the .jak file doesn't exist AND we have to retranslate, // we have a fundamental problem -- we can't translate // a non-existant file to produce a .ser file. // Note: it is possible that a .ser file exists but no .jak // file -- this happens when a single .jak file defines multiple // state machines, listed in ancestor order. In this way, // parent state machines are translated first, and thus their // .ser files will exist even though there is no .jak file, per se, // that uniquely identifies parent state machines if ( retrans && !jakExists ) { AstNode.fatalError( "parent state machine in " + jakfilename + " does not exist" ); } return retrans; } static String FileName( String n, String extension ) { String filename = n + extension; if ( kernelConstants.globals().sm4vars.ser_directory != null ) filename = kernelConstants.globals().sm4vars.ser_directory + File.separatorChar + filename; return filename; } static String SerFileName( String n ) { return FileName( n, sm4data.serExtension ); } static String JakFileName( String n ) { // there are two ways of determining the extension of a jak file. // we will first use the currentFileExt, and if that fails, // default to the jakExtension set on the command-line (defaulting to .jak) String f = FileName( n, kernelConstants.globals().currentFileExt ); try { File fl = new File(f); if (fl.exists()) return f; } catch (Exception e) { /* ignore errors */ } return FileName( n, kernelConstants.jakExtension ); } static String SourceName() { // for reporting errors return "In State Machine " + kernelConstants.globals().sm4vars.Sm.name + ": "; } // this method either reads a previously built .ser file, or // invokes the parser to retranslate the .jak file public static sdInfo LocateSuperSmFile() { // Step 1: get the file names for the .jak and .ser files String jakFile = JakFileName( kernelConstants.globals().sm4vars.Sm.superSm_name ); String serFile = SerFileName( kernelConstants.globals().sm4vars.Sm.superSm_name ); // Step 2: retranslate if necessary if ( retranslate( serFile,jakFile ) ) { Main.instance.processing( "jak2java", jakFile ); } // Step 3: now read the ser file return ( sdInfo ) readObjectFromFile( serFile ); } static void writeObjectToFile( Object o, String filename ) { ObjectOutputStream os = null; try { os = new ObjectOutputStream( new FileOutputStream( filename ) ); } catch( Exception e ) { AstNode.fatalError( "writeObjectToFile(.., " + filename + e.getMessage() ); } try { os.writeObject( o ); os.close(); } catch( Exception e ) { AstNode.fatalError( e.getMessage() ); } // write is successful. Now write object to $TEqn.kernelConstants.globals().sm4vars.serCache kernelConstants.globals().sm4vars.serCache.put( filename, o ); } static Object readObjectFromFile( String filename ) { ObjectInputStream is = null; // first, see if object exists in the $TEqn.kernelConstants.globals().sm4vars.serCache. If so, // return it, else read from file. Object o = kernelConstants.globals().sm4vars.serCache.get( filename ); if ( o != null ) return o; try { is = new ObjectInputStream( new FileInputStream( filename ) ); o = is.readObject(); is.close(); } catch ( Exception e ) { AstNode.fatalError( e.getMessage() ); } // finally, put the object in the cache kernelConstants.globals().sm4vars.serCache.put( filename, o ); return o; } }