Skip to content

Commit a38facd

Browse files
committed
added additional tests and support for structs
1 parent 2dc6b28 commit a38facd

27 files changed

+2419
-80
lines changed

.gitmodules

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,12 @@
44
[submodule "testCRepos/repos/BLAKE2"]
55
path = testCRepos/repos/BLAKE2
66
url = https://github.com/BLAKE2/BLAKE2
7+
[submodule "testCRepos/repos/openssl"]
8+
path = testCRepos/repos/openssl
9+
url = https://github.com/openssl/openssl.git
10+
[submodule "testCRepos/repos/libsodium"]
11+
path = testCRepos/repos/libsodium
12+
url = https://github.com/jedisct1/libsodium.git
13+
[submodule "testCRepos/repos/liboqs"]
14+
path = testCRepos/repos/liboqs
15+
url = https://github.com/open-quantum-safe/liboqs.git

nimAutoWrapper.nimble

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,54 @@ task build_blake2, "Generate wrapper for BLAKE2 reference code":
1111
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
1212
exec "nim c -r nimAutoWrapper.nim testCRepos/repos/BLAKE2/ref/blake2.h testCRepos/builds/BLAKE2/blake2_wrapper.nim"
1313

14-
task build_repos, "Generate wrappers for all test repos":
14+
task build_openssl, "Build OpenSSL 3 and generate wrapper":
1515
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
16-
exec "nim c -r nimAutoWrapper.nim testCRepos/repos/tiny-AES-c/aes.h testCRepos/builds/tiny-AES-c/aes_wrapper.nim"
17-
exec "nim c -r nimAutoWrapper.nim testCRepos/repos/BLAKE2/ref/blake2.h testCRepos/builds/BLAKE2/blake2_wrapper.nim"
16+
exec "nim r tools/build_openssl.nim"
17+
exec "nim c -r nimAutoWrapper.nim testCRepos/repos/openssl/include/openssl/sha.h testCRepos/builds/openssl/openssl_sha_wrapper.nim"
18+
19+
task build_libsodium, "Build libsodium and generate wrapper":
20+
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
21+
exec "nim r tools/build_libsodium.nim"
22+
exec "nim r tools/prepare_libsodium_header.nim"
23+
exec "nim c -r nimAutoWrapper.nim testCRepos/builds/libsodium/sodium_combined.h testCRepos/builds/libsodium/libsodium_wrapper.nim"
24+
25+
task build_liboqs, "Build liboqs and generate wrapper":
26+
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
27+
exec "nim r tools/build_liboqs.nim"
28+
exec "nim r tools/prepare_liboqs_header.nim"
29+
exec "nim c -r nimAutoWrapper.nim testCRepos/builds/liboqs/oqs_full_combined.h testCRepos/builds/liboqs/liboqs_wrapper.nim"
30+
31+
task build_c_repos_basic, "Build C test repos without OpenSSL":
32+
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
33+
exec "nim r tools/build_libsodium.nim"
34+
exec "nim r tools/build_liboqs.nim"
35+
36+
task build_c_repos_all, "Build all C test repos":
37+
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
38+
exec "nim r tools/build_openssl.nim"
39+
exec "nim r tools/build_libsodium.nim"
40+
exec "nim r tools/build_liboqs.nim"
41+
42+
task build_repos, "Generate wrappers for all test repos":
43+
exec "nimble build_repos_basic"
44+
45+
task build_repos_basic, "Generate wrappers for test repos without OpenSSL":
46+
exec "nimble build_aes"
47+
exec "nimble build_blake2"
48+
exec "nimble build_libsodium"
49+
exec "nimble build_liboqs"
50+
51+
task build_repos_all, "Generate wrappers for all test repos":
52+
exec "nimble build_repos_basic"
53+
exec "nimble build_openssl"
1854

1955
task setup, "Fetch submodules for test repos":
2056
exec "nim r tools/ensure_env.nim -- --submodules"
2157

2258
task start, "Fetch submodules and build test wrappers":
2359
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
24-
exec "nimble build_repos"
60+
exec "nimble build_c_repos_basic"
61+
exec "nimble build_repos_basic"
2562

