Task 201: .F File Format

Task 201: .F File Format

File Format Specifications for the .F File Format

The .F file format is utilized for Fortran source code files that incorporate preprocessor directives. It adheres to the fixed-form layout defined in the Fortran 77 standard, with the capital .F extension indicating the need for preprocessing (e.g., for macros or includes) before compilation. The file is structured as plain text in ASCII encoding, with specific column-based rules for code layout. Preprocessor directives, if present, are typically C-style (starting with #) and processed by tools like cpp. The format does not include a binary header or magic number; identification relies on content parsing and the extension.

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

  • File extension: .F (case-sensitive in some systems, but often treated as equivalent to .f)
  • MIME type: text/x-fortran
  • Encoding: ASCII (7-bit)
  • Line termination: Platform-dependent (CR, LF, or CRLF)
  • Line length: Fixed at 72 characters for code statements; lines may extend to 132 characters in some extensions, but standard is 72
  • Comment indicator: 'C', '*', or '!' in column 1 for comment lines
  • Statement label: Columns 1-5, optional numeric label (0-99999, leading spaces allowed)
  • Continuation indicator: Column 6, non-blank and non-zero character (e.g., '&' or '1') for continuation lines; blank for initial lines
  • Statement body: Columns 7-72, containing the Fortran statement or code
  • Preprocessor directives: Lines starting with '#' (e.g., #define, #include), processed before compilation
  • File system attributes: Regular text file; no special magic bytes; readable as plain text; permissions and metadata (size, timestamps) managed by the operating system

3. Ghost Blog Embedded HTML JavaScript for Drag and Drop .F File Dump

.F File Properties Dumper
Drag and drop a .F file here

4. Python Class for .F File Handling

import os
import stat
import time

class FFileHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.content = None
        self.properties = []

    def read_and_decode(self):
        with open(self.filepath, 'r') as f:
            self.content = f.readlines()
        st = os.stat(self.filepath)
        self.properties = [
            f"File name: {os.path.basename(self.filepath)}",
            f"File size: {st.st_size} bytes",
            f"Last modified: {time.ctime(st.st_mtime)}",
            f"Permissions: {stat.filemode(st.st_mode)}",
            f"Owner UID: {st.st_uid}",
            f"Group GID: {st.st_gid}"
        ]
        for idx, line in enumerate(self.content):
            trimmed = line.rstrip('\n').ljust(72)[:72]
            col1 = trimmed[0] if len(trimmed) > 0 else ' '
            label = trimmed[:5].strip() or 'none'
            continuation = trimmed[5] if len(trimmed) > 5 else ' '
            statement = trimmed[6:].strip() or ''
            is_comment = col1.upper() in ['C', '*', '!']
            self.properties.append(f"Line {idx+1}:")
            self.properties.append(f"  Is comment: {is_comment}")
            self.properties.append(f"  Label: {label}")
            self.properties.append(f"  Continuation: {continuation if continuation != ' ' else 'none'}")
            self.properties.append(f"  Statement: {statement}")

    def print_properties(self):
        for prop in self.properties:
            print(prop)

    def write(self, new_filepath):
        with open(new_filepath, 'w') as f:
            f.writelines(self.content)

# Example usage:
# handler = FFileHandler('example.F')
# handler.read_and_decode()
# handler.print_properties()
# handler.write('new_example.F')

5. Java Class for .F File Handling

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.time.Instant;

public class FFileHandler {
    private String filepath;
    private String[] content;
    private String[] properties;

    public FFileHandler(String filepath) {
        this.filepath = filepath;
    }

    public void readAndDecode() throws IOException {
        content = Files.readAllLines(Paths.get(filepath)).toArray(new String[0]);
        BasicFileAttributes attrs = Files.readAttributes(Paths.get(filepath), BasicFileAttributes.class);
        PosixFileAttributes posixAttrs = null;
        try {
            posixAttrs = Files.readAttributes(Paths.get(filepath), PosixFileAttributes.class);
        } catch (UnsupportedOperationException e) {
            // Posix not supported
        }
        properties = new String[content.length * 5 + 6];
        int idx = 0;
        properties[idx++] = "File name: " + Paths.get(filepath).getFileName();
        properties[idx++] = "File size: " + attrs.size() + " bytes";
        properties[idx++] = "Last modified: " + Instant.ofEpochMilli(attrs.lastModifiedTime().toMillis());
        if (posixAttrs != null) {
            properties[idx++] = "Permissions: " + PosixFilePermissions.toString(posixAttrs.permissions());
            properties[idx++] = "Owner: " + posixAttrs.owner().getName();
            properties[idx++] = "Group: " + posixAttrs.group().getName();
        } else {
            properties[idx++] = "Permissions: Not available (non-POSIX)";
            properties[idx++] = "Owner: Not available";
            properties[idx++] = "Group: Not available";
        }
        for (int lineNum = 0; lineNum < content.length; lineNum++) {
            String line = content[lineNum];
            String trimmed = String.format("%-72s", line.replaceAll("\n", "")).substring(0, 72);
            char col1 = trimmed.length() > 0 ? trimmed.charAt(0) : ' ';
            String label = trimmed.substring(0, Math.min(5, trimmed.length())).trim();
            if (label.isEmpty()) label = "none";
            char continuation = trimmed.length() > 5 ? trimmed.charAt(5) : ' ';
            String statement = trimmed.substring(Math.min(6, trimmed.length())).trim();
            boolean isComment = "C*!".indexOf(Character.toUpperCase(col1)) >= 0;
            properties[idx++] = "Line " + (lineNum + 1) + ":";
            properties[idx++] = "  Is comment: " + isComment;
            properties[idx++] = "  Label: " + label;
            properties[idx++] = "  Continuation: " + (continuation != ' ' ? String.valueOf(continuation) : "none");
            properties[idx++] = "  Statement: " + (statement.isEmpty() ? "" : statement);
        }
        this.properties = java.util.Arrays.copyOf(properties, idx);
    }

    public void printProperties() {
        for (String prop : properties) {
            System.out.println(prop);
        }
    }

    public void write(String newFilepath) throws IOException {
        Files.write(Paths.get(newFilepath), String.join("\n", content).getBytes());
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     FFileHandler handler = new FFileHandler("example.F");
    //     handler.readAndDecode();
    //     handler.printProperties();
    //     handler.write("new_example.F");
    // }
}

6. JavaScript Class for .F File Handling

class FFileHandler {
    constructor(file) {
        this.file = file;
        this.content = null;
        this.properties = [];
    }

    async readAndDecode() {
        this.content = await new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => resolve(e.target.result.split(/\r?\n/));
            reader.onerror = reject;
            reader.readAsText(this.file);
        });
        this.properties.push(`File name: ${this.file.name}`);
        this.properties.push(`File size: ${this.file.size} bytes`);
        this.properties.push(`MIME type: ${this.file.type || 'text/x-fortran'}`);
        this.properties.push(`Last modified: ${new Date(this.file.lastModified).toISOString()}`);
        this.content.forEach((line, index) => {
            const trimmed = line.padEnd(72).slice(0, 72);
            const col1 = trimmed[0] || ' ';
            let label = trimmed.slice(0, 5).trim() || 'none';
            const continuation = trimmed[5] || ' ';
            const statement = trimmed.slice(6).trim() || '';
            const isComment = 'C*!'.includes(col1.toUpperCase());
            this.properties.push(`Line ${index + 1}:`);
            this.properties.push(`  Is comment: ${isComment}`);
            this.properties.push(`  Label: ${label}`);
            this.properties.push(`  Continuation: ${continuation !== ' ' ? continuation : 'none'}`);
            this.properties.push(`  Statement: ${statement}`);
        });
    }

    printProperties() {
        console.log(this.properties.join('\n'));
    }

    write(newFilename) {
        const blob = new Blob([this.content.join('\n')], { type: 'text/plain' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = newFilename;
        a.click();
        URL.revokeObjectURL(url);
    }
}

// Example usage:
// const input = document.createElement('input');
// input.type = 'file';
// input.onchange = async () => {
//     const handler = new FFileHandler(input.files[0]);
//     await handler.readAndDecode();
//     handler.printProperties();
//     handler.write('new_example.F');
// };
// input.click();

7. C Class for .F File Handling

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>

#define MAX_LINES 10000
#define LINE_LENGTH 73  // 72 + null terminator

struct FFileHandler {
    char* filepath;
    char** content;
    int line_count;
};

struct FFileHandler* createFFileHandler(const char* filepath) {
    struct FFileHandler* handler = malloc(sizeof(struct FFileHandler));
    handler->filepath = strdup(filepath);
    handler->content = NULL;
    handler->line_count = 0;
    return handler;
}

void readAndDecode(struct FFileHandler* handler) {
    FILE* f = fopen(handler->filepath, "r");
    if (!f) {
        perror("Error opening file");
        return;
    }
    handler->content = malloc(MAX_LINES * sizeof(char*));
    char line[LINE_LENGTH];
    while (fgets(line, LINE_LENGTH, f) && handler->line_count < MAX_LINES) {
        handler->content[handler->line_count] = strdup(line);
        handler->line_count++;
    }
    fclose(f);
}

void printProperties(const struct FFileHandler* handler) {
    struct stat st;
    if (stat(handler->filepath, &st) != 0) {
        perror("stat failed");
        return;
    }
    struct passwd* pw = getpwuid(st.st_uid);
    struct group* gr = getgrgid(st.st_gid);
    printf("File name: %s\n", handler->filepath);
    printf("File size: %ld bytes\n", (long)st.st_size);
    printf("Last modified: %s", ctime(&st.st_mtime));
    printf("Permissions: %o\n", st.st_mode & 0777);
    printf("Owner: %s\n", pw ? pw->pw_name : "unknown");
    printf("Group: %s\n", gr ? gr->gr_name : "unknown");
    for (int i = 0; i < handler->line_count; i++) {
        char trimmed[73];
        strncpy(trimmed, handler->content[i], 72);
        trimmed[72] = '\0';
        char col1 = trimmed[0];
        char label_str[6];
        strncpy(label_str, trimmed, 5);
        label_str[5] = '\0';
        char* label = strtrim(label_str);  // Assume strtrim function to trim spaces
        if (strlen(label) == 0) label = "none";
        char continuation = trimmed[5];
        char* statement = strtrim(trimmed + 6);
        int is_comment = (toupper(col1) == 'C' || col1 == '*' || col1 == '!');
        printf("Line %d:\n", i + 1);
        printf("  Is comment: %d\n", is_comment);
        printf("  Label: %s\n", label);
        printf("  Continuation: %c\n", continuation != ' ' ? continuation : "none");
        printf("  Statement: %s\n", statement ? statement : "");
    }
}

void write(const struct FFileHandler* handler, const char* new_filepath) {
    FILE* f = fopen(new_filepath, "w");
    if (!f) {
        perror("Error opening file for write");
        return;
    }
    for (int i = 0; i < handler->line_count; i++) {
        fputs(handler->content[i], f);
    }
    fclose(f);
}

void destroyFFileHandler(struct FFileHandler* handler) {
    for (int i = 0; i < handler->line_count; i++) {
        free(handler->content[i]);
    }
    free(handler->content);
    free(handler->filepath);
    free(handler);
}

// Note: Implement strtrim or use string library for trimming.
// Example usage:
// int main() {
//     struct FFileHandler* handler = createFFileHandler("example.F");
//     readAndDecode(handler);
//     printProperties(handler);
//     write(handler, "new_example.F");
//     destroyFFileHandler(handler);
//     return 0;
// }