2010-12-30 27 views
5

Tôi có mã có rất nhiều mã lỗi #define phức tạp không dễ giải mã vì chúng được lồng trong nhiều cấp độ.Làm cách nào để tạo danh sách # giá trị xác định từ mã C?

Có cách nào tao nhã để tôi có thể nhận danh sách #defines với giá trị số cuối cùng của chúng (hoặc bất kỳ giá trị nào khác có thể) không?

Như một ví dụ:

<header1.h> 
#define CREATE_ERROR_CODE(class, sc, code) ((class << 16) & (sc << 8) & code) 
#define EMI_MAX 16 

<header2.h> 
#define MI_1 EMI_MAX 

<header3.h> 
#define MODULE_ERROR_CLASS MI_1 
#define MODULE_ERROR_SUBCLASS 1 
#define ERROR_FOO CREATE_ERROR_CODE(MODULE_ERROR_CLASS, MODULE_ERROR_SUBCLASS, 1) 

tôi sẽ có một số lượng lớn cáC# định nghĩa tương tự phù hợp với ERROR _ [\ w _] + mà tôi muốn liệt kê vì vậy mà tôi luôn luôn có một danh sách hiện tại của mã lỗi chương trình có thể xuất ra. Tôi cần giá trị bằng số vì đó là tất cả các chương trình sẽ in ra (và không, nó không phải là một tùy chọn để in ra một chuỗi thay vì).

Gợi ý cho gcc hoặc bất kỳ trình biên dịch nào khác sẽ hữu ích.

+0

Bạn đã xem xét ** sử dụng hằng số thực ** thay vì #defines chưa? –

+0

Việc thay đổi mã thành các const sẽ không thực tế vì nó được kế thừa từ một nguồn ngược dòng. – djs

Trả lời

4

Tôi nghĩ giải pháp là kết hợp các câu trả lời của @nmichaels và @ aschepler.

Sử dụng tùy chọn -dM của gcc để nhận danh sách các macro. Sử dụng perl hoặc awk hoặc bất kỳ thứ gì để tạo 2 tệp từ danh sách này:

1) Macro.h, chỉ chứa #defines.

2) Codes.c, trong đó có

#include "Macros.h" 

ERROR_FOO = "ERROR_FOO" 
ERROR_BAR = "ERROR_BAR" 

