# 帳票設計書 2-IREP Cソースダンプ (cfunc形式)

## 概要

mrubyの中間表現(IREP)をC言語のuint8_t配列として出力する帳票設計書である。`mrb_dump_irep_cfunc`関数により生成されたCファイルをコンパイルすることで、mrubyバイトコードをCプログラムに組み込んで利用できる。

### 本帳票の処理概要

本帳票は、mrubyコンパイラ(mrbc)がRubyスクリプトをコンパイルした結果得られる中間表現(IREP)を、C言語のソースコード形式で出力する機能である。出力されるCソースファイルには、RiteBinaryフォーマットのバイナリデータがuint8_t配列として埋め込まれる。このCファイルをアプリケーションと共にコンパイル・リンクすることで、外部ファイルを読み込むことなくmrubyバイトコードを実行できる。

**業務上の目的・背景**：組み込みシステムにおいて、ファイルシステムを持たない環境やROMに直接バイトコードを焼き込む必要がある環境で、mrubyスクリプトをC言語のデータとしてアプリケーションに静的に組み込むために使用される。これにより、実行時のファイルI/Oが不要となり、起動速度の向上とシステムの単純化が実現できる。

**帳票の利用シーン**：mrbcコマンドに`-B`オプション（`-S`なし）を指定して実行する場面で使用される。特に、組み込みLinuxやベアメタル環境でmrubyアプリケーションを構築する際のビルドパイプラインに組み込まれることが多い。

**主要な出力内容**：
1. `#include <stdint.h>` ヘッダーインクルード
2. extern宣言またはstatic宣言（`-s`フラグによる制御）
3. `const uint8_t {initname}[]` 配列宣言
4. RiteBinaryフォーマットのバイナリデータを16進数リテラルとして列挙

**帳票の出力タイミング**：mrbcコマンドを`-B <symbol>`オプション付きで（`-S`なしで）実行した際に出力される。例: `mrbc -B my_script script.rb` で `script.c` が生成される。

**帳票の利用者**：組み込みシステムエンジニア、mrubyアプリケーション開発者、ビルドシステム管理者。

## 帳票種別

Cソースコードファイル（.c形式テキストファイル）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLIコマンド (mrbc) | `mrbc -B <symbol> [options] script.rb` | mrbcコマンド実行（-Bオプション指定、-Sなし） |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | Cソースコード (.c) |
| 用紙サイズ | N/A（テキストファイル） |
| 向き | N/A |
| ファイル名 | 命名規則: `{入力ファイル名(拡張子なし)}.c` （-oオプションで任意指定可能） |
| 出力方法 | ファイル書き込み（fprintf/fputs） |
| 文字コード | ASCII |

### PDF固有設定

N/A（テキストファイル形式のため該当なし）

### Excel固有設定

N/A（テキストファイル形式のため該当なし）

## 帳票レイアウト

### レイアウト概要

出力されるCソースコードは、ヘッダーインクルード、配列宣言、バイナリデータ列挙、配列終端の構成をとる。

```
┌─────────────────────────────────────┐
│  #include <stdint.h>                │
│  extern / static 宣言               │
│  const uint8_t {name}[] = {         │
├─────────────────────────────────────┤
│  0xXX,0xXX,...  (16個ごとに改行)     │
│  0xXX,0xXX,...                       │
│  ...                                │
├─────────────────────────────────────┤
│  };                                 │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | インクルード文 | `#include <stdint.h>` | 固定文字列 | テキスト |
| 2 | ストレージクラス | `static` または `extern` (C++対応) | MRB_DUMP_STATICフラグ | テキスト |
| 3 | 配列宣言 | `const uint8_t {initname}[] = {` | -Bオプション引数 | テキスト |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | バイナリデータ | RiteBinaryフォーマットの各バイト | mrb_dump_irep()の出力バッファ | `0x%02x,` 形式 | 可変 |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 配列終端 | `};` | 固定文字列 | テキスト |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 入力ファイル | コンパイル対象のRubyスクリプトファイル(.rb) | Yes |
| -B \<symbol\> | 生成される配列名（initname） | Yes |
| -s フラグ | static修飾子を付加する場合に指定 | No |
| -g フラグ | デバッグ情報を含める場合に指定 | No |

### ソート順

N/A（バイナリデータのバイト順序はRiteBinaryフォーマットに従う）

### 改ページ条件

16バイトごとに改行を挿入（`bin_idx % 16 == 0` の条件で改行出力）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照しない。mrb_dump_irep関数で生成されたバイナリバッファを参照する。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| mrb_irep (構造体) | IREP本体データ | コンパイル結果から直接取得 |

### テーブル別参照項目詳細

#### mrb_irep

