Task 007: .4TH File Format

Task 007: .4TH File Format

File Format Specifications for the .4TH File Format

The .4TH file format is a text-based format utilized for source code in the Forth programming language. It consists of plain ASCII or UTF-8 text containing Forth words, definitions, and expressions, without a predefined binary structure or header. The format adheres to the syntax rules of the Forth standard (e.g., ANS Forth or Forth-2012), where code is interpreted as a sequence of space-delimited tokens processed by a stack-based virtual machine. There is no magic number, fixed fields, or encoded metadata specific to the format itself; it is essentially a script file similar to other text-based source code formats like .c or .py. As such, the internal content is human-readable and editable with any text editor.

  1. List of All Properties of This File Format Intrinsic to Its File System

Given that the .4TH format lacks inherent binary properties, the properties "intrinsic to its file system" are interpreted as standard file system metadata attributes associated with any file, including those with the .4TH extension. These are retrieved via operating system APIs and include:

  • File name
  • File size (in bytes)
  • Creation time (birth time, if available; otherwise, change time)
  • Last modification time
  • Last access time
  • Permissions (mode, e.g., octal representation such as 0644)
  • Owner user ID (UID)
  • Group ID (GID)
  • Inode number
  • Number of hard links
  • Device ID

These properties are not unique to the .4TH format but are standard across file systems like ext4 on Linux or NTFS on Windows.

  1. Two Direct Download Links for Files of Format .4TH
  1. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .4TH File Property Dump

The following is a self-contained HTML snippet with embedded JavaScript that can be embedded in a Ghost blog post (or any HTML page). It creates a drop zone where a user can drag and drop a .4TH file. Upon dropping, it displays the available file system properties accessible in a browser context (note: browser APIs limit access to full metadata; properties like permissions, UID, GID, inode, links, and device ID are not available without server-side processing). The code validates the file extension and dumps the properties to the screen.

Drag and drop a .4TH file here
  1. Python Class for Handling .4TH Files

The following Python class uses the os and stat modules to open a .4TH file, read its file system metadata (decode is not required as there is no binary encoding), print the properties to the console, and includes a method to write a new .4TH file with example Forth content while setting basic permissions if needed.

import os
import stat
import time

class FourthFileHandler:
    def __init__(self, filename):
        if not filename.lower().endswith('.4th'):
            raise ValueError("File must have .4th extension")
        self.filename = filename
        self.properties = {}

    def read_properties(self):
        st = os.stat(self.filename)
        self.properties = {
            'File name': self.filename,
            'File size (in bytes)': st.st_size,
            'Creation time': time.ctime(st.st_birthtime) if hasattr(st, 'st_birthtime') else time.ctime(st.st_ctime),
            'Last modification time': time.ctime(st.st_mtime),
            'Last access time': time.ctime(st.st_atime),
            'Permissions (mode)': oct(st.st_mode & 0o777),
            'Owner user ID (UID)': st.st_uid,
            'Group ID (GID)': st.st_gid,
            'Inode number': st.st_ino,
            'Number of hard links': st.st_nlink,
            'Device ID': st.st_dev
        }

    def print_properties(self):
        if not self.properties:
            self.read_properties()
        print("File Properties:")
        for key, value in self.properties.items():
            print(f"{key}: {value}")

    def write_example_file(self, new_filename):
        if not new_filename.lower().endswith('.4th'):
            raise ValueError("New file must have .4th extension")
        with open(new_filename, 'w') as f:
            f.write(": HELLO CR ." Hello, Forth! " CR ;\nHELLO\n")
        os.chmod(new_filename, 0o644)  # Set read/write for owner, read for others

# Example usage:
# handler = FourthFileHandler('example.4th')
# handler.print_properties()
# handler.write_example_file('new_example.4th')
  1. Java Class for Handling .4TH Files

The following Java class uses java.nio.file to open a .4TH file, read its file system metadata, print the properties to the console, and includes a method to write a new .4TH file with example Forth content while setting basic permissions.

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermissions;
import java.time.Instant;

public class FourthFileHandler {
    private String filename;
    private Path path;

    public FourthFileHandler(String filename) throws IOException {
        if (!filename.toLowerCase().endsWith(".4th")) {
            throw new IllegalArgumentException("File must have .4th extension");
        }
        this.filename = filename;
        this.path = Paths.get(filename);
    }

    public void readAndPrintProperties() throws IOException {
        BasicFileAttributes basicAttrs = Files.readAttributes(path, BasicFileAttributes.class);
        PosixFileAttributes posixAttrs = Files.readAttributes(path, PosixFileAttributes.class);

        System.out.println("File Properties:");
        System.out.println("File name: " + filename);
        System.out.println("File size (in bytes): " + basicAttrs.size());
        System.out.println("Creation time: " + Instant.ofEpochMilli(basicAttrs.creationTime().toMillis()));
        System.out.println("Last modification time: " + Instant.ofEpochMilli(basicAttrs.lastModifiedTime().toMillis()));
        System.out.println("Last access time: " + Instant.ofEpochMilli(basicAttrs.lastAccessTime().toMillis()));
        System.out.println("Permissions (mode): " + PosixFilePermissions.toString(posixAttrs.permissions()));
        System.out.println("Owner: " + posixAttrs.owner().getName());
        System.out.println("Group: " + posixAttrs.group().getName());
        System.out.println("Inode number: " + basicAttrs.fileKey());  // Approximation, as inode not directly exposed
        // Number of hard links and device ID not directly available in standard attributes
    }

