//import win32 ( WIN32_FIND_DATAA, FindFirst ) import win32; import libc; import io.paths; private printWithSprintf(stream, formatString, value) { var buf = Array[CChar, 100](); libc.sprintf(&buf[0], cstring(formatString), value); var n = libc.strlen(&buf[0]); var ptr = Pointer[Byte](&buf[0]); write(stream, ptr, SizeT(n)); } private record FileDirectory[S] ( path : S, ); [T | String?(T)] direntSequence(x:T) = FileDirectory[T](x); [T | String?(T)] overload iterator(x:FileDirectory[T]) = FileIterator(x.path); private record FileIterator ( handle : win32.HANDLE, queued? : Bool, findData : win32.WIN32_FIND_DATAA, ); private record FileInfo ( name : String, system? : Bool, directory? : Bool, ); [T | String?(T)] overload FileIterator(path:T) self:FileIterator { self.handle = win32.FindFirstFileA(cstring(path), &self.findData); self.queued? = true; return self; } overload destroy(x:FileIterator) { win32.FindClose(x.handle); } overload hasNext?(x:FileIterator) { if (not x.queued?) { x.queued? = true; var returnCode = win32.FindNextFileA(x.handle, &x.findData); return (returnCode != 0); } else return true; } testFlag(flags, flag) = bitwiseAnd(flags, flag) == flag; overload next(x:FileIterator) { if (not x.queued?) hasNext?(x); x.queued? = false; return FileInfo( String(CStringRef(begin(x.findData.cFileName))), testFlag(x.findData.dwFileAttributes, win32.FILE_ATTRIBUTE_SYSTEM), testFlag(x.findData.dwFileAttributes, win32.FILE_ATTRIBUTE_DIRECTORY) ); } overload subtract(a:Char, b:Char) { return Int(a)-Int(b); } hexToInt(string) { var number = 0; for (char in string) { if (char >= '0' and char <= '9') number = number * 16 + (char - '0'); else if (char >= 'A' and char <= 'F') number = number * 16 + (char - 'A' + 10); else return (false, 0); } return (true, number); } errorMsg(msg) { println(msg); flush(stdin); var buff = Array[Byte,1](); read(stdin, begin(buff),1); } renameFile(a,b) { win32.MoveFileA(cstring(a), cstring(b)); } massren() { var files = Vector[String](); var dir = FileDirectory("*"); for (fi in dir) { if (not fi.system? and not fi.directory? and fi.name != "massren.exe" and fi.name != "massren.txt") push(files, fi.name); } sort(files); if (not io.paths.pathExists?("massren.txt")) { println("listing..."); var configFile = File("massren.txt", CREATE); printWithSprintf(configFile, "massren file -- directory hash: %8.0X\n", hash(files)); for (f in files) printlnTo(configFile, f); println("done !"); } else { var configFile = File("massren.txt", READ); var header = readLine(configFile); // print(header); var hashString = slicedFrom(trimmed(header), size("massren file -- directory hash: ")); var ok, hash = ...unpack(hexToInt(hashString)); if (ok and hash == prelude.hash(files)) { println("testing..."); var filesFrom = files; var filesTo = Vector[String](); for(nameFrom in files) { push(filesTo, trim(readLine(configFile))); } print(filesTo); println("renaming (1/2)..."); for(nameFrom, nameTo in zipped(filesFrom, filesTo)) { // println(nameFrom, " -> " ,"massren_temp_"+nameFrom); renameFile(nameFrom, "massren_temp_"+nameFrom); } println("renaming (2/2)..."); for(nameFrom, nameTo in zipped(filesFrom, filesTo)) { // println("massren_temp_"+nameFrom, " -> " ,nameTo); renameFile("massren_temp_"+nameFrom, nameTo); } println("done !"); } else { errorMsg("directory hash mismatch !"); } } } main() { //printWithSprintf(stdout, "massren file -- directory hash: %0.8X\n", 1); massren(); }