# 機能設計書 21-rc

## 概要

本ドキュメントは、Zigコンパイラに組み込まれたWindowsリソースコンパイラ（rc）機能について記述する。この機能により、ZigをMicrosoft rc.exeのドロップイン代替として使用できる。

### 本機能の処理概要

**業務上の目的・背景**：
Windowsアプリケーション開発において、アイコン、バージョン情報、メニュー、ダイアログなどのリソースをコンパイルする必要がある。従来はMicrosoft Visual Studioに付属するrc.exeを使用していたが、これはWindows環境でのみ利用可能であり、クロスコンパイル環境では使用できない。Zigのrc機能は、この問題を解決し、どのプラットフォームからでもWindowsリソースをコンパイル可能にする。

**機能の利用シーン**：
- Windowsアプリケーションにアイコンやバージョン情報を埋め込む際
- .rcファイルを.resファイルまたはCOFFオブジェクトファイルに変換する際
- Linux/macOSからWindowsアプリケーションをクロスコンパイルする際
- 既存のMSVC rc.exeを使用するビルドシステムからの移行時

**主要な処理内容**：
1. コマンドライン引数の解析（rc.exe互換オプションをサポート）
2. .rcファイルの前処理（Aroプリプロセッサを使用したCプリプロセッサ処理）
3. リソーススクリプトの字句解析・構文解析
4. リソースデータのコンパイル（アイコン、カーソル、ビットマップ等の変換）
5. .resファイルまたはCOFFオブジェクトファイルの出力

**関連システム・外部連携**：
- Aro Cプリプロセッサとの連携（前処理フェーズ）
- リンカとの連携（COFF出力時）
- libc検出機能との連携（インクルードパス解決）

**権限による制御**：
本機能は特定の権限制御を持たない。ファイルシステムへのアクセス権限はOS標準のファイルパーミッションに従う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | RCツール画面 | 主画面 | zig rc コマンド実行時のWindowsリソースコンパイル処理 |

## 機能種別

データ変換処理 / コンパイル処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| INPUT | ファイルパス | Yes | 入力.rcファイルまたは.resファイル | 存在確認、拡張子チェック |
| OUTPUT | ファイルパス | No | 出力ファイルパス | 省略時は入力ファイル名から生成 |
| /fo | ファイルパス | No | 出力ファイルパス指定 | - |
| /d | 識別子[=値] | No | プリプロセッサシンボル定義 | - |
| /u | 識別子 | No | プリプロセッサシンボル未定義化 | - |
| /i | ディレクトリパス | No | インクルードパス追加 | - |
| /l | 16進数 | No | デフォルト言語ID（例: 409） | 0-FFFF |
| /ln | 文字列 | No | デフォルト言語名（例: en-us） | - |
| /c | 数値 | No | デフォルトコードページ（例: 65001） | - |
| /x | フラグ | No | INCLUDE環境変数を無視 | - |
| /v | フラグ | No | 詳細出力モード | - |
| /p | フラグ | No | 前処理のみ実行 | - |
| /n | フラグ | No | 文字列テーブルをNULL終端 | - |
| /sl | 数値 | No | 文字列リテラル長制限（1-100%） | 1-100 |
| /:target | アーキテクチャ | No | ターゲットマシン（X64、ARM64等） | サポート対象のみ |
| /:input-format | 列挙型 | No | 入力形式（rc/res/rcpp） | - |
| /:output-format | 列挙型 | No | 出力形式（res/coff/rcpp） | - |
| /:auto-includes | 列挙型 | No | 自動インクルードパス検出（any/msvc/gnu/none） | - |
| /:depfile | ファイルパス | No | 依存関係ファイル出力パス | - |
| /:no-preprocess | フラグ | No | 前処理をスキップ | - |

### 入力データソース

- 入力ファイル: .rcファイル（リソーススクリプト）または.resファイル
- インクルードファイル: .h、.rcヘッダファイル
- リソースファイル: .ico、.cur、.bmp、.png等の画像ファイル
- 環境変数: INCLUDE（インクルードパス指定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| .res ファイル | バイナリ | コンパイル済みリソースファイル |
| .obj/.o ファイル | バイナリ | COFFオブジェクトファイル |
| .rcpp ファイル | テキスト | 前処理済みリソーススクリプト |
| 依存関係ファイル | JSON | インクルードファイルの一覧 |

### 出力先

- 指定された出力ファイルパス
- 標準出力（-o - 指定時）
- 標準エラー出力（エラー・警告メッセージ）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数解析
   └─ cli.parse()で引数を解析しOptionsを構築

2. 入力ファイル準備
   └─ 入力形式に応じてファイルを読み込み
   └─ .rc拡張子が省略されている場合は補完

3. 前処理（preprocess != .no の場合）
   └─ Aro Cプリプロセッサで#include、#define等を展開
   └─ インクルードパスを解決（auto-includes設定に従う）

4. コメント除去・行番号マッピング
   └─ Cスタイルコメントを除去
   └─ #lineコマンドを解析してソースマッピングを構築

