Task 278: .H File Format
Task 278: .H File Format
1. Properties of the .H File Format Intrinsic to Its Structure
The .H file format refers to C/C++ header files, which are plain-text ASCII files used to declare shared elements like functions, variables, types, and macros for inclusion in source code via the #include
directive. These files follow conventions defined by the C standard (e.g., ISO/IEC 9899) and C++ standard (e.g., ISO/IEC 14882), but lack a rigid binary structure—instead, they are line-oriented text files parsed by the C preprocessor. "Intrinsic properties" here refer to core structural elements that define their content and behavior within the C/C++ compilation ecosystem (not a separate file system, but the compilation model's dependency graph). Based on standard specifications, the key properties are:
- Text Encoding: ASCII or UTF-8 compatible, with lines terminated by LF (line feed, ASCII 10) or CRLF (carriage return + line feed, ASCII 13+10). No binary data; maximum line length is implementation-defined but typically 509 characters (C standard recommendation).
- Preprocessor Directives: Lines starting with
#
(after optional whitespace), including: #include <header>
or#include "header"
for including other files (system or user headers).#define
for macro definitions (e.g., constants, functions).#undef
for macro undefinition.- Conditional compilation (
#if
,#ifdef
,#ifndef
,#else
,#elif
,#endif
). #pragma
for compiler-specific directives (e.g.,#pragma once
for include guards).- Include Guards: Typically a triplet of
#ifndef GUARD_NAME
,#define GUARD_NAME
, and#endif
to prevent multiple inclusions. - Declarations:
- Function prototypes (e.g.,
int func(int param);
). - Extern variable declarations (e.g.,
extern int global_var;
). - Type definitions:
struct
,union
,enum
,typedef
. - Comments:
/* block */
or// line
(C++ only), ignored by preprocessor. - No Definitions: Headers should avoid executable code or full function bodies (except inline or templates in C++); violations lead to multiple definition errors.
- File Extension Convention: Always
.h
(lowercase recommended for portability). - Self-Containment: Must compile standalone (after includes) to ensure forward declarations work.
These properties ensure modularity in C/C++ projects, where headers form a directed acyclic graph of dependencies.
2. Two Direct Download Links for .H Files
- Sample 3: https://filesamples.com/samples/code/h/sample3.h
- Sample 2: https://filesamples.com/samples/code/h/sample2.h
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .H File Parsing
This is a self-contained HTML snippet with embedded JavaScript, suitable for embedding in a Ghost blog post (via the HTML card). It enables drag-and-drop of a .H file, reads it as text, parses key properties (includes, defines, function prototypes, guards), and dumps them to a <div>
on screen. Parsing uses simple regex for demonstration; handles basic cases but not nested conditionals or complex syntax.
4. Python Class for .H File Handling
This Python class reads a .H file, parses and prints the properties (same as above), and supports writing a new .H file from a dict of properties. Uses re
for parsing.
import re
import os
class HFileHandler:
def __init__(self, filepath):
self.filepath = filepath
self.content = None
self.properties = None
def read_and_decode(self):
if not os.path.exists(self.filepath) or not self.filepath.endswith('.h'):
raise ValueError("Invalid .H file")
with open(self.filepath, 'r') as f:
self.content = f.read()
self.properties = self._parse()
self._print_properties()
return self.properties
def _parse(self):
lines = self.content.split('\n')
includes = []
defines = []
prototypes = []
guards = {'has_guard': False, 'name': None}
in_guard = False
for idx, line in enumerate(lines):
trimmed = line.strip()
if trimmed.startswith('#include'):
includes.append({'line': idx + 1, 'directive': trimmed})
elif trimmed.startswith('#define'):
defines.append({'line': idx + 1, 'macro': trimmed})
elif trimmed.startswith('#ifndef') and not in_guard:
guards['has_guard'] = True
match = re.match(r'#ifndef\s+(\w+)', trimmed)
if match:
guards['name'] = match.group(1)
in_guard = True
elif trimmed.startswith('#endif') and in_guard:
in_guard = False
elif re.match(r'^\w+\s+\w+\s*\([^)]*\)\s*;', trimmed):
prototypes.append({'line': idx + 1, 'proto': trimmed})
return {
'includes': includes,
'defines': defines,
'prototypes': prototypes,
'guards': guards,
'total_lines': len(lines)
}
def _print_properties(self):
print("=== .H File Properties ===")
print(f"Total lines: {self.properties['total_lines']}")
print("\nIncludes:")
for inc in self.properties['includes']:
print(f" Line {inc['line']}: {inc['directive']}")
print("\nDefines:")
for defn in self.properties['defines']:
print(f" Line {defn['line']}: {defn['macro']}")
print("\nPrototypes:")
for proto in self.properties['prototypes']:
print(f" Line {proto['line']}: {proto['proto']}")
print(f"\nGuards: {'Yes' if self.properties['guards']['has_guard'] else 'No'} (Name: {self.properties['guards']['name']})")
def write(self, output_path, properties=None):
if properties is None:
properties = self.properties
content = self._build_content(properties)
with open(output_path, 'w') as f:
f.write(content)
print(f"Wrote .H file to {output_path}")
def _build_content(self, props):
content = []
if props['guards']['has_guard']:
content.append(f"#ifndef {props['guards']['name']}")
content.append(f"#define {props['guards']['name']}")
for inc in props['includes']:
content.append(inc['directive'])
for defn in props['defines']:
content.append(defn['macro'])
for proto in props['prototypes']:
content.append(proto['proto'])
if props['guards']['has_guard']:
content.append("#endif")
return '\n'.join(content) + '\n'
# Usage example:
# handler = HFileHandler('sample.h')
# handler.read_and_decode()
# handler.write('output.h')
5. Java Class for .H File Handling
This Java class reads a .H file, parses and prints properties, and writes a new one. Uses java.util.regex
and BufferedReader
.
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class HFileHandler {
private String filepath;
private String content;
private Map<String, Object> properties;
public HFileHandler(String filepath) {
this.filepath = filepath;
this.properties = new HashMap<>();
}
public Map<String, Object> readAndDecode() throws IOException {
if (!filepath.endsWith(".h") || !new File(filepath).exists()) {
throw new IllegalArgumentException("Invalid .H file");
}
try (BufferedReader br = new BufferedReader(new FileReader(filepath))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
content = sb.toString();
}
properties = parse();
printProperties();
return properties;
}
private Map<String, Object> parse() {
String[] lines = content.split("\n");
List<Map<String, Object>> includes = new ArrayList<>();
List<Map<String, Object>> defines = new ArrayList<>();
List<Map<String, Object>> prototypes = new ArrayList<>();
Map<String, Object> guards = new HashMap<>();
guards.put("hasGuard", false);
guards.put("name", null);
boolean inGuard = false;
Pattern protoPattern = Pattern.compile("^\\w+\\s+\\w+\\s*\\([^)]*\\)\\s*;");
for (int idx = 0; idx < lines.length; idx++) {
String trimmed = lines[idx].trim();
if (trimmed.startsWith("#include")) {
Map<String, Object> inc = new HashMap<>();
inc.put("line", idx + 1);
inc.put("directive", trimmed);
includes.add(inc);
} else if (trimmed.startsWith("#define")) {
Map<String, Object> def = new HashMap<>();
def.put("line", idx + 1);
def.put("macro", trimmed);
defines.add(def);
} else if (trimmed.startsWith("#ifndef") && !inGuard) {
guards.put("hasGuard", true);
Matcher m = Pattern.compile("#ifndef\\s+(\\w+)").matcher(trimmed);
if (m.find()) {
guards.put("name", m.group(1));
}
inGuard = true;
} else if (trimmed.startsWith("#endif") && inGuard) {
inGuard = false;
} else if (protoPattern.matcher(trimmed).matches()) {
Map<String, Object> proto = new HashMap<>();
proto.put("line", idx + 1);
proto.put("proto", trimmed);
prototypes.add(proto);
}
}
Map<String, Object> props = new HashMap<>();
props.put("includes", includes);
props.put("defines", defines);
props.put("prototypes", prototypes);
props.put("guards", guards);
props.put("totalLines", lines.length);
return props;
}
private void printProperties() {
System.out.println("=== .H File Properties ===");
System.out.println("Total lines: " + properties.get("totalLines"));
System.out.println("\nIncludes:");
for (Map<String, Object> inc : (List<Map<String, Object>>) properties.get("includes")) {
System.out.println(" Line " + inc.get("line") + ": " + inc.get("directive"));
}
System.out.println("\nDefines:");
for (Map<String, Object> def : (List<Map<String, Object>>) properties.get("defines")) {
System.out.println(" Line " + def.get("line") + ": " + def.get("macro"));
}
System.out.println("\nPrototypes:");
for (Map<String, Object> proto : (List<Map<String, Object>>) properties.get("prototypes")) {
System.out.println(" Line " + proto.get("line") + ": " + proto.get("proto"));
}
Map<String, Object> guards = (Map<String, Object>) properties.get("guards");
System.out.println("\nGuards: " + (guards.get("hasGuard") ? "Yes" : "No") + " (Name: " + guards.get("name") + ")");
}
public void write(String outputPath, Map<String, Object> customProps) throws IOException {
Map<String, Object> props = (customProps != null) ? customProps : properties;
StringBuilder sb = new StringBuilder();
Map<String, Object> guards = (Map<String, Object>) props.get("guards");
if (guards.get("hasGuard") == Boolean.TRUE) {
sb.append("#ifndef ").append(guards.get("name")).append("\n");
sb.append("#define ").append(guards.get("name")).append("\n");
}
for (Map<String, Object> inc : (List<Map<String, Object>>) props.get("includes")) {
sb.append(inc.get("directive")).append("\n");
}
for (Map<String, Object> def : (List<Map<String, Object>>) props.get("defines")) {
sb.append(def.get("macro")).append("\n");
}
for (Map<String, Object> proto : (List<Map<String, Object>>) props.get("prototypes")) {
sb.append(proto.get("proto")).append("\n");
}
if (guards.get("hasGuard") == Boolean.TRUE) {
sb.append("#endif\n");
}
try (PrintWriter pw = new PrintWriter(new FileWriter(outputPath))) {
pw.print(sb.toString());
}
System.out.println("Wrote .H file to " + outputPath);
}
// Usage: HFileHandler handler = new HFileHandler("sample.h"); handler.readAndDecode(); handler.write("output.h", null);
}
6. JavaScript Class for .H File Handling
This Node.js-compatible class reads a .H file (using fs
), parses properties, prints to console, and writes a new file. Uses regex for parsing.
const fs = require('fs');
class HFileHandler {
constructor(filepath) {
this.filepath = filepath;
this.content = null;
this.properties = null;
}
async readAndDecode() {
if (!this.filepath.endsWith('.h') || !fs.existsSync(this.filepath)) {
throw new Error('Invalid .H file');
}
this.content = fs.readFileSync(this.filepath, 'utf8');
this.properties = this.parse();
this.printProperties();
return this.properties;
}
parse() {
const lines = this.content.split('\n');
const includes = [];
const defines = [];
const prototypes = [];
const guards = { hasGuard: false, name: null };
let inGuard = false;
const protoRegex = /^\w+\s+\w+\s*\([^)]*\)\s*;/;
lines.forEach((line, idx) => {
const trimmed = line.trim();
if (trimmed.startsWith('#include')) {
includes.push({ line: idx + 1, directive: trimmed });
} else if (trimmed.startsWith('#define')) {
defines.push({ line: idx + 1, macro: trimmed });
} else if (trimmed.startsWith('#ifndef') && !inGuard) {
guards.hasGuard = true;
const match = trimmed.match(/#ifndef\s+(\w+)/);
if (match) guards.name = match[1];
inGuard = true;
} else if (trimmed.startsWith('#endif') && inGuard) {
inGuard = false;
} else if (protoRegex.test(trimmed)) {
prototypes.push({ line: idx + 1, proto: trimmed });
}
});
return {
includes,
defines,
prototypes,
guards,
totalLines: lines.length
};
}
printProperties() {
console.log('=== .H File Properties ===');
console.log(`Total lines: ${this.properties.totalLines}`);
console.log('\nIncludes:');
this.properties.includes.forEach(inc => console.log(` Line ${inc.line}: ${inc.directive}`));
console.log('\nDefines:');
this.properties.defines.forEach(def => console.log(` Line ${def.line}: ${def.macro}`));
console.log('\nPrototypes:');
this.properties.prototypes.forEach(proto => console.log(` Line ${proto.line}: ${proto.proto}`));
console.log(`\nGuards: ${this.properties.guards.hasGuard ? 'Yes' : 'No'} (Name: ${this.properties.guards.name})`);
}
write(outputPath, customProps = null) {
const props = customProps || this.properties;
let content = '';
if (props.guards.hasGuard) {
content += `#ifndef ${props.guards.name}\n#define ${props.guards.name}\n`;
}
props.includes.forEach(inc => content += `${inc.directive}\n`);
props.defines.forEach(def => content += `${def.macro}\n`);
props.prototypes.forEach(proto => content += `${proto.proto}\n`);
if (props.guards.hasGuard) {
content += '#endif\n';
}
fs.writeFileSync(outputPath, content);
console.log(`Wrote .H file to ${outputPath}`);
}
}
// Usage:
// const handler = new HFileHandler('sample.h');
// await handler.readAndDecode();
// handler.write('output.h');
7. C Struct/Class for .H File Handling
This C implementation uses a struct with functions to read, parse, print, and write .H files. Parsing is line-based with strstr
and simple checks (no full regex; uses sscanf
where possible). Compile with gcc -o handler handler.c
.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 512
#define MAX_PROPS 100
typedef struct {
int line;
char directive[256];
} Prop;
typedef struct {
Prop includes[MAX_PROPS];
int num_includes;
Prop defines[MAX_PROPS];
int num_defines;
Prop prototypes[MAX_PROPS];
int num_prototypes;
int has_guard;
char guard_name[256];
int total_lines;
} HProperties;
typedef struct {
char filepath[256];
char *content;
HProperties props;
} HFileHandler;
void init_handler(HFileHandler *handler, const char *filepath) {
strcpy(handler->filepath, filepath);
handler->content = NULL;
handler->props.num_includes = 0;
handler->props.num_defines = 0;
handler->props.num_prototypes = 0;
handler->props.has_guard = 0;
handler->props.total_lines = 0;
}
int read_and_decode(HFileHandler *handler) {
FILE *fp = fopen(handler->filepath, "r");
if (!fp || !strstr(handler->filepath, ".h")) {
printf("Invalid .H file\n");
return 0;
}
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
handler->content = malloc(size + 1);
fread(handler->content, 1, size, fp);
handler->content[size] = '\0';
fclose(fp);
parse_content(handler);
print_properties(&handler->props);
return 1;
}
void parse_content(HFileHandler *handler) {
char *line = strtok(handler->content, "\n");
int idx = 0;
int in_guard = 0;
while (line != NULL) {
char trimmed[512];
sscanf(line, "%511[^\n]", trimmed);
char *p = trimmed;
while (*p == ' ' || *p == '\t') p++; // Trim left
char *end = p + strlen(p) - 1;
while (end > p && (*end == ' ' || *end == '\t' || *end == '\r')) *end-- = '\0';
if (strncmp(p, "#include", 8) == 0) {
if (handler->props.num_includes < MAX_PROPS) {
handler->props.includes[handler->props.num_includes].line = idx + 1;
strcpy(handler->props.includes[handler->props.num_includes].directive, p);
handler->props.num_includes++;
}
} else if (strncmp(p, "#define", 7) == 0) {
if (handler->props.num_defines < MAX_PROPS) {
handler->props.defines[handler->props.num_defines].line = idx + 1;
strcpy(handler->props.defines[handler->props.num_defines].directive, p);
handler->props.num_defines++;
}
} else if (strncmp(p, "#ifndef", 7) == 0 && !in_guard) {
handler->props.has_guard = 1;
sscanf(p, "#ifndef %255s", handler->props.guard_name);
in_guard = 1;
} else if (strncmp(p, "#endif", 6) == 0 && in_guard) {
in_guard = 0;
} else if (strstr(p, "(") && strstr(p, ")") && strstr(p, ";") && !strstr(p, "=")) { // Basic proto check
if (handler->props.num_prototypes < MAX_PROPS) {
handler->props.prototypes[handler->props.num_prototypes].line = idx + 1;
strcpy(handler->props.prototypes[handler->props.num_prototypes].directive, p);
handler->props.num_prototypes++;
}
}
line = strtok(NULL, "\n");
idx++;
}
handler->props.total_lines = idx;
}
void print_properties(HProperties *props) {
printf("=== .H File Properties ===\n");
printf("Total lines: %d\n", props->total_lines);
printf("\nIncludes:\n");
for (int i = 0; i < props->num_includes; i++) {
printf(" Line %d: %s\n", props->includes[i].line, props->includes[i].directive);
}
printf("\nDefines:\n");
for (int i = 0; i < props->num_defines; i++) {
printf(" Line %d: %s\n", props->defines[i].line, props->defines[i].directive);
}
printf("\nPrototypes:\n");
for (int i = 0; i < props->num_prototypes; i++) {
printf(" Line %d: %s\n", props->prototypes[i].line, props->prototypes[i].directive);
}
printf("\nGuards: %s (Name: %s)\n", props->has_guard ? "Yes" : "No", props->guard_name);
}
void write_file(const char *output_path, HProperties *props) {
FILE *fp = fopen(output_path, "w");
if (!fp) return;
if (props->has_guard) {
fprintf(fp, "#ifndef %s\n#define %s\n", props->guard_name, props->guard_name);
}
for (int i = 0; i < props->num_includes; i++) {
fprintf(fp, "%s\n", props->includes[i].directive);
}
for (int i = 0; i < props->num_defines; i++) {
fprintf(fp, "%s\n", props->defines[i].directive);
}
for (int i = 0; i < props->num_prototypes; i++) {
fprintf(fp, "%s\n", props->prototypes[i].directive);
}
if (props->has_guard) {
fprintf(fp, "#endif\n");
}
fclose(fp);
printf("Wrote .H file to %s\n", output_path);
}
/* Usage:
int main() {
HFileHandler handler;
init_handler(&handler, "sample.h");
if (read_and_decode(&handler)) {
write_file("output.h", &handler.props);
}
free(handler.content);
return 0;
}
*/