以下の環境で動作確認をしています。(すべて x86 のみ対応)
- Debian Linux 2.6.18-6-686
- NetBSD 4.0
- OpenBSD 4.2
- FreeBSD 6.3
- MacOS X 10.5.7
- Windows XP
- Windows Vista
twitterにおいてリリース情報などを発表していく予定です。
http://twitter.com/gommadofjp/
ぜひフォローをお願いします!
TNTの商品サービスについてのお問い合わせは電子メールにて info@trans-nt.comまでお願いいたします。
GommaDof
Generator of memory manager and Database-oriented framework
What is GommaDof ?
GommaDof は拡張BNFから安全で効率のよい様々なデータ構造とそれらを扱うための関数を自動生成するコードジェネレータです。GommaDof を導入することで、ソフトウェア技術者はバグやパフォーマンス低下を生じやすいメモリまわりの煩雑な管理から解放され、開発の本質となる処理の設計・実装に注力できるようになります。
GommaDof はメモリ使用効率が良く、検索速度に優れたデータ構造を生成し、カスタマイズによりコンテナ型データの構造や検索キーを最適化することができます。また、メモリ確保・解放、文字列やTLV(type length value)構造との相互変換など、メモリに対する操作としてよく用いられる必要性の高い関数を生成することができます。拡張BNFの記述を変更するだけで、データ構造と関数を一括して自動生成できるため、開発時の問題の切り分けも容易になり、バグの発生を低減します。また、仕様への追従が早く、Rapid Prototyping に有用で、仕様変更にも柔軟な対応が可能になります。
GommaDof のメリット
- 文字列とデータの相互変換による開発・デバッグコストの低減。
- 効率のよいデータ構造。
- バグ発生を低減。
- メモリ管理が分離されて問題の切り分けが容易に。
- 操作関数の記述が不要。
- 拡張BNFを記述するだけで簡単
→ コスト低減・開発期間短縮
GommaDof はC言語のソースコードを生成します。他の言語についてはご相談ください。
Why do we need GommaDof ?
開発現場の次のような問題がしばしば発生し、開発の効率が低下し、開発期間・コストの増大につながっています。
- 何度も同じようなメモリ管理のコードを書いている。
- データ構造を変更したら関数も全部作り直し。
- メモリ確保・解放の整合性がとれない。
- 無駄なメモリ操作で性能が上がらない。
- 毎度同じようなコードを書くことに疑問を感じる。
このような問題はGommaDof が解決します!
Where does GommaDof work?
- ネットワーク機器、ルーティングプロトコルの設計・開発
- 各種組込み機器、制御関連部分設計・開発
- エンドユーザ向けソフトウェア、仕様変更が多く発生するソフトウェアの設計・開発
- 短期間での試作・評価
How does GommaDof work?
Address ::= “IPv4” uint8 uint8 uint8 uint8
| “IPv6” uint16 uint16 uint16 uint16 uint16 uint16 uint16 uint16;
Nodes ::= Address*;
Segment ::= “Seg” Address Nodes; — “Seg” (GW addr) (other nodes)
わずか4行のBNFを入力
3800行超のデータ構造・関数を生成
コードの生成例

