以前もここで質問したものです。皆様の解答をヒントに一歩進みました。
C言語のソースコードを扱っています。
デバッグのため(関数がどういう順番で呼び出されているかを知るため)、関数の先頭にprint文をつけようと思っています。
例えば、
int hoge(引数の並び)
{
関数の中身
}
なら
int hoge(引数の並び)
{
printf("hoge");
関数の中身
}
といった具合です。
関数が膨大なので、手作業で一つずつprintfを書くのは現実的ではありません。
ここで、
open(IN,"$ARGV[0]");
@array = <IN>;
for($i=0;$i<@array;$i++){
if($array[$i] =~ / _*.+\(.*\)/){
$tmp = $&;
if($array[$i+1] =~ "^{\n"){
print $array[$i];
print $array[$i+1];
print "printf(\"FileName:$ARGV[0] FunctionName:";
print $tmp;
print "\");";
print "\n";
$i++;}
else{
print $array[$i];
}
}else{
print $array[$i];
}
}
というコードを書きました。しかしこれでもうまくいかないケースが多々ありました。
int
main(void)
{
intro();
new_game();
/* @@@ exit(0); */ /* causes a warning in C++ */
return(0);
}
のように返り値が横ではなく上についていたり、
void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
ast_string_field *fields, int num_fields,
int index, const char *format, ...)
{
のように引数が複数行にわたる場合です。
どのようにしたらよいのでしょうか。
どなたか教えてもらえませんか?
No.4ベストアンサー
- 回答日時:
表示がずれるので、空白2文字を全角空白にしていることに注意
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#ifndef __CYGWIN32__
#include <dlfcn.h>
#endif
/* BINARY HACKS P.300 */
/* 関数への enter/exit をフックする */
#ifndef __CYGWIN32__
__attribute__((no_instrument_function))
void addr2name(void *func_address, char *func_name)
{
Dl_info dli;
if (0 != dladdr(func_address, &dli)) {
strcpy(func_name, dli.dli_sname);
}
else {
strcpy(func_name, "");
}
}
#endif
__attribute__((no_instrument_function))
void __cyg_profile_func_enter(void *func_address, void *call_site)
{
extern void *__libc_stack_end;
char func_name[256];
int stack_size;
void *frame = __builtin_frame_address(1) + 8;
#ifndef __CYGWIN32__
addr2name(func_address, func_name);
stack_size = __libc_stack_end - __builtin_frame_address(0);
#else
strcpy(func_name, "");
stack_size = 0;
#endif
printf("enter %s:%p, from=%p stack size=%d\n",
func_name, func_address, call_site, stack_size);
}
__attribute__((no_instrument_function))
void __cyg_profile_func_exit(void *func_address, void *call_site)
{
char func_name[256];
#ifndef __CYGWIN32__
addr2name(func_address, func_name);
#else
strcpy(func_name, "");
#endif
printf("exit %s:%p, from=%p\n", func_name, func_address, call_site);
}
void sub_func(int arg1, char arg2, char *arg3)
{
}
void func(int arg1, char arg2, char *arg3)
{
sub_func(arg1, arg2, arg3);
}
__attribute__((no_instrument_function))
void func_no_instrument_function(int arg1, char arg2, char *arg3)
{
}
__attribute__((no_instrument_function))
int main(int argc, char *argv[])
{
int arg1 = 10;
char arg2 = 20;
char *arg3 = "abc";
printf("sub_func = %p\n", sub_func);
printf("func = %p\n", func);
func(arg1, arg2, arg3);
func_no_instrument_function(arg1, arg2, arg3);
return 0;
}
/* $ gcc -g -finstrument-functions -rdynamic foo.c -o a.out -ldl && ./a.out */
/* sub_func = 0x804891e */
/* func = 0x8048952 */
/* enter func:0x8048952, from=0x8048a13 stack size=264 */
/* enter sub_func:0x804891e, from=0x804898b stack size=312 */
/* exit sub_func:0x804891e, from=0x804898b */
/* exit func:0x8048952, from=0x8048a13 */
No.3
- 回答日時:
のつづきでしょうか?
真面目にやろうとすると、C言語の構文解析プログラムになり、かなり面倒です。
簡潔にしたかったら、整形ツール(astyle, uncrustify等)で書式を整え、一定の規則(引数はかならず開き括弧と別の行、とか、定義の開始の{はかならず行頭、とか)にそろえてから、その規則に従った正規表現にするのがいいと思います。
No.2
- 回答日時:
GCC なら C99 が使える. あとはコーディングの問題だけど,
・関数の最初の { はインデントせず行頭にある
・それ以外のブロックを始める { は行頭にないかインデントされている
という条件を満たすなら
$/ = undef;
$program = <>;
$program =~ s/\)\s*\n\{/$&printf("FileName: %s FunctionName: %s\\n, __FILE__, __func__);/g;
print $program;
でだいたいいけると思う.
上の条件を満たさないと突然面倒だが.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- その他(プログラミング・Web制作) 十進BASICでの再帰についての質問です。 2 2022/11/18 09:17
- Ruby パイソンプログラミング 2 2022/12/03 18:44
- その他(プログラミング・Web制作) listへのappendが出来ない件 1 2022/12/06 21:44
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- その他(プログラミング・Web制作) pythonのmap、結果の利用は1度だけ? 5 2022/06/11 12:33
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
組み合わせを作るアルゴリズム
-
データベースから取得したデー...
-
プログラミングについて。 1つ...
-
画面を強制的に再描画させる方法
-
VBのReturnの使い方
-
DoEventsが必要な理由について
-
クラスに配列を渡す方法
-
pythonでファイルのコメント行...
-
DOSコマンドのループ内のTIMEコ...
-
For文を使った九九表の作成
-
VBAで3秒だけ時間を止めたい
-
英語でのシャープとコメの呼び...
-
vbscriptでIE自動入力(途中で...
-
ループ内での条件処理
-
CSVファイルの特定の行だけを読...
-
GIFアニメをループさせたくない
-
VBA横データを縦にしたいです
-
vb.netからエクセル関数書き込み
-
VBScript 配列
-
エクセル関数で1〜12の数字がル...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
データベースから取得したデー...
-
perlで2つの配列を比較する方...
-
DBIを使ってのデータの取り出し...
-
python質問
-
perlでファイルの拡張子を除い...
-
アルファベットn文字の組み合わ...
-
grep関数を用いた複数行からの抽出
-
乱数と順列と組み合わせ
-
半角文字の縦書き表示
-
配列やハッシュで中身が同じか...
-
ループ中でのmy宣言と処理速度
-
桁数指定と四捨五入
-
画面を強制的に再描画させる方法
-
VBAで3秒だけ時間を止めたい
-
VBAでの一時停止と再開の方法
-
VBのReturnの使い方
-
どなたかこのプログラミングを...
-
Escキーを押すと、中断する時と...
-
UWSCの終了の仕方
-
エクセルの当番表を作っていま...
おすすめ情報