2663
task test_functionality, "Run tokenizer and utils tests":
2764
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
@@ -30,14 +67,42 @@ task test_functionality, "Run tokenizer and utils tests":
3067

3168
task test_realworld, "Run real-world wrapper tests":
3269
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
33-
exec "nimble build_repos"
70+
exec "nimble build_c_repos_basic"
71+
exec "nimble build_repos_basic"
72+
exec "nim c -r tests/realworld/tiny_aes_c_runner.nim"
73+
exec "nim c -r tests/realworld/blake2_ref_runner.nim"
74+
exec "nim c -r tests/realworld/libsodium_runner.nim"
75+
exec "nim c -r tests/realworld/liboqs_runner.nim"
76+
77+
task test_realworld_all, "Run all real-world wrapper tests":
78+
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
79+
exec "nimble build_c_repos_all"
80+
exec "nimble build_repos_all"
3481
exec "nim c -r tests/realworld/tiny_aes_c_runner.nim"
3582
exec "nim c -r tests/realworld/blake2_ref_runner.nim"
83+
exec "nim c -r tests/realworld/openssl3_runner.nim"
84+
exec "nim c -r tests/realworld/libsodium_runner.nim"
85+
exec "nim c -r tests/realworld/liboqs_runner.nim"
3686

3787
task test_all, "Run all tests":
3888
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
39-
exec "nimble build_repos"
89+
exec "nimble build_c_repos_basic"
90+
exec "nimble build_repos_basic"
91+
exec "nim c -r --path:. tests/functionality/test_tokenizer.nim"
92+
exec "nim c -r --path:. tests/functionality/test_utils.nim"
93+
exec "nim c -r tests/realworld/tiny_aes_c_runner.nim"
94+
exec "nim c -r tests/realworld/blake2_ref_runner.nim"
95+
exec "nim c -r tests/realworld/libsodium_runner.nim"
96+
exec "nim c -r tests/realworld/liboqs_runner.nim"
97+
98+
task test_all_full, "Run all tests including OpenSSL":
99+
exec "nim r tools/ensure_env.nim -- --submodules --builddirs"
100+
exec "nimble build_c_repos_all"
101+
exec "nimble build_repos_all"
40102
exec "nim c -r --path:. tests/functionality/test_tokenizer.nim"
41103
exec "nim c -r --path:. tests/functionality/test_utils.nim"
42104
exec "nim c -r tests/realworld/tiny_aes_c_runner.nim"
43105
exec "nim c -r tests/realworld/blake2_ref_runner.nim"
106+
exec "nim c -r tests/realworld/openssl3_runner.nim"
107+
exec "nim c -r tests/realworld/libsodium_runner.nim"
108+
exec "nim c -r tests/realworld/liboqs_runner.nim"

src/define_parser.nim

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,19 @@ proc hasTemplateLine*(s: ParserState, b: string): bool =
4141
dec i
4242
result = false
4343

44+
proc isSimpleDefineBody*(a: seq[Token]): bool =
45+
## a: define body tokens
46+
## Returns true when the body has no identifiers and can be emitted as a const.
47+
var
48+
i: int = 0
49+
l: int = a.len
50+
while i < l:
51+
if a[i].kind == tkIdentifier:
52+
result = false
53+
return
54+
inc i
55+
result = true
56+
4457
proc formatTemplateParams*(a: seq[string]): string =
4558
## a: parameter names
4659
## Formats names into a Nim template parameter list.
@@ -53,6 +66,47 @@ proc formatTemplateParams*(a: seq[string]): string =
5366
parts.add a[i] & ": untyped"
5467
result = parts.join(", ")
5568

