const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; pub fn formatDosPath(allocator: Allocator, path: []const u8) ![]const u8 { var result = ArrayList(u8).init(allocator); defer result.deinit(); // Convert path to DOS format with uppercase drive letter and backslashes var converted_path = ArrayList(u8).init(allocator); defer converted_path.deinit(); for (path) |ch| { if (ch == '/') { try converted_path.append('\\'); } else { try converted_path.append(std.ascii.toUpper(ch)); } } // Split into components and convert each to 8.3 format var it = std.mem.splitScalar(u8, converted_path.items, '\\'); var first = true; while (it.next()) |component| { if (component.len == 0) continue; if (!first) { try result.append('\\'); } first = false; // Convert component to 8.3 format const short_name = try convertTo83(allocator, component); defer allocator.free(short_name); try result.appendSlice(short_name); } // Ensure it starts with a drive letter if it's an absolute path if (result.items.len == 0 or (result.items.len >= 1 and result.items[0] == '\\')) { var prefixed = ArrayList(u8).init(allocator); defer prefixed.deinit(); try prefixed.appendSlice("C:"); if (result.items.len > 0 and result.items[0] != '\\') { try prefixed.append('\\'); } try prefixed.appendSlice(result.items); return allocator.dupe(u8, prefixed.items); } return allocator.dupe(u8, result.items); } pub fn convertTo83(allocator: Allocator, filename: []const u8) ![]const u8 { // Handle special directories if (std.mem.eql(u8, filename, ".") or std.mem.eql(u8, filename, "..")) { return allocator.dupe(u8, filename); } // Handle drive letters (like C:) if (filename.len == 2 and filename[1] == ':') { return allocator.dupe(u8, filename); } // Split filename and extension var name_part: []const u8 = filename; var ext_part: []const u8 = ""; if (std.mem.lastIndexOf(u8, filename, ".")) |dot_pos| { if (dot_pos > 0) { // Don't treat leading dot as extension separator name_part = filename[0..dot_pos]; ext_part = filename[dot_pos + 1 ..]; } } // Clean name part (remove spaces and invalid chars, convert to uppercase) var clean_name = ArrayList(u8).init(allocator); defer clean_name.deinit(); for (name_part) |ch| { if (std.ascii.isAlphanumeric(ch)) { try clean_name.append(std.ascii.toUpper(ch)); } else if (ch == '-' or ch == '_') { try clean_name.append(ch); } // Skip spaces and other invalid characters } // Clean extension part (max 3 chars, uppercase) var clean_ext = ArrayList(u8).init(allocator); defer clean_ext.deinit(); for (ext_part) |ch| { if (clean_ext.items.len >= 3) break; if (std.ascii.isAlphanumeric(ch)) { try clean_ext.append(std.ascii.toUpper(ch)); } } // Build 8.3 filename var result = ArrayList(u8).init(allocator); defer result.deinit(); if (clean_name.items.len <= 8 and clean_ext.items.len <= 3) { // Name fits in 8.3, use as-is try result.appendSlice(clean_name.items); if (clean_ext.items.len > 0) { try result.append('.'); try result.appendSlice(clean_ext.items); } } else { // Need to abbreviate with ~1 const max_name_len = if (clean_name.items.len > 6) 6 else clean_name.items.len; try result.appendSlice(clean_name.items[0..max_name_len]); try result.appendSlice("~1"); if (clean_ext.items.len > 0) { try result.append('.'); const max_ext_len = if (clean_ext.items.len > 3) 3 else clean_ext.items.len; try result.appendSlice(clean_ext.items[0..max_ext_len]); } } return allocator.dupe(u8, result.items); }