2014-05-03 26 views
0

我想將文件數量轉換爲C中的靜態字符串聲明。我試圖用Python編寫一個快速腳本(如下所示),但它看起來並不簡單,問題出現了,試圖編譯輸出。將文件轉換爲靜態C字符串聲明

import os, sys 
from glob import glob 
from re import sub 

test_dirs = ('basics', 'float', 'import', 'io', 'misc') 
tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files) 

def cfunc_name(t): 
    return sub(r'/|\.|-', '_', t) 

for t in tests: 
    print("void {}(void* data) {{".format(cfunc_name(t))) 
    with open(t) as f: 
    lines = ''.join(f.readlines()) 
    cstr = sub('"', '\\"', lines) 
    cstr = sub('\n', '\"\n\"', cstr) 
    print(" const char * pystr = \"\"\n\"{}\";".format(cstr)) 
    print("end:\n ;\n}") 

print("struct testcase_t core_tests[] = {") 

for t in tests: 
    print(" {{ \"{}\", test_{}_fn, TT_ENABLED_, 0, 0 }},".format(t, cfunc_name(t))) 

print("END_OF_TESTCASES };") 

尋找現有的工具是不完全明顯(可能是我的搜索關鍵詞是不完全正確)...有一個簡單的UNIX工具,做這樣或有沒有人遇到類似的東西來嗎?

回答

1

這是否適合您? https://code.google.com/p/txt2cs/

我能想到的主要問題是新線條和逃跑,如果你想自己推出。

+2

非打印/控制字符(你所提到的新行)和正確的字符編碼也很重要。 – Deduplicator

+0

我設法繞過換行符和內部雙引號,但是像_「十六進制轉義序列超出範圍」這樣的編譯器錯誤_有點極端,我真的不想處理(除非必須)。 – errordeveloper

+0

我真的認爲你會更好地使用鏈接的項目(這不是我的項目)。你發佈的代碼真的很離譜。 'sub('\ n','\'\ n \'',cstr)'應該是'sub(「\ n」,'\\ n',cstr)''''''如果我正在寫東西,我會替換這些:http://en.cppreference.com/w/cpp/language/escape加上不在32-127之間的任何字符。請注意,\ xHH語法只能編碼一個*字節*,即0-255--所以要小心python的Unicode處理,除非您使用\ u或\ U而不是 – teambob

0

我已經使用txt2cs實現作爲參考,最後只用了幾行Python來完成所有轉義。由於我不想在構建系統中添加額外的東西,因此在Python中完成這項工作會更容易。這將被集成到測試自動化中,這已經是一個複雜的野獸。

主要問題是RE替代必須按照一定的順序完成,並不是實現此目的的理想工具。

import os, sys 
from glob import glob 
from re import sub 

def escape(s): 
    lookup = { 
    '\0': '\\0', 
    '\t': '\\t', 
    '\n': '\\n\"\n\"', 
    '\r': '\\r', 
    '\\': '\\\\', 
    '\"': '\\\"', 
    } 
    return "\"\"\n\"{}\"".format(''.join([lookup[x] if x in lookup else x for x in s])) 

def chew_filename(t): 
    return { 'func': "test_{}_fn".format(sub(r'/|\.|-', '_', t)), 'desc': t.split('/')[1] } 

def script_to_map(t): 
    r = { 'name': chew_filename(t)['func'] } 
    with open(t) as f: r['script'] = escape(''.join(f.readlines())) 
    return r 

test_function = (
    "void {name}(void* data) {{\n" 
    " const char * pystr = {script};\n" 
    " do_str(pystr);\n" 
    "}}" 
) 

testcase_struct = (
    "struct testcase_t {name}_tests[] = {{\n{body}\n END_OF_TESTCASES\n}};" 
) 
testcase_member = (
    " {{ \"{desc}\", {func}, TT_ENABLED_, 0, 0 }}," 
) 

testgroup_struct = (
    "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};" 
) 
testgroup_member = (
    " {{ \"{name}/\", {name}_tests }}," 
) 

test_dirs = ('basics', 'float', 'import', 'io', 'misc') 

output = [] 

for group in test_dirs: 
    tests = glob('{}/*.py'.format(group)) 
    output.extend([test_function.format(**script_to_map(test)) for test in tests]) 
    testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] 
    output.append(testcase_struct.format(name=group, body='\n'.join(testcase_members))) 

testgroup_members = [testgroup_member.format(name=group) for group in test_dirs] 

output.append(testgroup_struct.format(body='\n'.join(testgroup_members))) 

print('\n\n'.join(output)) 

下面是輸出看起來像什麼,你可以看到初始""\n'\\n\"\n\"'使相當多的可讀:

void test_basics_break_py_fn(void* data) { 
    const char * pystr = "" 
"while True:\n" 
" break\n" 
"\n" 
"for i in range(4):\n" 
" print('one', i)\n" 
" if i > 2:\n" 
"  break\n" 
" print('two', i)\n" 
"\n" 
"for i in [1, 2, 3, 4]:\n" 
" if i == 3:\n" 
"  break\n" 
" print(i)\n" 
""; 
    do_str(pystr); 
}