質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

1回答

2618閲覧

有効なマクロの一覧を取得したい

l9uftn

総合スコア3

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/10/06 05:14

編集2021/10/07 06:29

下記の件につきまして、
解決策や代替案、その他何らかの知見等ございましたら、お教えいただけないでしょうか。

前提・実現したいこと

define や undef、ifdef、コメント(// や /* */) が乱立しているソースコードを含むプロジェクト上から、
有効なマクロの一覧を取得したいです。
※下記のようなファイルがプロジェクト上に複数あるイメージです。

cpp

1/* macro.h */ 2#define MACRO_A 3#define MACRO_B 4#define MACRO_C 5#define MACRO_D 6 7#undef MACRO_B 8 9#ifdef MACRO_A 10#define MACRO_A1 11#endif 12 13/* #define MACRO_E */ 14// #define MACRO_F 15/* #define MACRO_G 16*/ 17/* 18#define MACRO_G*/ 19/* 20#define MACRO_H 21*/

cpp

1/* sample.c */ 2#include "macro.h" 3 4#undef MACRO_C 5 6#ifdef MACRO_A1 7#define MACRO_A2 8#endif 9 10#ifndef MACRO_B 11#undef MACRO_D 12#define MACRO_A3 13#endif 14

上記の場合、以下のように有効なマクロの一覧が取得したいです。

MACRO_A MACRO_A1 MACRO_A2 MACRO_A3

発生している問題

gcc や clang で -dM オプションを利用するように、
定義済みのマクロの一覧を取得したいのですが、
Visual C++ (Visual Studio 2010) で同様のことを実現する方法が見つかりませんでした。

(参考)
知っていると便利な gcc のオプション
gcc のプリプロセッサの定義済みマクロ(Predefined Macros)の確認方法 - Qiita

試したこと

正規表現を使って、有効な define を絞り込もうとしましたが、
ifdef や undef や /* */ により、
有効なマクロのみを絞り込むことができませんでした。

補足情報(FW/ツールのバージョンなど)

IDE:Visual Studio 2010
言語:Visual C++
生成物:DLL(ActiveX コントロール)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/10/06 05:24

「clang の定義済みマクロを取得する」のリンクの記事で示されている方法は、コンパイラが事前に定義しているマクロの一覧であって、質問者さんがお求めのソースコード中から有効なマクロを取り出す方法ではないと思いますがどうでしょうか。
l9uftn

2021/10/06 06:48

ご指摘ありがとうございます。修正いたしました。
matukeso

2021/10/06 10:28

たとえばinclude windows.hしているとそれだけで多分defineって10000個とか出て来ると思いますけど、そういうのを求めてます?
l9uftn

2021/10/06 10:38

可能であれば標準や外部のライブラリのヘッダは除外したいですが、 それも含めて取得することになっても構わないです。
l9uftn

2021/10/06 11:11

後者です。 ご質問の意図を読み違えておりました。 失礼しました。
guest

回答1

0

あーたしかによくよく処理を読めば、unifdefは引数から定義されたdefineをつかってifdefを剥がすだけで、コードからdefine/undef/includeを処理しないですね。
ま、ifdefとかの処理はできるので、こういう感じの改造を入れればそれっぽく出ましたが、incldueの処理を手抜きしてあるのでちゃんと動かすならそのあたりの手当が必要かな、という感じですね。(長いので省略しましたが、outputをダミーにしておく必要もあります)

あるいはVS2019あたりを入れて、clangに食わせたほうが速いかもしれません。

C

1 2@@ -367,6 +367,17 @@ 3 processinout(*argv, *argv); 4 argv++; 5 } 6+ 7+ { 8+ int i; 9+ fprintf(stderr, "Symbols\n"); 10+ for( i=0; i< nsyms; i++){ 11+ if( symname[i] && value[i] ){ 12+ fprintf(stderr, "%s\n", symname[i] ); 13+ } 14+ 15+ } 16+ } 17 18 19+ 20+static const char *getsym(const char **cpp); 21+ 22 static Linetype 23 parseline(void) 24 { 25@@ -800,6 +816,57 @@ 26 goto done; 27 } 28 keyword = tline + (cp - tline); 29+ 30+ if ((cp = matchsym("define", keyword)) != NULL){ 31+ const char *end = cp + strlen(cp); 32+ 33+ const char *sym = getsym(&cp); 34+ const char *val; 35+ if (sym == NULL) 36+ error("Missing macro name in #define"); 37+ if (*cp == '(') { 38+ val = "1"; 39+ } else { 40+ cp = skipcomment(cp); 41+ val = (cp < end) ? xstrdup(cp, end) : ""; 42+ } 43+ debug("#define"); 44+ addsym2(false, sym, val); 45+ } 46+ else if ((cp = matchsym("undef", keyword)) != NULL){ 47+ const char *sym = getsym(&cp); 48+ debug("undef:%s\n", sym); 49+ addsym2( false, sym, NULL); 50+ } 51+ else if ((cp = matchsym("include", keyword)) != NULL){ 52+ int pos = strcspn( cp, "\"<\n"); 53+ 54+ if( cp[pos] == '"' ) 55+ { 56+ const char *st = cp+pos+1; 57+ const char *end = strchr( st, '"'); 58+ if( end ){ 59+ char *incl = xstrdup(st,end); 60+ FILE *old = input; 61+ FILE *oldout = output; 62+ 63+ output = fbinmode(stdout); 64+ 65+ input = fopen(incl, "rb"); 66+ if( input ){ 67+ debug("INCLUDE %s start", incl ); 68+ process(); 69+ debug("INCLUDE %s end\n", incl ); 70+// fclose(input); 71+ } 72+ output = oldout; 73+ input = old; 74+ } 75+ } 76+ } 77

unifdefをビルドして、-sオプションをつけて.cppファイルを食わせるのはどうでしょうか。
ビルド時点でプロジェクトによってdefineされるものは下記stackoverflowの方法で取得してunifdefに引き渡してやる必要があります。

http://dotat.at/prog/unifdef/
参考 https://stackoverflow.com/questions/3665537/how-to-find-out-cl-exes-built-in-macros
参考 https://qiita.com/tokudiro/items/0643e15f5b973ec030c5

投稿2021/10/06 11:20

編集2021/10/07 10:40
matukeso

総合スコア1681

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

l9uftn

2021/10/07 05:44 編集

ご回答くださりありがとうございます。 実際に動作させて確認してみたのですが、 #ifdef 等で利用されているマクロ名も共に出力されてしまうため、 有効なマクロを特定することはできないようでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問