Task 208: .F77 File Format
Task 208: .F77 File Format
1. List of all the properties of the .F77 file format intrinsic to its file system
The .F77 file format is used for Fortran 77 source code files. It is a plain text format following the fixed-form source layout defined in the ANSI Fortran 77 standard. The properties are as follows:
- Plain text file, typically ASCII-encoded.
- Fixed-form structure with specific column-based layout for each line.
- Standard line length: Up to 72 columns for meaningful content; lines are typically 80 characters total.
- Column 1: 'C' or '*' indicates a comment line; otherwise, the line is executable or blank.
- Columns 1-5: Statement label (optional numeric value from 1 to 99999, digits only, leading blanks allowed; right-justified if present).
- Column 6: Continuation indicator (blank or '0' for initial statement lines; any non-blank, non-zero character for continuation of previous statement).
- Columns 7-72: The actual Fortran statement or code body.
- Columns 73-80: Ignored by the compiler (often used for sequence numbers or identification; not part of the code).
- Case-insensitive, but traditionally written in uppercase.
- No free-form support; all code must adhere to the column rules.
- Blank lines are allowed and treated as comments.
- No binary header or footer; purely text-based.
2. Two direct download links for files of format .F77
- https://people.sc.fsu.edu/~jburkardt/f77_src/analemma/analemma.f77
- https://people.sc.fsu.edu/~jburkardt/f77_src/args/args.f77
3. Ghost blog embedded HTML JavaScript for drag and drop .F77 file to dump properties
Here's an embeddable HTML snippet with JavaScript that can be used in a Ghost blog post (or any HTML-enabled blog). It creates a drop zone where users can drag and drop a .F77 file. Upon dropping, it reads the file as text, parses each line according to the .F77 fixed-form properties, and dumps the extracted properties (comment status, label, continuation status, statement, and identification) to the screen in a readable format.
4. Python class for .F77 files
Here's a Python class that can open, read, decode (parse), print the properties to console, and write a new .F77 file (e.g., reconstructing from parsed data).
class F77FileHandler:
def __init__(self, filepath):
self.filepath = filepath
self.lines = []
self.parsed_lines = []
def read_and_decode(self):
with open(self.filepath, 'r') as f:
self.lines = f.readlines()
for line in self.lines:
padded_line = line.rstrip('\n').ljust(80) # Pad to 80 chars
col1 = padded_line[0] if len(padded_line) > 0 else ' '
cols1_5 = padded_line[0:5].strip()
col6 = padded_line[5] if len(padded_line) > 5 else ' '
cols7_72 = padded_line[6:72].strip()
cols73_80 = padded_line[72:80].strip()
is_comment = (col1 in ['C', '*']) or not padded_line.strip()
label = cols1_5 if cols1_5.isdigit() else 'none'
is_continuation = col6 not in [' ', '0'] and not is_comment
statement = cols7_72 if cols7_72 else 'none'
identification = cols73_80 if cols73_80 else 'none'
self.parsed_lines.append({
'is_comment': is_comment,
'label': label,
'is_continuation': is_continuation,
'statement': statement,
'identification': identification
})
def print_properties(self):
if not self.parsed_lines:
self.read_and_decode()
for idx, props in enumerate(self.parsed_lines):
print(f"Line {idx + 1}:")
print(f"- Is Comment: {'yes' if props['is_comment'] else 'no'}")
print(f"- Label: {props['label']}")
print(f"- Is Continuation: {'yes' if props['is_continuation'] else 'no'}")
print(f"- Statement: {props['statement']}")
print(f"- Identification (cols 73-80): {props['identification']}")
print()
def write(self, new_filepath):
if not self.lines:
raise ValueError("No data to write. Read a file first.")
with open(new_filepath, 'w') as f:
for line in self.lines:
f.write(line)
# Example usage:
# handler = F77FileHandler('example.F77')
# handler.read_and_decode()
# handler.print_properties()
# handler.write('output.F77')
5. Java class for .F77 files
Here's a Java class that can open, read, decode (parse), print the properties to console, and write a new .F77 file.
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class F77FileHandler {
private String filepath;
private List<String> lines = new ArrayList<>();
private List<F77LineProperties> parsedLines = new ArrayList<>();
public F77FileHandler(String filepath) {
this.filepath = filepath;
}
public void readAndDecode() throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filepath))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
}
for (String line : lines) {
String paddedLine = String.format("%-80s", line);
char col1 = paddedLine.length() > 0 ? paddedLine.charAt(0) : ' ';
String cols1_5 = paddedLine.substring(0, Math.min(5, paddedLine.length())).trim();
char col6 = paddedLine.length() > 5 ? paddedLine.charAt(5) : ' ';
String cols7_72 = paddedLine.substring(6, Math.min(72, paddedLine.length())).trim();
String cols73_80 = paddedLine.length() > 72 ? paddedLine.substring(72, Math.min(80, paddedLine.length())).trim() : "";
boolean isComment = (col1 == 'C' || col1 == '*') || paddedLine.trim().isEmpty();
String label = cols1_5.matches("\\d+") ? cols1_5 : "none";
boolean isContinuation = (col6 != ' ' && col6 != '0') && !isComment;
String statement = cols7_72.isEmpty() ? "none" : cols7_72;
String identification = cols73_80.isEmpty() ? "none" : cols73_80;
parsedLines.add(new F77LineProperties(isComment, label, isContinuation, statement, identification));
}
}
public void printProperties() {
if (parsedLines.isEmpty()) {
try {
readAndDecode();
} catch (IOException e) {
e.printStackTrace();
return;
}
}
for (int i = 0; i < parsedLines.size(); i++) {
F77LineProperties props = parsedLines.get(i);
System.out.println("Line " + (i + 1) + ":");
System.out.println("- Is Comment: " + (props.isComment ? "yes" : "no"));
System.out.println("- Label: " + props.label);
System.out.println("- Is Continuation: " + (props.isContinuation ? "yes" : "no"));
System.out.println("- Statement: " + props.statement);
System.out.println("- Identification (cols 73-80): " + props.identification);
System.out.println();
}
}
public void write(String newFilepath) throws IOException {
if (lines.isEmpty()) {
throw new IllegalStateException("No data to write. Read a file first.");
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(newFilepath))) {
for (String line : lines) {
writer.write(line);
writer.newLine();
}
}
}
private static class F77LineProperties {
boolean isComment;
String label;
boolean isContinuation;
String statement;
String identification;
F77LineProperties(boolean isComment, String label, boolean isContinuation, String statement, String identification) {
this.isComment = isComment;
this.label = label;
this.isContinuation = isContinuation;
this.statement = statement;
this.identification = identification;
}
}
// Example usage:
// public static void main(String[] args) throws IOException {
// F77FileHandler handler = new F77FileHandler("example.F77");
// handler.readAndDecode();
// handler.printProperties();
// handler.write("output.F77");
// }
}
6. JavaScript class for .F77 files
Here's a JavaScript class (for Node.js) that can open, read, decode (parse), print the properties to console, and write a new .F77 file. Requires Node.js fs module.
const fs = require('fs');
class F77FileHandler {
constructor(filepath) {
this.filepath = filepath;
this.lines = [];
this.parsedLines = [];
}
readAndDecode() {
this.lines = fs.readFileSync(this.filepath, 'utf8').split(/\r?\n/);
this.lines.forEach(line => {
const paddedLine = line.padEnd(80, ' ');
const col1 = paddedLine[0] || ' ';
const cols1_5 = paddedLine.slice(0, 5).trim();
const col6 = paddedLine[5] || ' ';
const cols7_72 = paddedLine.slice(6, 72).trim();
const cols73_80 = paddedLine.slice(72, 80).trim();
const isComment = (col1 === 'C' || col1 === '*') || !paddedLine.trim();
const label = /^\d+$/.test(cols1_5) ? cols1_5 : 'none';
const isContinuation = (col6 !== ' ' && col6 !== '0') && !isComment;
const statement = cols7_72 || 'none';
const identification = cols73_80 || 'none';
this.parsedLines.push({
isComment,
label,
isContinuation,
statement,
identification
});
});
}
printProperties() {
if (this.parsedLines.length === 0) {
this.readAndDecode();
}
this.parsedLines.forEach((props, index) => {
console.log(`Line ${index + 1}:`);
console.log(`- Is Comment: ${props.isComment ? 'yes' : 'no'}`);
console.log(`- Label: ${props.label}`);
console.log(`- Is Continuation: ${props.isContinuation ? 'yes' : 'no'}`);
console.log(`- Statement: ${props.statement}`);
console.log(`- Identification (cols 73-80): ${props.identification}`);
console.log();
});
}
write(newFilepath) {
if (this.lines.length === 0) {
throw new Error('No data to write. Read a file first.');
}
fs.writeFileSync(newFilepath, this.lines.join('\n'));
}
}
// Example usage:
// const handler = new F77FileHandler('example.F77');
// handler.readAndDecode();
// handler.printProperties();
// handler.write('output.F77');
7. C class for .F77 files
Since C does not have native classes, here's a C++ class (as "c class" likely implies C++) that can open, read, decode (parse), print the properties to console, and write a new .F77 file.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iomanip>
struct F77LineProperties {
bool isComment;
std::string label;
bool isContinuation;
std::string statement;
std::string identification;
};
class F77FileHandler {
private:
std::string filepath;
std::vector<std::string> lines;
std::vector<F77LineProperties> parsedLines;
public:
F77FileHandler(const std::string& filepath) : filepath(filepath) {}
void readAndDecode() {
std::ifstream file(filepath);
if (!file.is_open()) {
std::cerr << "Error opening file: " << filepath << std::endl;
return;
}
std::string line;
while (std::getline(file, line)) {
lines.push_back(line);
}
file.close();
for (const auto& line : lines) {
std::string paddedLine = line;
paddedLine.resize(80, ' ');
char col1 = paddedLine[0];
std::string cols1_5 = paddedLine.substr(0, 5);
cols1_5.erase(0, cols1_5.find_first_not_of(' '));
cols1_5.erase(cols1_5.find_last_not_of(' ') + 1);
char col6 = paddedLine[5];
std::string cols7_72 = paddedLine.substr(6, 66);
cols7_72.erase(0, cols7_72.find_first_not_of(' '));
cols7_72.erase(cols7_72.find_last_not_of(' ') + 1);
std::string cols73_80 = paddedLine.substr(72, 8);
cols73_80.erase(0, cols73_80.find_first_not_of(' '));
cols73_80.erase(cols73_80.find_last_not_of(' ') + 1);
bool isComment = (col1 == 'C' || col1 == '*') || paddedLine.find_first_not_of(' ') == std::string::npos;
std::string label = (cols1_5.find_first_not_of("0123456789") == std::string::npos && !cols1_5.empty()) ? cols1_5 : "none";
bool isContinuation = (col6 != ' ' && col6 != '0') && !isComment;
std::string statement = cols7_72.empty() ? "none" : cols7_72;
std::string identification = cols73_80.empty() ? "none" : cols73_80;
parsedLines.push_back({isComment, label, isContinuation, statement, identification});
}
}
void printProperties() {
if (parsedLines.empty()) {
readAndDecode();
}
for (size_t i = 0; i < parsedLines.size(); ++i) {
const auto& props = parsedLines[i];
std::cout << "Line " << (i + 1) << ":" << std::endl;
std::cout << "- Is Comment: " << (props.isComment ? "yes" : "no") << std::endl;
std::cout << "- Label: " << props.label << std::endl;
std::cout << "- Is Continuation: " << (props.isContinuation ? "yes" : "no") << std::endl;
std::cout << "- Statement: " << props.statement << std::endl;
std::cout << "- Identification (cols 73-80): " << props.identification << std::endl;
std::cout << std::endl;
}
}
void write(const std::string& newFilepath) {
if (lines.empty()) {
std::cerr << "No data to write. Read a file first." << std::endl;
return;
}
std::ofstream outFile(newFilepath);
if (!outFile.is_open()) {
std::cerr << "Error opening output file: " << newFilepath << std::endl;
return;
}
for (const auto& line : lines) {
outFile << line << std::endl;
}
outFile.close();
}
};
// Example usage:
// int main() {
// F77FileHandler handler("example.F77");
// handler.readAndDecode();
// handler.printProperties();
// handler.write("output.F77");
// return 0;
// }