5. リソースコンパイル（input_format != .res の場合）
   └─ 字句解析（lex.zig）
   └─ 構文解析（parse.zig）
   └─ リソースコンパイル（compile.zig）
   └─ .res形式で出力

6. COFF変換（output_format == .coff の場合）
   └─ .resをパース（cvtres.parseRes）
   └─ COFFオブジェクトファイルを生成（cvtres.writeCoff）

7. 出力・クリーンアップ
   └─ 出力ファイルへ書き込み
   └─ 依存関係ファイル出力（指定時）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン引数解析]
    B --> C{ヘルプ表示?}
    C -->|Yes| D[ヘルプ出力]
    D --> Z[終了]
    C -->|No| E[入力ファイル読み込み]
    E --> F{前処理必要?}
    F -->|Yes| G[Aroプリプロセッサ実行]
    G --> H{前処理のみ?}
    H -->|Yes| I[前処理結果出力]
    I --> Z
    H -->|No| J[コメント除去・行番号マッピング]
    F -->|No| J
    J --> K{入力形式=res?}
    K -->|Yes| N[.resをパース]
    K -->|No| L[リソースコンパイル]
    L --> M{出力形式=coff?}
    M -->|Yes| N
    M -->|No| O[.res出力]
    O --> Z
    N --> P[COFF出力]
    P --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | rc.exe互換性 | Microsoft rc.exeと同じオプション形式をサポート | 常時 |
| BR-02 | 自動拡張子補完 | 入力ファイルに拡張子がなく存在しない場合.rcを補完 | input_format=rc |
| BR-03 | デフォルト出力形式 | 出力形式未指定時はinput_formatに応じて推論 | 常時 |
| BR-04 | コードページ変換 | リソース文字列を指定コードページでエンコード | 文字列処理時 |
| BR-05 | 重複リソースエラー | 同一ID/タイプ/言語のリソースが重複するとエラー | COFF出力時 |

### 計算ロジック

**文字列リテラル長制限**:
- /sl オプションの値（1-100）に応じて最大文字列長を決定
- 100% = 8192文字（max_string_literal_length_100_percent）
- デフォルト = 4097文字（default_max_string_literal_codepoints）

## データベース操作仕様

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ParseError | 構文エラー | .rcファイルの構文不正 | エラー箇所と詳細を表示 |
| CompileError | コンパイルエラー | リソース定義の不正 | エラー箇所と詳細を表示 |
| FileNotFound | ファイルエラー | 入力/インクルードファイルが存在しない | ファイルパスを確認 |
| DuplicateResource | 重複エラー | 同一リソースが重複定義 | リソースID/タイプ/言語を確認 |
| ResourceDataTooLong | サイズエラー | リソースデータがCOFF上限超過 | データを分割 |
| PreprocessError | 前処理エラー | プリプロセッサエラー | #include等を確認 |

### リトライ仕様

本機能にリトライ機構は存在しない。エラー発生時はプロセスを終了する。

## トランザクション仕様

本機能はトランザクションを使用しない。出力ファイルへの書き込みはバッファリングされ、エラー発生時は出力ファイルを削除してクリーンアップする。

## パフォーマンス要件

- 典型的な.rcファイル（数十リソース）のコンパイルは1秒以内
- 大規模プロジェクト（数百リソース）でも数秒以内

## セキュリティ考慮事項

- 入力ファイルパスの検証
- シンボリックリンク攻撃への対策（ファイルオープン時の検証）
- 出力ファイルの安全な書き込み（一時ファイル経由は使用しない）

## 備考

- 本機能はZigの標準ライブラリとAroプリプロセッサを使用してPure Zigで実装されている
- Microsoft rc.exeと100%の互換性を目指すが、一部未サポート機能あり（MUI、LCX/LCE関連）
- resinator という名前で内部的に管理されている

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、CLIオプションとリソース定義のデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cli.zig | `lib/compiler/resinator/cli.zig` | Options構造体でCLIオプションを定義。IoSource、AutoIncludes、InputFormat、OutputFormat等の列挙型 |
| 1-2 | res.zig | `lib/compiler/resinator/res.zig` | リソース定義のデータ構造、NameOrOrdinal等 |

**読解のコツ**:
- Options構造体の各フィールドがrc.exeのどのオプションに対応するか把握する
- SymbolValue union型でdefine/undefineの両方を表現している点に注目

#### Step 2: エントリーポイントを理解する

処理の起点となるmain.zigとresinatarのmain.zigを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | main.zig | `src/main.zig` | rcコマンドのディスパッチ処理（309-317行目） |
| 2-2 | main.zig | `lib/compiler/resinator/main.zig` | resinatarのメイン処理フロー |

**主要処理フロー**:
1. **309-317行目**: `mem.eql(u8, cmd, "rc")`でrcコマンドを検出し、jitCmdを呼び出し
2. **21-413行目（resinator/main.zig）**: 全体の処理フロー。cli.parse → 前処理 → コンパイル → COFF変換

#### Step 3: CLI引数解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cli.zig | `lib/compiler/resinator/cli.zig` | parse関数で引数を解析しOptionsを構築 |

**主要処理フロー**:
- **14-82行目**: usage_string_after_command_nameでヘルプメッセージ定義
- **84-88行目**: writeUsage関数でヘルプ出力

