implementation module UpdateObject; /* from StdMisc import abort; from StdBool import not, ||, &&; from StdInt import <; import StdClass; */ import StdEnv; import ExtString; import ExtFile; import DLState; import target; import State; import UnknownModuleOrSymbol; //1.3 from deltaIOState import FileEnv; from deltaEventIO import IOState; import Directory; //3.1 /*2.0 from deltaIOState import class FileEnv, instance FileEnv (IOState s); from StdLibMisc import ::Date(..), ::Time(..); import Directory; 0.2*/ import pdUpdateObject; //import DebugUtilities; /* GenerateObject It is checked that the object module exists (as a separate object module or as part of a static library). Only object modules *without* extension (i.e. not having an .obj or .lib) are updated. Improvemtents: - eliminating the Directory-module which requires conversions from strings to its own representation of paths which creates unnecessary garbage. */ GenerateObject :: !String !*State !*DLClientState !*DLServerState !(IOState s) -> !(!Bool,!String,[ModuleOrSymbolUnknown],[String],!*State,!*DLClientState,!*DLServerState,!(IOState s)); GenerateObject module_path_name state dl_client_state=:{target={target_vers,target_cgen}} dl_server_state=:{application_path} io #! (path_file,extension) = ExtractPathFileAndExtension module_path_name; // an .obj- or .lib-file | extension == "obj" || extension == "lib" // check whether file exists #! ((ok,obj_or_lib_file),io) = accFiles (pd_StringToPath module_path_name) io; | not ok = abort ("GenerateObject: internal error during path conversion"); # ((obj_or_lib_error,_),io) = accFiles (getFileInfo obj_or_lib_file) io; = (obj_or_lib_error == NoDirError,module_path_name,[],[],state,dl_client_state,dl_server_state,io); | extension <> "" = abort ("GenObj3 (internal error): extension not permitted <" +++ extension +++ ">"); // (re)create the file_name with the {.abc,.o}-extensions // collect .abc info #! abc_path_file = path_file +++ ".abc"; #! ((ok,abc_file),io) = accFiles (pd_StringToPath abc_path_file) io; | /*F ("GenerateObject: " +++ abc_path_file)*/ not ok = abort ("DynamicLink (GenObj): something went wrong during path conversion 1"); // collect .o info #! o_path_file = path_file +++ ".o"; #! ((ok,o_file),io) = accFiles (pd_StringToPath o_path_file) io; | /*F ("GenerateObject: " +++ o_path_file)*/ not ok = abort ("DynamicLink (GenObj): something went wrong during path conversion 2"); // get the file info # ((abc_dir_error,abc_file_info),io) = accFiles (getFileInfo abc_file) io; # ((o_dir_error,o_file_info),io) = accFiles (getFileInfo o_file) io; | (abc_dir_error == DoesntExist) && (o_dir_error == DoesntExist) // given path was invalid; pop up a dialogue = (False,"abc & o do not exists",[],[],state,dl_client_state,dl_server_state,io); | (abc_dir_error == DoesntExist) && (o_dir_error <> DoesntExist) // only .o exists; assume it to be up-to-date = (True,o_path_file,[],[],state,dl_client_state,dl_server_state,io); // .abc-file exists #! ((ok,offered_version,objs,libs,state),io) = accFiles (read_abc_info abc_path_file state) io; | not ok #! message = "failed to open '" +++ abc_path_file +++ "'"; = (False,"1",[],[],AddMessage (LinkerWarning message) state,dl_client_state,dl_server_state,io); // check .abc-file version with required version | target_vers <> offered_version #! message = "incorrect version of file '" +++ abc_path_file +++ "'"; = (False,"2",[],[],AddMessage (LinkerWarning message) state,dl_client_state,dl_server_state,io); // .abc-file with correct version number | (o_dir_error == DoesntExist) // .o does *not* exist; generate a new .o = generate_abc_file module_path_name o_path_file objs libs state dl_client_state dl_server_state io; // both extensions of the file exist. is .o out of date? #! abc_datetime = abc_file_info.pi_fileInfo.lastModified; # o_datatime = o_file_info.pi_fileInfo.lastModified; #! (older,equal) = older_than_or_equal abc_datetime o_datatime; | (not older && not equal) // .abc is newer as its corresponding .o = generate_abc_file module_path_name o_path_file objs libs state dl_client_state dl_server_state io; // .o is up-to-date = (True,o_path_file,objs,libs,state,dl_client_state,dl_server_state,io); where { /* // winos generate_abc_file :: !String !String [ModuleOrSymbolUnknown] [String] !*State !*DLClientState !*DLServerState !(IOState s) -> !(!Bool,!String,[ModuleOrSymbolUnknown],[String],!*State,!*DLClientState,!*DLServerState,!(IOState s)); generate_abc_file module_path_name o_path_file objs libs state dl_client_state=:{cgpath} dl_server_state=:{application_path} io #! cgpath_without_terminating_null = cgpath % (0,size cgpath - 2) #! cmdline = cgpath_without_terminating_null +++ " \"" +++ module_path_name +++ "\"\0"; = (GenerateObjectFileOld cgpath cmdline,o_path_file,objs,libs,state,dl_client_state,dl_server_state,io); */ read_abc_info :: !{#Char} !*State !*Files -> *((!Bool,!Int,[ModuleOrSymbolUnknown],[{#Char}],!*State),!*Files); read_abc_info abc_path_file state files // open .abc #! (ok,abc_file,files) = fopen abc_path_file FReadText files; | not ok #! message = "failed to open '" +++ abc_path_file +++ "'"; = ((False,0,[],[],AddMessage (LinkerWarning message) state),files); // collect info #! (abc_file,version,objs,libs,state,files) = collect_abc_info abc_file 0 [] [] state files; // close .abc #! (_,files) = fclose abc_file files; = ((True,version,objs,libs,state),files); where { // (path_prefix,_) // = ExtractPathAndFile abc_path_file; collect_abc_info abc_file version objs libs state files #! (line,abc_file) = freadline abc_file; // reached end of info block? #! (found,i) = starts ".endinfo" line; | found = (abc_file,version,objs,libs,state,files); // version? #! (found,i_comp) = starts ".comp " line; | found #! (ok,space_index) = CharIndex line i_comp ' '; #! version_number = toInt (line % (i_comp,dec space_index)); = collect_abc_info abc_file version_number objs libs state files; // imported object? #! (found,i_impobj) = starts ".impobj \"" line; | found #! obj = line % (i_impobj,size line - 3); = collect_abc_info abc_file version [ModuleUnknown (/*path_prefix +++ toString path_separator +++ */ strip_abc_and_o_extension obj) "":objs] libs state files; // imported (dynamic) library? #! (found,i_implib) = starts ".implib \"" line; | found #! lib = line % (i_implib,size line - 3); = collect_abc_info abc_file version objs [/*path_prefix +++ toString path_separator +++*/ lib:libs] state files; = collect_abc_info abc_file version objs libs state files; } // read_abc_info } //from Directory import ::Data`; // macOS //import CallCg; class older_than_or_equal a :: !a !a -> (!Bool,!Bool); //1.3 instance older_than_or_equal Date` where { older_than_or_equal {year`=year1,month`=month1,day`=day1} {year`=year2,month`=month2,day`=day2} //3.1 /*2.0 instance older_than_or_equal Date where { older_than_or_equal {year=year1,month=month1,day=day1} {year=year2,month=month2,day=day2} 0.2*/ | year1 < year2 = (True,False); | year1 == year2 | month1 < month2 = (True,False); | month1 == month2 | day1 < day2 = (True,False); // data equal or bigger = (False, day1 == day2); // month1 > month2 = (False,False); // year1 > year2 = (False,False); }; //1.3 instance older_than_or_equal Time` where { older_than_or_equal {hours`=hours1,minutes`=minutes1,seconds`=seconds1} {hours`=hours2,minutes`=minutes2,seconds`=seconds2} //3.1 /*2.0 instance older_than_or_equal Time where { older_than_or_equal {hours=hours1,minutes=minutes1,seconds=seconds1} {hours=hours2,minutes=minutes2,seconds=seconds2} 0.2*/ | hours1 < hours2 = (True,False); | hours1 == hours2 | minutes1 < minutes2 = (True,False); | minutes1 == minutes2 | seconds1 < seconds2 = (True,False); // time equal or bigger = (False, seconds1 == seconds2); // minutes1 > minutes2 = (False,False); // hours1 > hours2 = (False,False); }; //1.3 instance older_than_or_equal (!Date`, !Time`) // DateTime //3.1 /*2.0 instance older_than_or_equal (!Date, !Time) // DateTime 0.2*/ where { older_than_or_equal (date1,time1) (date2,time2) # (older,equal) = older_than_or_equal date1 date2 | older = (True,False); | equal # (older,equal) = older_than_or_equal time1 time2; | older = (True,False); = (False,equal); = (False,False); }; instance toString DirError where { toString NoDirError = "NoDirError"; toString DoesntExist = "DoesntExist"; toString BadName = "BadName"; toString NotEnoughSpace = "NotEnoughSpace"; toString AlreadyExists = "AlreadyExists"; toString NoPermission = "NoPermission"; toString MoveIntoOffspring = "MoveIntoOffspring"; toString MoveAcrossDisks = "MoveAcrossDisks"; toString NotYetRemovable = "NotYetRemovable"; toString OtherDirError = "OtherDirError"; }; /* GenObj :: !String !String !*Files -> (!Bool,!Bool,!String,!String,!*Files); GenObj cgpath path_and_file files = GenObj2 cgpath path_and_file files; /* GenObj2 Improvements: - if code generator changes path, then it can not be found (no dialogue pops up; cancel unimplemented) - version of code generator doesn't yet matter */ GenObj2 :: !String !String !*Files -> (!Bool,!Bool,!String,!String,!*Files); GenObj2 cgpath path_and_file files | not (ends path_and_file ".o" || ends path_and_file ".obj" || ends path_and_file ".abc") = abort ("DynamicLink (GenObj): file " +++ path_and_file +++ " doesn't end with {abc,o,obj}-extension"); #! (path_file,extension) = ExtractPathFileAndExtension path_and_file; | extension == "obj" = abort ("DynamicLink (GenObj): object not generated by cg " +++ path_and_file); // (re)create the file_name with the {.abc,.o}-extensions // collect .abc info #! abc_path_file = path_file +++ ".abc"; #! ((ok,abc_file),files) = pd_StringToPath abc_path_file files; | not ok = abort ("DynamicLink (GenObj): something went wrong during path conversion 1"); // collect .o info #! o_path_file = path_file +++ ".o"; #! ((ok,o_file),files) = pd_StringToPath o_path_file files; | not ok = abort ("DynamicLink (GenObj): something went wrong during path conversion 2"); // get the file info # ((abc_dir_error,abc_file_info),files) = getFileInfo abc_file files; # ((o_dir_error,o_file_info),files) = getFileInfo o_file files; | (abc_dir_error == DoesntExist) && (o_dir_error == DoesntExist) // given path was invalid; pop up a dialogue = abort ("nothing exists" ); | (abc_dir_error == DoesntExist) && (o_dir_error <> DoesntExist) // only .o exists; assume it to be up-to-date = (True,False,o_path_file,"",files); | (abc_dir_error <> DoesntExist) && (o_dir_error == DoesntExist) // only .abc exists; then generate corresponding .o #! (s,ok) = CodeGen path_file; | ok = (True,False,s,"",files); = abort "problems during .o generation"; // both extensions of the file exist. is .o out of date? #! abc_datetime = abc_file_info.pi_fileInfo.lastModified; #! o_datatime = o_file_info.pi_fileInfo.lastModified; #! (older,equal) = older_than_or_equal abc_datetime o_datatime; | not older && not equal // .abc is newer as its corresponding .o; generate a new .o # (s,ok) = CodeGen path_file; | ok = (True,False,s,"",files); = abort ("not ok" +++ s); // .o is up-to-date = (True,False,o_path_file,"",files); */