Skip to content

Commit 345655e

Browse files
authored
add custom prefix to autogenerated C functions (#268)
1 parent 1ce1225 commit 345655e

File tree

10 files changed

+1128
-1470
lines changed

10 files changed

+1128
-1470
lines changed

cmd/mkcgo/generate.go

Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ func generateGo(src *mkcgo.Source, w io.Writer) {
1919
// This block outputs C header includes and forward declarations for loader functions.
2020
fmt.Fprintf(w, "/*\n")
2121
fmt.Fprintf(w, "#cgo CFLAGS: -Wno-attributes\n\n")
22-
for _, file := range src.Files {
23-
fmt.Fprintf(w, "#include %q\n", file)
24-
}
2522
if *includeHeader != "" {
2623
fmt.Fprintf(w, "#include \"%s\"\n", *includeHeader)
2724
}
@@ -39,10 +36,10 @@ func generateGo(src *mkcgo.Source, w io.Writer) {
3936
// Generate Go wrapper functions that load and unload the C symbols.
4037
for _, tag := range src.Tags() {
4138
fmt.Fprintf(w, "func mkcgoLoad_%s(handle unsafe.Pointer) {\n", tag)
42-
fmt.Fprintf(w, "\tC.__mkcgoLoad_%s(handle)\n", tag)
39+
fmt.Fprintf(w, "\tC.__mkcgo_load_%s(handle)\n", tag)
4340
fmt.Fprintf(w, "}\n\n")
4441
fmt.Fprintf(w, "func mkcgoUnload_%s() {\n", tag)
45-
fmt.Fprintf(w, "\tC.__mkcgoUnload_%s()\n", tag)
42+
fmt.Fprintf(w, "\tC.__mkcgo_unload_%s()\n", tag)
4643
fmt.Fprintf(w, "}\n\n")
4744
}
4845

@@ -57,14 +54,13 @@ func generateGo(src *mkcgo.Source, w io.Writer) {
5754

5855
// Generate function wrappers.
5956
for _, fn := range src.Funcs {
60-
if fn.Variadic() {
61-
// cgo doesn't support variadic functions
57+
if !fnCalledFromGo(fn) {
6258
continue
6359
}
6460
if fn.Optional {
6561
// Generate a function that returns true if the function is available.
66-
fmt.Fprintf(w, "func %s_Available() bool {\n", fn.GoName)
67-
fmt.Fprintf(w, "\treturn C.%s_Available() != 0\n", fn.ImportName)
62+
fmt.Fprintf(w, "func %s() bool {\n", fnGoNameAvailable(fn))
63+
fmt.Fprintf(w, "\treturn C.%s() != 0\n", fnCNameAvailable(fn))
6864
fmt.Fprintf(w, "}\n\n")
6965
}
7066
generateGoFn(fn, w)
@@ -81,10 +77,7 @@ func generateGo124(src *mkcgo.Source, w io.Writer) {
8177
// This block outputs C header includes and forward declarations for loader functions.
8278
fmt.Fprintf(w, "/*\n")
8379
for _, fn := range src.Funcs {
84-
name := fn.CName
85-
if fnNeedErrWrapper(fn) {
86-
name = fnCErrWrapperName(fn)
87-
}
80+
name := fnCName(fn)
8881
if fn.NoEscape {
8982
fmt.Fprintf(w, "#cgo noescape %s\n", name)
9083
}
@@ -155,13 +148,26 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) {
155148
fmt.Fprintf(w, "#ifndef MKCGO_H // only include this header once\n")
156149
fmt.Fprintf(w, "#define MKCGO_H\n\n")
157150

158-
for _, file := range src.Files {
159-
fmt.Fprintf(w, "#include %q\n", file)
160-
}
161151
if *includeHeader != "" {
162-
fmt.Fprintf(w, "#include \"%s\"\n", *includeHeader)
152+
fmt.Fprintf(w, "#include %q\n\n", *includeHeader)
153+
}
154+
155+
// Source includes.
156+
for _, v := range src.Includes {
157+
fmt.Fprintf(w, "#include %s\n", v)
158+
}
159+
fmt.Fprintf(w, "\n")
160+
161+
// Source types and enums.
162+
for _, def := range src.TypeDefs {
163+
fmt.Fprintf(w, "typedef %s %s;\n", def.Type, def.Name)
163164
}
164165
fmt.Fprintf(w, "\n")
166+
fmt.Fprintf(w, "enum {\n")
167+
for _, enum := range src.Enums {
168+
fmt.Fprintf(w, "\t%s = %s,\n", enum.Name, enum.Value)
169+
}
170+
fmt.Fprintf(w, "};\n\n")
165171

166172
// Custom types
167173
fmt.Fprintf(w, "typedef void* %s;\n", mkcgoErrState)
@@ -171,25 +177,30 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) {
171177

172178
// Add forward declarations for loader functions.
173179
for _, tag := range src.Tags() {
174-
fmt.Fprintf(w, "void __mkcgoLoad_%s(void* handle);\n", tag)
175-
fmt.Fprintf(w, "void __mkcgoUnload_%s();\n", tag)
180+
fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle);\n", tag)
181+
fmt.Fprintf(w, "void __mkcgo_unload_%s();\n", tag)
176182
}
177183
fmt.Fprintf(w, "\n")
178184

179185
// Add forward declarations for optional functions.
180186
for _, fn := range src.Funcs {
181187
if fn.Optional {
182-
fmt.Fprintf(w, "int %s_Available();\n", fn.ImportName)
188+
fmt.Fprintf(w, "int %s();\n", fnCNameAvailable(fn))
183189
}
184190
}
185191
fmt.Fprintf(w, "\n")
186192

187193
// Add forward declarations for function wrappers returning errors.
188194
for _, fn := range src.Funcs {
189-
if !fnNeedErrWrapper(fn) {
195+
if !fnCalledFromGo(fn) {
196+
// cgo doesn't support variadic functions, no need to include them.
190197
continue
191198
}
192-
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret.Type, fnCErrWrapperName(fn), fnCErrWrapperParams(fn, false))
199+
if fnNeedErrWrapper(fn) {
200+
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret.Type, fnCName(fn), fnCErrWrapperParams(fn, false))
201+
} else {
202+
fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret.Type, fnCName(fn), fnToCArgs(fn, true, false))
203+
}
193204
}
194205
fmt.Fprintf(w, "\n")
195206
fmt.Fprintf(w, "#endif // MKCGO_H\n")
@@ -204,11 +215,8 @@ func generateC(src *mkcgo.Source, w io.Writer) {
204215
fmt.Fprintf(w, "#include <stdlib.h>\n")
205216
fmt.Fprintf(w, "#include <stdint.h>\n")
206217
fmt.Fprintf(w, "#include <stdio.h>\n")
207-
for _, file := range src.Files {
208-
fmt.Fprintf(w, "#include %q\n", file)
209-
}
210218
if *includeHeader != "" {
211-
fmt.Fprintf(w, "#include \"%s\"\n", *includeHeader)
219+
fmt.Fprintf(w, "#include %q\n", *includeHeader)
212220
}
213221
fmt.Fprintf(w, "#include \"%s\"\n", autogeneratedFileName(".h"))
214222
fmt.Fprintf(w, "\n")
@@ -222,12 +230,11 @@ func generateC(src *mkcgo.Source, w io.Writer) {
222230
fmt.Fprintf(w, "#endif\n\n")
223231

224232
// Function pointer declarations.
225-
fmt.Fprintf(w, "#define __mkcgo__funcptr(name) typeof(name) *_g_##name;\n\n")
226233
for _, fn := range src.Funcs {
227234
if fn.VariadicInst {
228235
continue
229236
}
230-
fmt.Fprintf(w, "__mkcgo__funcptr(%s);\n", fn.ImportName)
237+
fmt.Fprintf(w, "%s (*_g_%s)(%s);\n", fn.Ret.Type, fn.ImportName, fnToCArgs(fn, true, false))
231238
}
232239
fmt.Fprintf(w, "\n")
233240

@@ -242,7 +249,7 @@ func generateC(src *mkcgo.Source, w io.Writer) {
242249

243250
// Loader and unloader functions for each tag.
244251
for _, tag := range src.Tags() {
245-
fmt.Fprintf(w, "void __mkcgoLoad_%s(void* handle) {\n", tag)
252+
fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle) {\n", tag)
246253
for _, fn := range src.Funcs {
247254
if fn.VariadicInst {
248255
continue
@@ -267,7 +274,7 @@ func generateC(src *mkcgo.Source, w io.Writer) {
267274
}
268275
fmt.Fprintf(w, "}\n\n")
269276

270-
fmt.Fprintf(w, "void __mkcgoUnload_%s() {\n", tag)
277+
fmt.Fprintf(w, "void __mkcgo_unload_%s() {\n", tag)
271278
for _, fn := range src.Funcs {
272279
if fn.VariadicInst {
273280
continue
@@ -292,26 +299,25 @@ func generateC(src *mkcgo.Source, w io.Writer) {
292299
typedefs[def.Name] = def.Type
293300
}
294301
for _, fn := range src.Funcs {
295-
if fn.Variadic() {
296-
// cgo doesn't support variadic functions
302+
if !fnCalledFromGo(fn) {
303+
// cgo doesn't support variadic functions, no need to include them.
297304
continue
298305
}
299306
if fn.Optional {
300307
// Generate a function that returns true if the function is available.
301-
fmt.Fprintf(w, "int %s_Available() {\n", fn.CName)
308+
fmt.Fprintf(w, "int %s() {\n", fnCNameAvailable(fn))
302309
fmt.Fprintf(w, "\treturn _g_%s != NULL;\n", fn.ImportName)
303310
fmt.Fprintf(w, "}\n\n")
304311
}
305-
generateCFn(fn, w)
306-
generateCFnErrorWrapper(typedefs, fn, w)
312+
generateCFn(typedefs, fn, w)
307313
}
308314
}
309315

310316
// generateGoFn generates Go function f.
311317
func generateGoFn(fn *mkcgo.Func, w io.Writer) {
312-
fnCall := fmt.Sprintf("C.%s(%s)", fn.CName, fnToGoArgs(fn))
318+
fnCall := fmt.Sprintf("C.%s(%s)", fnCName(fn), fnToGoArgs(fn))
313319
// Function definition
314-
fmt.Fprintf(w, "func %s(%s)", fn.GoName, fnToGoParams(fn))
320+
fmt.Fprintf(w, "func %s(%s)", fnGoName(fn), fnToGoParams(fn))
315321
if retIsVoid(fn.Ret) {
316322
// Easy path, just call the C function. No need to write the return types,
317323
// nor do error handling, nor cast the return value.
@@ -320,17 +326,16 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) {
320326
fmt.Fprintf(w, "}\n\n")
321327
return
322328
}
323-
typ, _ := cTypeToGo(fn.Ret.Type, false)
329+
goType, needCast := cTypeToGo(fn.Ret.Type, false)
324330
if fn.NoError {
325-
fmt.Fprintf(w, " %s ", typ)
331+
fmt.Fprintf(w, " %s ", goType)
326332
} else {
327-
fmt.Fprintf(w, " (%s, error) ", typ)
333+
fmt.Fprintf(w, " (%s, error) ", goType)
328334
}
329335
fmt.Fprintf(w, "{\n")
330336

331337
// Function call
332338
var needUnsafeCast bool
333-
goType, needCast := cTypeToGo(fn.Ret.Type, false)
334339
if needCast && goType[0] == '*' {
335340
goType = fmt.Sprintf("(%s)(unsafe.Pointer", goType)
336341
needUnsafeCast = true
@@ -351,7 +356,7 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) {
351356
return
352357
}
353358
fmt.Fprintf(w, "\tvar _err C.%s\n", mkcgoErrState)
354-
fmt.Fprintf(w, "\t_ret := C.%s(", fnCErrWrapperName(fn))
359+
fmt.Fprintf(w, "\t_ret := C.%s(", fnCName(fn))
355360
args := fnToGoArgs(fn)
356361
if len(args) > 0 {
357362
args += ", "
@@ -368,26 +373,22 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) {
368373
} else {
369374
fmt.Fprintf(w, "_ret")
370375
}
371-
fmt.Fprintf(w, ", newMkcgoErr(%q, _err)\n", fn.CName)
372-
fmt.Fprintf(w, "}\n\n")
373-
}
374-
375-
func generateCFn(fn *mkcgo.Func, w io.Writer) {
376-
fmt.Fprintf(w, "%s %s(%s) {\n\t", fn.Ret.Type, fn.CName, fnToCArgs(fn, true, true))
377-
if !retIsVoid(fn.Ret) {
378-
fmt.Fprintf(w, "return ")
379-
}
380-
fmt.Fprintf(w, "_g_%s(%s);\n", fn.ImportName, fnToCArgs(fn, false, true))
376+
fmt.Fprintf(w, ", newMkcgoErr(%q, _err)\n", fn.Name)
381377
fmt.Fprintf(w, "}\n\n")
382378
}
383379

384-
// generateCFnErrorWrapper generates C function wrapper for function f
385-
// that returns an error state.
386-
func generateCFnErrorWrapper(typedefs map[string]string, fn *mkcgo.Func, w io.Writer) {
380+
func generateCFn(typedefs map[string]string, fn *mkcgo.Func, w io.Writer) {
387381
if !fnNeedErrWrapper(fn) {
382+
fmt.Fprintf(w, "%s %s(%s) {\n\t", fn.Ret.Type, fnCName(fn), fnToCArgs(fn, true, true))
383+
if !retIsVoid(fn.Ret) {
384+
fmt.Fprintf(w, "return ")
385+
}
386+
fmt.Fprintf(w, "_g_%s(%s);\n", fn.ImportName, fnToCArgs(fn, false, true))
387+
fmt.Fprintf(w, "}\n\n")
388388
return
389389
}
390-
fmt.Fprintf(w, "%s %s(%s) {\n", fn.Ret.Type, fnCErrWrapperName(fn), fnCErrWrapperParams(fn, true))
390+
391+
fmt.Fprintf(w, "%s %s(%s) {\n", fn.Ret.Type, fnCName(fn), fnCErrWrapperParams(fn, true))
391392
fmt.Fprintf(w, "\tmkcgo_err_clear();\n") // clear any previous error
392393
fmt.Fprintf(w, "\t%s _ret = _g_%s(%s);\n", fn.Ret.Type, fn.ImportName, fnToCArgs(fn, false, true))
393394
errCond := "<= 0"
@@ -506,7 +507,7 @@ func cTypeToGo(t string, cgo bool) (string, bool) {
506507
// paramToC returns C source code of parameter p.
507508
func paramToC(i int, p *mkcgo.Param, addType, addName bool) string {
508509
if p.Type == "..." {
509-
return ""
510+
return "..."
510511
}
511512
var s string
512513
if addType {
@@ -585,12 +586,33 @@ func fnCErrWrapperParams(fn *mkcgo.Func, addName bool) string {
585586
return args
586587
}
587588

588-
// fnCErrWrapperName returns the name of the error wrapper function for function f.
589-
func fnCErrWrapperName(fn *mkcgo.Func) string {
590-
return "_mkcgo_err_" + fn.CName
589+
// fnGoName returns the Go function name for function f.
590+
func fnGoName(fn *mkcgo.Func) string {
591+
// TODO: use a prefix that is not OpenSSL specific.
592+
return "go_openssl_" + fn.Name
593+
}
594+
595+
func fnGoNameAvailable(fn *mkcgo.Func) string {
596+
return fnGoName(fn) + "_Available"
597+
}
598+
599+
// fnCName returns the C function name for function f.
600+
func fnCName(fn *mkcgo.Func) string {
601+
return "_mkcgo_" + fn.Name
602+
}
603+
604+
// fnCNameAvailable returns the C function name for function f
605+
// that checks if the function is available.
606+
func fnCNameAvailable(fn *mkcgo.Func) string {
607+
return "_mkcgo_available_" + fn.Name
591608
}
592609

593610
// fnNeedErrWrapper reports whether function fn needs an error wrapper.
594611
func fnNeedErrWrapper(fn *mkcgo.Func) bool {
595612
return !fn.NoError && !retIsVoid(fn.Ret)
596613
}
614+
615+
// fnCalledFromGo reports whether function fn is called from Go code.
616+
func fnCalledFromGo(fn *mkcgo.Func) bool {
617+
return !fn.Variadic() // cgo doesn't support variadic functions
618+
}

errors.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package openssl
55
/*
66
#include <stdlib.h> // for calloc and free
77
#include <string.h> // for strdup
8-
#include "shims.h"
98
#include "zossl.h"
109
1110
// OpenSSL only allows a maximum of 16 errors to be stored in the error queue.
@@ -22,7 +21,7 @@ typedef struct ossl_err_state_st {
2221
// mkcgo_err_clear clears the error queue in OpenSSL.
2322
void mkcgo_err_clear() {
2423
// Clear the error queue.
25-
ERR_clear_error();
24+
_mkcgo_ERR_clear_error();
2625
}
2726
2827
// mkcgo_err_retrieve retrieves the error state from OpenSSL.
@@ -37,12 +36,12 @@ mkcgo_err_state mkcgo_err_retrieve() {
3736
// Retrieve the errors from OpenSSL.
3837
for (int i = 0; i < ERR_NUM_MAX; i++) {
3938
const char *file;
40-
if (OPENSSL_version_major_Available() == 1) { // Only available in OpenSSL 3.
39+
if (_mkcgo_available_OPENSSL_version_major() == 1) { // Only available in OpenSSL 3.
4140
// OpenSSL 3 error handling
42-
errs->code[i] = ERR_get_error_all(&file, &errs->line[i], NULL, NULL, NULL);
41+
errs->code[i] = _mkcgo_ERR_get_error_all(&file, &errs->line[i], NULL, NULL, NULL);
4342
} else {
4443
// OpenSSL 1 error handling
45-
errs->code[i] = ERR_get_error_line(&file, &errs->line[i]);
44+
errs->code[i] = _mkcgo_ERR_get_error_line(&file, &errs->line[i]);
4645
}
4746
if (errs->code[i] == 0) {
4847
break;

hash.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
package openssl
44

55
/*
6-
#include "shims.h"
76
#include "zossl.h"
87
// go_hash_sum copies ctx into ctx2 and calls EVP_DigestFinal_ex using ctx2.
98
// This is necessary because Go hash.Hash mandates that Sum has no effect
@@ -14,9 +13,9 @@ package openssl
1413
static inline int
1514
go_hash_sum(const _EVP_MD_CTX_PTR ctx, _EVP_MD_CTX_PTR ctx2, unsigned char *out, mkcgo_err_state *_err_state)
1615
{
17-
if (_mkcgo_err_EVP_MD_CTX_copy(ctx2, ctx, _err_state) != 1)
16+
if (_mkcgo_EVP_MD_CTX_copy(ctx2, ctx, _err_state) != 1)
1817
return -1;
19-
if (_mkcgo_err_EVP_DigestFinal_ex(ctx2, out, NULL, _err_state) <= 0)
18+
if (_mkcgo_EVP_DigestFinal_ex(ctx2, out, NULL, _err_state) <= 0)
2019
return -2;
2120
return 1;
2221
}

internal/mkcgo/mkcgo.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type Source struct {
1111
Funcs []*Func
1212
Files []string
1313
Comments []string // All line comments. Directives in this slice start with "#"
14+
Includes []string // All #include directives, without the #include prefix.
1415
}
1516

1617
// TypeDef describes a type definition.
@@ -28,8 +29,7 @@ type Enum struct {
2829
// Func describes a function.
2930
type Func struct {
3031
FuncAttributes
31-
GoName string
32-
CName string
32+
Name string
3333
Params []*Param
3434
Ret *Return
3535
}

0 commit comments

Comments
 (0)