    public void writeExampleFile(String newFilename) throws IOException {
        if (!newFilename.toLowerCase().endsWith(".4th")) {
            throw new IllegalArgumentException("New file must have .4th extension");
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(newFilename))) {
            writer.write(": HELLO CR ." Hello, Forth! " CR ;\nHELLO\n");
        }
        Files.setPosixFilePermissions(Paths.get(newFilename), PosixFilePermissions.fromString("rw-r--r--"));
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     FourthFileHandler handler = new FourthFileHandler("example.4th");
    //     handler.readAndPrintProperties();
    //     handler.writeExampleFile("new_example.4th");
    // }
}
  1. JavaScript Class for Handling .4TH Files (Node.js)

The following JavaScript class (for Node.js environment) uses the fs module to open a .4TH file, read its file system metadata, print the properties to the console, and includes a method to write a new .4TH file with example Forth content while setting permissions.

const fs = require('fs');
const path = require('path');

class FourthFileHandler {
    constructor(filename) {
        if (!filename.toLowerCase().endsWith('.4th')) {
            throw new Error('File must have .4th extension');
        }
        this.filename = filename;
    }

    readProperties() {
        const stats = fs.statSync(this.filename);
        return {
            'File name': this.filename,
            'File size (in bytes)': stats.size,
            'Creation time': stats.birthtime.toString(),
            'Last modification time': stats.mtime.toString(),
            'Last access time': stats.atime.toString(),
            'Permissions (mode)': (stats.mode & 0o777).toString(8),
            'Owner user ID (UID)': stats.uid,
            'Group ID (GID)': stats.gid,
            'Inode number': stats.ino,
            'Number of hard links': stats.nlink,
            'Device ID': stats.dev
        };
    }

    printProperties() {
        const properties = this.readProperties();
        console.log('File Properties:');
        for (const [key, value] of Object.entries(properties)) {
            console.log(`${key}: ${value}`);
        }
    }

    writeExampleFile(newFilename) {
        if (!newFilename.toLowerCase().endsWith('.4th')) {
            throw new Error('New file must have .4th extension');
        }
        fs.writeFileSync(newFilename, ': HELLO CR ." Hello, Forth! " CR ;\nHELLO\n');
        fs.chmodSync(newFilename, 0o644);
    }
}

// Example usage:
// const handler = new FourthFileHandler('example.4th');
// handler.printProperties();
// handler.writeExampleFile('new_example.4th');
  1. C "Class" for Handling .4TH Files

C does not have native classes, so the following implements a struct with associated functions to mimic class behavior. It uses <sys/stat.h> to open a .4TH file, read its file system metadata, print the properties to the console, and includes a function to write a new .4TH file with example Forth content while setting permissions.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>

struct FourthFileHandler {
    char *filename;
};

struct FourthFileHandler* createFourthFileHandler(const char *filename) {
    if (strstr(filename, ".4th") == NULL && strstr(filename, ".4TH") == NULL) {
        fprintf(stderr, "File must have .4th extension\n");
        exit(1);
    }
    struct FourthFileHandler *handler = malloc(sizeof(struct FourthFileHandler));
    handler->filename = strdup(filename);
    return handler;
}

void destroyFourthFileHandler(struct FourthFileHandler *handler) {
    free(handler->filename);
    free(handler);
}

void printProperties(struct FourthFileHandler *handler) {
    struct stat st;
    if (stat(handler->filename, &st) != 0) {
        perror("stat");
        return;
    }
    printf("File Properties:\n");
    printf("File name: %s\n", handler->filename);
    printf("File size (in bytes): %ld\n", (long)st.st_size);
    printf("Creation time: %s", ctime(&st.st_ctime));  // ctime as proxy for creation
    printf("Last modification time: %s", ctime(&st.st_mtime));
    printf("Last access time: %s", ctime(&st.st_atime));
    printf("Permissions (mode): %o\n", st.st_mode & 0777);
    printf("Owner user ID (UID): %d\n", st.st_uid);
    printf("Group ID (GID): %d\n", st.st_gid);
    printf("Inode number: %ld\n", (long)st.st_ino);
    printf("Number of hard links: %ld\n", (long)st.st_nlink);
    printf("Device ID: %ld\n", (long)st.st_dev);
}

void writeExampleFile(const char *newFilename) {
    if (strstr(newFilename, ".4th") == NULL && strstr(newFilename, ".4TH") == NULL) {
        fprintf(stderr, "New file must have .4th extension\n");
        return;
    }
    FILE *f = fopen(newFilename, "w");
    if (f == NULL) {
        perror("fopen");
        return;
    }
    fprintf(f, ": HELLO CR .\" Hello, Forth! \" CR ;\nHELLO\n");
    fclose(f);
    chmod(newFilename, 0644);
}

// Example usage:
// int main() {
//     struct FourthFileHandler *handler = createFourthFileHandler("example.4th");
//     printProperties(handler);
//     writeExampleFile("new_example.4th");
//     destroyFourthFileHandler(handler);
//     return 0;
// }