69+
proc emitDefineTemplate*(s: var ParserState, b: string, c: seq[string], d: string,
70+
e: bool) =
71+
## s: parser state
72+
## b: template name
73+
## c: template parameter names
74+
## d: macro body text
75+
## e: include parentheses when there are no parameters
76+
## Emits a template stub for a macro definition.
77+
var
78+
paramsText: string = formatTemplateParams(c)
79+
if paramsText.len == 0:
80+
if e:
81+
emitLine(s, "template " & b & "*(): untyped =")
82+
else:
83+
emitLine(s, "template " & b & "*: untyped =")
84+
else:
85+
emitLine(s, "template " & b & "*(" & paramsText & "): untyped =")
86+
if s.config.emitComments and d.len > 0:
87+
emitLine(s, " ## C macro: " & d)
88+
emitLine(s, " discard")
89+
90+
proc collectDefineBodyTokens*(s: var ParserState): seq[Token] =
91+
## s: parser state
92+
## Collects macro body tokens across backslash-newline continuations.
93+
var
94+
items: seq[Token] = @[]
95+
tok: Token
96+
continueLine: bool = true
97+
while continueLine and not isAtEnd(s):
98+
continueLine = false
99+
tok = peekToken(s)
100+
while not isAtEnd(s) and tok.kind != tkNewline:
101+
items.add advanceToken(s)
102+
tok = peekToken(s)
103+
if tok.kind == tkNewline:
104+
discard advanceToken(s)
105+
if items.len > 0 and items[^1].text == "\\":
106+
discard items.pop()
107+
continueLine = true
108+
result = items
109+
56110
proc tryParseDefine*(s: var ParserState): bool =
57111
## s: parser state
58112
## Parses C #define directives into Nim consts or templates.
@@ -66,7 +120,6 @@ proc tryParseDefine*(s: var ParserState): bool =
66120
bodyText: string = ""
67121
constLine: string = ""
68122
params: seq[string] = @[]
69-
paramsText: string = ""
70123
paramName: string = ""
71124
tok: Token
72125
isFunc: bool = false
@@ -97,23 +150,16 @@ proc tryParseDefine*(s: var ParserState): bool =
97150
params.add paramName
98151
else:
99152
discard advanceToken(s)
100-
bodyTokens = collectUntilNewline(s)
153+
bodyTokens = collectDefineBodyTokens(s)
101154
if not isFunc:
102155
bodyTokens = stripLeadingCastTokens(bodyTokens)
103156
bodyText = tokensToText(bodyTokens)
104-
if isFunc:
157+
if isFunc or not isSimpleDefineBody(bodyTokens):
105158
name = registerName(s, name, origName, "template")
106159
if hasTemplateLine(s, name):
107160
result = true
108161
return
109-
paramsText = formatTemplateParams(params)
110-
if paramsText.len == 0:
111-
emitLine(s, "template " & name & "*(): untyped =")
112-
else:
113-
emitLine(s, "template " & name & "*(" & paramsText & "): untyped =")
114-
if s.config.emitComments and bodyText.len > 0:
115-
emitLine(s, " ## C macro: " & bodyText)
116-
emitLine(s, " discard")
162+
emitDefineTemplate(s, name, params, bodyText, isFunc)
117163
else:
118164
name = registerName(s, name, origName, "const")
119165
if bodyText.len == 0:

src/function_parser.nim

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import strutils
22
import name_mangle
33
import name_registry
4+
import type_mapper
45
import types
56
import utils
67

@@ -93,34 +94,24 @@ proc paramNameFromTokens*(a: seq[Token]): string =
9394
else:
9495
result = name
9596

96-
proc paramTypeFromTokens*(a: seq[Token]): string =
97+
proc paramTypeFromTokens*(s: var ParserState, a: seq[Token], b: string): string =
98+
## s: parser state
9799
## a: parameter tokens
98-
## Returns the Nim type for known C types, defaulting to pointer.
99-
var
100-
i: int = 0
101-
l: int = a.len
102-
tok: Token
103-
hasSizeT: bool = false
104-
while i < l:
105-
tok = a[i]
106-
if tok.kind == tkIdentifier and tok.text == "size_t":
107-
hasSizeT = true
108-
inc i
109-
if hasSizeT:
110-
result = "csize_t"
111-
else:
112-
result = "pointer"
100+
## b: parameter name to skip
101+
## Returns the Nim type for the parameter.
102+
result = mapTokensToNimType(s, a, b)
113103