#### Step 4: 前処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | preprocess.zig | `lib/compiler/resinator/preprocess.zig` | Aro Cプリプロセッサとの連携 |
| 4-2 | main.zig | `lib/compiler/resinator/main.zig` | 124-208行目で前処理を実行 |

**主要処理フロー**:
- **146行目**: aro.Compilation.init でAroコンパイラを初期化
- **169行目**: preprocess.preprocess で前処理実行

#### Step 5: リソースコンパイルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | lex.zig | `lib/compiler/resinator/lex.zig` | 字句解析器 |
| 5-2 | parse.zig | `lib/compiler/resinator/parse.zig` | 構文解析器 |
| 5-3 | compile.zig | `lib/compiler/resinator/compile.zig` | リソースコンパイラ本体 |

**主要処理フロー**:
- **281行目（main.zig）**: compile関数でリソースをコンパイル

#### Step 6: COFF出力を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | cvtres.zig | `lib/compiler/resinator/cvtres.zig` | .res → COFF変換処理 |

**主要処理フロー**:
- **357行目（main.zig）**: cvtres.parseRes で.resをパース
- **375行目（main.zig）**: cvtres.writeCoff でCOFF出力

### プログラム呼び出し階層図

```
src/main.zig::mainArgs()
    │
    └─ jitCmd() [rcコマンド検出時]
           │
           └─ lib/compiler/resinator/main.zig::main()
                  │
                  ├─ cli.parse() [引数解析]
                  │
                  ├─ preprocess.preprocess() [前処理]
                  │      └─ aro.Compilation [Aroプリプロセッサ]
                  │
                  ├─ parseAndRemoveLineCommands() [行番号マッピング]
                  │
                  ├─ removeComments() [コメント除去]
                  │
                  ├─ compile() [リソースコンパイル]
                  │      ├─ lex [字句解析]
                  │      ├─ parse [構文解析]
                  │      └─ リソース処理
                  │
                  ├─ cvtres.parseRes() [.resパース]
                  │
                  └─ cvtres.writeCoff() [COFF出力]
```

### データフロー図

```
[入力]                    [処理]                         [出力]

.rcファイル ─────────────┐
                         │
インクルードファイル ────┤
                         │
#define等の定義 ─────────┼──▶ Aroプリプロセッサ ──▶ 前処理済み.rc
                         │
                         │
前処理済み.rc ───────────┼──▶ 字句解析・構文解析
                         │
                         ├──▶ リソースコンパイラ ───▶ .resファイル
                         │
                         └──▶ cvtres変換 ──────────▶ COFFオブジェクト

.resファイル ────────────────▶ cvtres変換 ──────────▶ COFFオブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| main.zig | `src/main.zig` | ソース | rcコマンドのディスパッチ |
| main.zig | `lib/compiler/resinator/main.zig` | ソース | resinatarのエントリーポイント |
| cli.zig | `lib/compiler/resinator/cli.zig` | ソース | CLI引数解析、Optionsデータ構造 |
| preprocess.zig | `lib/compiler/resinator/preprocess.zig` | ソース | Aroプリプロセッサ連携 |
| lex.zig | `lib/compiler/resinator/lex.zig` | ソース | リソーススクリプト字句解析 |
| parse.zig | `lib/compiler/resinator/parse.zig` | ソース | リソーススクリプト構文解析 |
| ast.zig | `lib/compiler/resinator/ast.zig` | ソース | 抽象構文木定義 |
| compile.zig | `lib/compiler/resinator/compile.zig` | ソース | リソースコンパイラ本体 |
| res.zig | `lib/compiler/resinator/res.zig` | ソース | .resファイル形式処理 |
| cvtres.zig | `lib/compiler/resinator/cvtres.zig` | ソース | .res→COFF変換 |
| ico.zig | `lib/compiler/resinator/ico.zig` | ソース | アイコンファイル処理 |
| bmp.zig | `lib/compiler/resinator/bmp.zig` | ソース | ビットマップファイル処理 |
| ani.zig | `lib/compiler/resinator/ani.zig` | ソース | アニメーションカーソル処理 |
| errors.zig | `lib/compiler/resinator/errors.zig` | ソース | エラー診断・メッセージ |
| code_pages.zig | `lib/compiler/resinator/code_pages.zig` | ソース | コードページ処理 |
| lang.zig | `lib/compiler/resinator/lang.zig` | ソース | 言語ID処理 |
| source_mapping.zig | `lib/compiler/resinator/source_mapping.zig` | ソース | ソースマッピング |
| comments.zig | `lib/compiler/resinator/comments.zig` | ソース | コメント除去処理 |
| literals.zig | `lib/compiler/resinator/literals.zig` | ソース | リテラル処理 |
| utils.zig | `lib/compiler/resinator/utils.zig` | ソース | ユーティリティ関数 |
| windows1252.zig | `lib/compiler/resinator/windows1252.zig` | ソース | Windows-1252エンコーディング |
| disjoint_code_page.zig | `lib/compiler/resinator/disjoint_code_page.zig` | ソース | コードページ判定 |