No.1「IREPバイナリダンプ (mrb形式)」と同一。mrb_dump_irepを内部で呼び出してバイナリデータを生成するため、参照データ構造は同一である。

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| バイナリデータサイズ | mrb_dump_irepの出力（bin_size） | なし | mrb_dump_irep内部で計算 |
| 改行位置 | `bin_idx % 16 == 0` | なし | 16バイトごと |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[mrbcコマンド実行 -B option] --> B[コマンドライン引数解析 parse_args]
    B --> C[Rubyスクリプト読み込み load_file]
    C --> D[コンパイル mrb_load_file_cxt]
    D --> E{コンパイル成功?}
    E -->|No| F[エラー出力・終了]
    E -->|Yes| G[出力ファイルオープン]
    G --> H[dump_file呼び出し]
    H --> I{-Sオプションあり?}
    I -->|Yes| J[mrb_dump_irep_cstruct呼び出し]
    I -->|No| K[mrb_dump_irep_cfunc呼び出し]
    K --> L[mrb_dump_irep でバイナリ生成]
    L --> M[#include stdint.h 出力]
    M --> N[extern/static + 配列宣言出力]
    N --> O[バイナリデータを16進数で列挙出力]
    O --> P[配列終端 出力]
    P --> Q[メモリ解放・終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| MRB_DUMP_INVALID_ARGUMENT (-6) | fp==NULL, initname==NULL, initname空文字 | `invalid C language symbol name` | -Bオプションの引数を確認 |
| MRB_DUMP_WRITE_FAULT (-2) | fprintf/fputs失敗 | `error in mrb dump ({outfile}) -2` | ディスク容量の確認 |
| MRB_DUMP_GENERAL_FAILURE (-1) | mrb_dump_irep内部エラー | `error in mrb dump ({outfile}) -1` | mruby状態の確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1スクリプトファイルのバイナリサイズに依存（通常数KB〜数百KB） |
| 目標出力時間 | ミリ秒単位 |
| 同時出力数上限 | 1（mrbcは単一プロセスで動作） |

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

- 出力されるCソースファイルにバイナリデータが平文で含まれるため、逆アセンブル可能
- `static`修飾子（-sフラグ）を使用することで、シンボルの外部リンケージを防止可能
- デバッグ情報を含む場合、ソースファイル名や行番号がバイナリに含まれる

## 備考

- cfunc形式は実行時にmrb_load_irep()等でバイナリデータをロードする必要がある
- cstruct形式（No.3）と比較して、ロード時にバイナリ解析のオーバーヘッドがある
- C++からの利用を考慮して、`static`フラグなしの場合は`#ifdef __cplusplus / extern / #endif`で囲まれる
- `#include <stdint.h>`は特にDarwin環境でuint8_tの定義に必要なために含まれる

---

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

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

### 推奨読解順序

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

No.1「IREPバイナリダンプ (mrb形式)」と共通。mrb_irep構造体とRiteBinaryフォーマットの理解が前提となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | irep.h | `include/mruby/irep.h` | `struct mrb_irep`（55-80行目）: IREPデータ構造の全体像 |
| 1-2 | dump.h | `include/mruby/dump.h` | ダンプフラグ `MRB_DUMP_STATIC`（21行目）: static修飾子制御 |

**読解のコツ**: cfunc形式はmrb_dump_irepでバイナリを生成した後、そのバイトデータを16進数テキストとしてCソースに書き出すラッパーである。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mrbc.c | `mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c` | `dump_file`関数（258-281行目）: 263行目の`if (args->initname)`で-Bオプション指定時の分岐、268行目でmrb_dump_irep_cfuncを呼び出し |
| 2-2 | mrbc.c | `mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c` | `parse_args`関数（118-129行目）: -Bオプションの解析。initnameに配列名を設定 |

**主要処理フロー**:
1. **118行目**: `-B`オプション検出
2. **119-125行目**: 配列名（initname）の取得
3. **263行目**: dump_file内でinitname有無の判定
4. **268行目**: mrb_dump_irep_cfunc呼び出し

#### Step 3: cfuncダンプのコア処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dump.c | `src/dump.c` | `mrb_dump_irep_cfunc`（951-996行目）: cfunc形式出力のメイン処理 |

**主要処理フロー**:
- **955行目**: 引数検証（fp, initname, initname空文字チェック）
- **959行目**: mrb_dump_irep()でバイナリデータを生成
- **961行目**: `#include <stdint.h>`を出力
- **965-975行目**: MRB_DUMP_STATICフラグに応じて`static`または`extern`(C++)宣言と配列名を出力
- **976-987行目**: バイナリデータを1バイトずつ`0x%02x,`形式で出力。16バイトごとに改行
- **988行目**: 配列終端 `};` を出力
- **994行目**: メモリ解放

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

```
main() [mrbc.c:284]
    │
    ├─ parse_args() [mrbc.c:88]
    │      └─ -B オプション処理 [mrbc.c:118-129]
    │
    ├─ load_file() [mrbc.c:219]
    │      └─ mrb_load_file_cxt() [外部: コンパイラ]
    │
    └─ dump_file() [mrbc.c:258]
           │
           └─ mrb_dump_irep_cfunc() [dump.c:951]
                  │
                  ├─ mrb_dump_irep() [dump.c:820]  ← バイナリ生成
                  │      └─ (No.1と同じ内部処理)
                  │
                  ├─ fprintf() ← #include出力
                  ├─ fprintf() ← extern/static + 配列宣言出力
                  ├─ fprintf() ← 0x%02x データ列挙 (16バイトごと改行)
                  └─ fputs()   ← }; 終端出力
```

### データフロー図

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

.rb スクリプト ───▶ mrb_load_file_cxt() ───▶ mrb_irep (メモリ上)

mrb_irep ───────▶ mrb_dump_irep() ─────────▶ uint8_t *bin (バイナリ)

uint8_t *bin ───▶ mrb_dump_irep_cfunc() ──▶ .c ファイル
                   │                          │
                   ├─ #include出力              │
                   ├─ 配列宣言出力              │
                   ├─ 各バイトを0x%02x変換      │
                   └─ 配列終端出力              │
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dump.c | `src/dump.c` | ソース | mrb_dump_irep_cfunc関数の実装（951-996行目） |
| dump.h | `include/mruby/dump.h` | ヘッダー | MRB_DUMP_STATICフラグ定義、エラーコード定義 |
| irep.h | `include/mruby/irep.h` | ヘッダー | mrb_irep構造体定義 |
| mrbc.c | `mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c` | ソース | mrbcコマンドのエントリーポイント、-Bオプション解析 |