ソースコードの一部
Address.h
#ifndef Address_H_INCLUDED #define Address_H_INCLUDED struct GC_context; union Address; typedef void (* IPv4_apply_func_t)(struct GC_context *, unsigned char , unsigned char , unsigned char , unsigned char ); typedef void (* IPv6_apply_func_t)(struct GC_context *, unsigned short , unsigned short , unsigned short , unsigned short , unsigned short , unsigned short , unsigned short , unsigned short ); #define Address_apply_(cx, obj, prefix) \ (Address_apply(cx, obj \ , prefix##IPv4 \ , prefix##IPv6 \ )) void Address_apply(struct GC_context *cx, union Address *x, IPv4_apply_func_t func_IPv4, IPv6_apply_func_t func_IPv6); void Address_delete(struct GC_context *cx, union Address *x); unsigned char Address_get_IPv4_m1(struct GC_context *cx, union Address *x); unsigned char Address_get_IPv4_m2(struct GC_context *cx, union Address *x); unsigned char Address_get_IPv4_m3(struct GC_context *cx, union Address *x); unsigned char Address_get_IPv4_m4(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m1(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m2(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m3(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m4(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m5(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m6(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m7(struct GC_context *cx, union Address *x); unsigned short Address_get_IPv6_m8(struct GC_context *cx, union Address *x); union Address * Address_getroot_IPv4(struct GC_context *cx); union Address * Address_getroot_IPv6(struct GC_context *cx); enum Tags Address_gettag(struct GC_context *cx, union Address *x); union Address * Address_new_IPv4(struct GC_context *cx); union Address * Address_new_IPv6(struct GC_context *cx); union Address * Address_newset_IPv4(struct GC_context *cx, unsigned char m1, unsigned char m2, unsigned char m3, unsigned char m4); union Address * Address_newset_IPv6(struct GC_context *cx, unsigned short m1, unsigned short m2, unsigned short m3, unsigned short m4, unsigned short m5, unsigned short m6, unsigned short m7, unsigned short m8); const char * Address_read(struct GC_context *cx, const char *str, union Address **x, void *cont0); void Address_set_IPv4_m1(struct GC_context *cx, union Address *x, unsigned char arg); void Address_set_IPv4_m2(struct GC_context *cx, union Address *x, unsigned char arg); void Address_set_IPv4_m3(struct GC_context *cx, union Address *x, unsigned char arg); void Address_set_IPv4_m4(struct GC_context *cx, union Address *x, unsigned char arg); void Address_set_IPv6_m1(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m2(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m3(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m4(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m5(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m6(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m7(struct GC_context *cx, union Address *x, unsigned short arg); void Address_set_IPv6_m8(struct GC_context *cx, union Address *x, unsigned short arg); struct GTstring * Address_show(struct GC_context *cx, union Address *x); unsigned int Address_tlvdecode(struct GC_context *cx, const char *str, union Address **x); struct GTstring * Address_tlvencode(struct GC_context *cx, union Address *x, unsigned int *length); #endif /* !Address_H_INCLUDED */
Nodes.h
#ifndef Nodes_H_INCLUDED #define Nodes_H_INCLUDED struct GC_context; union Address; struct Nodes; typedef void (*Nodes_foreach_func_t )(struct GC_context *,union Address *); void Nodes_add(struct GC_context *cx, struct Nodes *base, union Address *x); void Nodes_addlist(struct GC_context *cx, struct Nodes *left, struct Nodes *right); void Nodes_delete(struct GC_context *cx, struct Nodes *x); void Nodes_foreach(struct GC_context *cx, struct Nodes *x, Nodes_foreach_func_t func); union Address * Nodes_get(struct GC_context *cx, struct Nodes *x, int n); struct Nodes * Nodes_getroot(struct GC_context *cx); int Nodes_length(struct GC_context *cx, struct Nodes *x); struct Nodes * Nodes_new(struct GC_context *cx); const char * Nodes_read(struct GC_context *cx, const char *str, struct Nodes **x, void *cont0); void Nodes_remove(struct GC_context *cx, struct Nodes *base, union Address *x); void Nodes_removeall(struct GC_context *cx, struct Nodes *base); void Nodes_set(struct GC_context *cx, struct Nodes *x, int n, union Address *arg); struct GTstring * Nodes_show(struct GC_context *cx, struct Nodes *x); unsigned int Nodes_tlvdecode(struct GC_context *cx, const char *str, struct Nodes **x); struct GTstring * Nodes_tlvencode(struct GC_context *cx, struct Nodes *x, unsigned int *length); #endif /* !Nodes_H_INCLUDED */
Segment.h
#ifndef Segment_H_INCLUDED #define Segment_H_INCLUDED struct GC_context; union Address; struct Nodes; union Segment; typedef void (* Seg_apply_func_t)(struct GC_context *, union Address *, struct Nodes *); #define Segment_apply_(cx, obj, prefix) \ (Segment_apply(cx, obj \ , prefix##Seg \ )) void Segment_apply(struct GC_context *cx, union Segment *x, Seg_apply_func_t func_Seg); void Segment_delete(struct GC_context *cx, union Segment *x); union Address * Segment_get_Seg_m1(struct GC_context *cx, union Segment *x); struct Nodes * Segment_get_Seg_m2(struct GC_context *cx, union Segment *x); union Address * Segment_get_m1(struct GC_context *cx, union Segment *x); struct Nodes * Segment_get_m2(struct GC_context *cx, union Segment *x); union Segment * Segment_getroot_Seg(struct GC_context *cx); enum Tags Segment_gettag(struct GC_context *cx, union Segment *x); union Segment * Segment_new_Seg(struct GC_context *cx); union Segment * Segment_newset_Seg(struct GC_context *cx, union Address *m1, struct Nodes *m2); const char * Segment_read(struct GC_context *cx, const char *str, union Segment **x, void *cont0); void Segment_set_Seg_m1(struct GC_context *cx, union Segment *x, union Address *arg); void Segment_set_Seg_m2(struct GC_context *cx, union Segment *x, struct Nodes *arg); void Segment_set_m1(struct GC_context *cx, union Segment *x, union Address *arg); void Segment_set_m2(struct GC_context *cx, union Segment *x, struct Nodes *arg); struct GTstring * Segment_show(struct GC_context *cx, union Segment *x); unsigned int Segment_tlvdecode(struct GC_context *cx, const char *str, union Segment **x); struct GTstring * Segment_tlvencode(struct GC_context *cx, union Segment *x, unsigned int *length); #endif /* !Segment_H_INCLUDED */
Address.c 抜粋
#include <assert.h> #include <ctype.h> #include <string.h> #include "00EnumTags.h" #include "Address.h" #include "00PrimInt.h" struct IPv4 { unsigned char m1; unsigned char m2; unsigned char m3; unsigned char m4; }; struct IPv6 { unsigned short m1; unsigned short m2; unsigned short m3; unsigned short m4; unsigned short m5; unsigned short m6; unsigned short m7; unsigned short m8; }; union Address { struct IPv4 m1; struct IPv6 m2; };
Nodes.c 抜粋
#include <assert.h> #include <ctype.h> #include "00EnumTags.h" #include "Address.h" #include "Nodes.h" struct Nodes { struct Nodes *link; union Address *m1; };
Segment.c 抜粋
#include <assert.h> #include <ctype.h> #include <string.h> #include "00EnumTags.h" #include "Address.h" #include "Nodes.h" #include "Segment.h" struct Seg { union Address *m1; struct Nodes *m2; }; union Segment { struct Seg m1; };