114-
proc paramInfoFromTokens*(a: seq[Token]): ParamInfo =
104+
proc paramInfoFromTokens*(s: var ParserState, a: seq[Token]): ParamInfo =
105+
## s: parser state
115106
## a: parameter tokens
116107
## Builds a ParamInfo with a name and Nim type.
117108
var
118109
info: ParamInfo
119110
info.name = paramNameFromTokens(a)
120-
info.nimType = paramTypeFromTokens(a)
111+
info.nimType = paramTypeFromTokens(s, a, info.name)
121112
result = info
122113

123-
proc collectParamInfos*(s: ParserState): seq[ParamInfo] =
114+
proc collectParamInfos*(s: var ParserState): seq[ParamInfo] =
124115
## s: parser state
125116
## Collects parameter infos between parentheses.
126117
## Example: `int foo(int a, size_t n)` yields `@["a: pointer", "n: csize_t"]`.
@@ -141,12 +132,12 @@ proc collectParamInfos*(s: ParserState): seq[ParamInfo] =
141132
continue
142133
if tok.text == ")":
143134
if current.len > 0:
144-
info = paramInfoFromTokens(current)
135+
info = paramInfoFromTokens(s, current)
145136
if info.name.len > 0:
146137
params.add info
147138
break
148139
if tok.text == ",":
149-
info = paramInfoFromTokens(current)
140+
info = paramInfoFromTokens(s, current)
150141
if info.name.len > 0:
151142
params.add info
152143
current = @[]

src/name_registry.nim

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import strutils
12
import tables
23
import debugger
34
import types
@@ -14,6 +15,20 @@ proc altNameForKind*(a: string, b: string): string =
1415
else:
1516
result = ""
1617

18+
proc normalizeUsedName*(a: string): string =
19+
## a: Nim identifier
20+
## Returns a style-insensitive key for Nim identifiers.
21+
var
22+
i: int = 0
23+
l: int = a.len
24+
ch: char
25+
result = ""
26+
while i < l:
27+
ch = a[i]
28+
if ch != '_':
29+
result.add(toLowerAscii(ch))
30+
inc i
31+
1732
proc registerName*(s: var ParserState, a: string, b: string, c: string): string =
1833
## s: parser state
1934
## a: desired Nim name
@@ -26,34 +41,43 @@ proc registerName*(s: var ParserState, a: string, b: string, c: string): string
2641
alt: string = ""
2742
base: string = ""
2843
count: int = 0
44+
baseKey: string = ""
45+
altKey: string = ""
46+
nameKey: string = ""
2947
if s.nameMap.hasKey(key):
3048
result = s.nameMap[key]
3149
return
32-
if not s.usedNames.hasKey(a):
33-
s.usedNames[a] = 1
50+
baseKey = normalizeUsedName(a)
51+
if not s.usedNames.hasKey(baseKey):
52+
s.usedNames[baseKey] = 1
3453
s.nameMap[key] = a
3554
result = a
3655
return
3756
alt = altNameForKind(a, c)
38-
if alt.len > 0 and not s.usedNames.hasKey(alt):
39-
s.usedNames[alt] = 1
57+
if alt.len > 0:
58+
altKey = normalizeUsedName(alt)
59+
if alt.len > 0 and not s.usedNames.hasKey(altKey):
60+
s.usedNames[altKey] = 1
4061
s.nameMap[key] = alt
4162
recordCollision(s, a, b, alt)
4263
result = alt
4364
return
4465
base = a
4566
if alt.len > 0:
4667
base = alt
47-
if s.usedNames.hasKey(base):
48-
count = s.usedNames[base]
68+
baseKey = normalizeUsedName(base)
69+
if s.usedNames.hasKey(baseKey):
70+
count = s.usedNames[baseKey]
4971
else:
5072
count = 1
5173
name = base & "_" & $count
52-
while s.usedNames.hasKey(name):
74+
nameKey = normalizeUsedName(name)
75+
while s.usedNames.hasKey(nameKey):
5376
inc count
5477
name = base & "_" & $count
55-
s.usedNames[base] = count + 1
56-
s.usedNames[name] = 1
78+
nameKey = normalizeUsedName(name)
79+
s.usedNames[baseKey] = count + 1
80+
s.usedNames[nameKey] = 1
5781
s.nameMap[key] = name
5882
recordCollision(s, a, b, name)
5983
result = name

0 commit comments

Comments
 (0)