(ví dụ: trích xuất mỗi #define ERROR_x thành một phù hợp với vĩ mô và một chuỗi

bây giờ chạy gcc -E Codes.c Điều đó sẽ tạo ra một tập tin với tất cả.. các macro mở rộng. Đầu ra sẽ trông giống như

1 = "ERROR_FOO" 
2 = "ERROR_BAR" 

Tôi không có gcc tiện dụng, vì vậy chưa thử nghiệm ...

+1

Tôi đã thử điều này và chỉ với 6 perl một lớp xử lý cuối cùng tôi đã kết thúc với một danh sách được sắp xếp các giá trị số! Một vấn đề với giải pháp này là gcc -E -P mang lại cho tôi một tệp lớn với tất cả các tiêu đề đã được xử lý trước. Tôi đã xóa -P và chỉ lấy các dòng sau "# 2 Codes.c 2". Sửa lỗi này và tôi nghĩ bạn giành được số tiền thưởng ... – djs

+0

đã hoàn tất. -P được cho là "Ngăn chặn việc tạo ra các kẻ đánh dấu ở đầu ra từ bộ tiền xử lý", điều này có vẻ hữu ích để làm cho tệp trông sạch hơn. Oh well. – AShelly

+0

Khái niệm chính mà tôi bỏ lỡ ở đây là tôi không thể chỉ xử lý trước tiêu đề, tôi cần chạy một tệp C tham chiếu các hằng số đó để thực sự mở rộng nó. Một phần khác mà tôi đã bỏ lỡ, tôi đã tự tìm ra: Tôi chỉ có thể đạt được một biểu thức số học mà tôi cần phải đánh giá. Về mặt kỹ thuật, tôi cho rằng tôi cần biên dịch nó, nhưng tôi đã lừa dối và chuyển nó cho perl eval. – djs

7

GCC's -dMpreprocessor option có thể giúp bạn có được những gì bạn muốn.

+0

Điều này có vẻ giống như ý tưởng đúng, nhưng nó không mở rộng các macro của tôi. Tôi đã thử chạy 'gcc -E -Wp, -dD header3.h và tôi kết thúc với chính xáC#define như được định nghĩa ở trên. – djs

+1

@djs: Vâng, nó không hoàn toàn là tất cả các cách. '-dM' sẽ xuất ra một danh sách các macro mà bạn có thể nạp vào một kịch bản để tạo ra các mở rộng. – nmichaels

+0

Kết quả cuối cùng mặc dù là tôi có một danh sách các macro giống như hàm mà bộ tiền xử lý có thể mở rộng, nhưng điều mà tôi chắc chắn không muốn làm. Vì vậy, tôi cần một số cách để mở rộng chúng ... – djs

1

Nếu bạn có một danh sách đầy đủ của các macro bạn muốn xem, và tất cả đều là số, bạn có thể biên dịch và chạy một chương trình ngắn chỉ dành riêng cho mục đích này:

#include <header3.h> 
#include <stdio.h> 

#define SHOW(x) printf(#x " = %lld\n", (long long int) x) 

int main(void) { 
    SHOW(ERROR_FOO); 
    /*...*/ 
    return 0; 
} 

Như @nmichaels đề cập, gcc của -d cờ có thể giúp có được danh sách các macro để hiển thị.

2

Chương trình 'coan' trông giống như công cụ bạn đang theo dõi. Nó có các tiểu lệnh 'defs', được mô tả như sau:

defs [OPTION ...] [file ...] [thư mục ...]

Chọn #define#undef chỉ thị từ các tập tin đầu vào phù hợp với các tùy chọn và báo cáo chúng về đầu ra tiêu chuẩn phù hợp với các tùy chọn.

Xem URL được trích dẫn để biết thêm thông tin về các tùy chọn. Lấy mã số here.

+0

Ứng dụng thú vị. Tôi đã thực sự vui mừng về nó cho đến khi tôi phát hiện ra rằng nó không hỗ trợ mở rộng các macro giống như hàm. Có một khiếm khuyết mở để sửa lỗi này, vì vậy có lẽ một ngày nào đó nó sẽ là câu trả lời. – djs

1

Dưới đây là một chút giải pháp sáng tạo:

Viết một chương trình để phù hợp với tất cả các định danh của bạn với một biểu thức chính quy (như \#define :b+(?<NAME>[0-9_A-Za-z]+):b+(?<VALUE>[^(].+)$ trong .NET), sau đó có nó tạo ra một tập tin C chỉ với những cái tên xuất hiện:

void main() { 
    /*my_define_1*/ my_define_1; 
    /*my_define_2*/ my_define_2; 
    //... 
} 

Sau đó xử lý trước tệp của bạn bằng tùy chọn/C/P (cho VC++) và bạn sẽ nhận được tất cả những thay thế bằng giá trị. Sau đó, sử dụng regex khác để hoán đổi mọi thứ xung quanh và đặt nhận xét trước các giá trị ở định dạng #define - bây giờ bạn có danh sách các số #define!

(Bạn có thể làm điều gì đó tương tự với GCC.)

0

Có cách nào thanh lịch tôi có thể có được một danh sách cáC# định nghĩa với giá trị số cuối cùng của họ

Đối với mức độ khác nhau của sự sang trọng, loại.

#!/bin/bash 

file="mount.c"; 
for macro in $(grep -Po '(?<=#define)\s+(\S+)' "$file"); do 
    echo -en "$macro: "; 
    echo -en '#include "'"$file"'"\n'"$macro\n" | \ 
    cpp -E -P -x c ${CPPFLAGS} - | tail -n1; 
done; 

không đơn giản (#define \ \n macro(x) ... sẽ không bị bắt - nhưng không có phong cách tôi đã nhìn thấy không rằng).

Các vấn đề liên quan