koffi 2.6.11 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2023 Niels Martignène <niels.martignene@protonmail.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ # this software and associated documentation files (the “Software”), to deal in
7
+ # the Software without restriction, including without limitation the rights to use,
8
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
9
+ # Software, and to permit persons to whom the Software is furnished to do so,
10
+ # subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ # This script uses the database of mimetypes distributed here: https://github.com/jshttp/mime-db
25
+ # to produce the X-header file mimetypes.inc
26
+
27
+ import os
28
+ import argparse
29
+ import json
30
+
31
+ if __name__ == "__main__":
32
+ parser = argparse.ArgumentParser(description = 'Update mimetypes include file')
33
+ parser.add_argument('-O', '--output_file', dest = 'output_file', action = 'store', help = 'Output file')
34
+ parser.add_argument('json', help = 'Source JSON database')
35
+ args = parser.parse_args()
36
+
37
+ if args.output_file is None:
38
+ output_file = os.path.join(os.path.dirname(__file__), 'mimetypes.inc')
39
+ else:
40
+ output_file = args.output_file
41
+
42
+ with open(args.json) as f:
43
+ db = json.load(f)
44
+
45
+ extensions = {}
46
+ for (k, v) in db.items():
47
+ if 'extensions' not in v:
48
+ continue
49
+
50
+ for ext in v['extensions']:
51
+ if not ext in extensions:
52
+ extensions[ext] = 'application/x-'
53
+ if extensions[ext].startswith('application/x-'):
54
+ extensions[ext] = k
55
+
56
+ extensions = [(k, extensions[k]) for k in sorted(extensions.keys())]
57
+ extensions.sort()
58
+
59
+ with open(output_file) as f:
60
+ lines = f.readlines()
61
+ with open(output_file, 'w') as f:
62
+ for line in lines:
63
+ if not line.startswith('//'):
64
+ break
65
+ f.write(line)
66
+
67
+ print('', file = f)
68
+ print('#ifndef MIMETYPE', file = f)
69
+ print(' #error Please define MIMETYPE() before including mimetypes.inc', file = f)
70
+ print('#endif', file = f)
71
+ print('', file = f)
72
+
73
+ for k, v in extensions:
74
+ print(f'MIMETYPE(".{k}", "{v}")', file = f)
75
+
76
+ print('', file = f)
77
+ print('#undef MIMETYPE', file = f)
@@ -880,35 +880,50 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
880
880
  return WrapType(env, instance, type);
881
881
  }
882
882
 
883
- static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value ret,
884
- Napi::Array parameters, FunctionInfo *func)
883
+ static bool ParseClassicFunction(const Napi::CallbackInfo &info, FunctionInfo *out_func)
885
884
  {
885
+ Napi::Env env = info.Env();
886
886
  InstanceData *instance = env.GetInstanceData<InstanceData>();
887
887
 
888
+ Napi::String name = info[0u].As<Napi::String>();
889
+ Napi::Value ret = info[1u];
890
+ Napi::Array parameters = info[2u].As<Napi::Array>();
891
+
892
+ // Detect optional call convention
893
+ if (name.IsString() && DetectCallConvention(name.Utf8Value().c_str(), &out_func->convention)) {
894
+ if (info.Length() < 4) {
895
+ ThrowError<Napi::TypeError>(env, "Expected 4 arguments, got %1", info.Length());
896
+ return false;
897
+ }
898
+
899
+ name = info[1u].As<Napi::String>();
900
+ ret = info[2u];
901
+ parameters = info[3u].As<Napi::Array>();
902
+ }
903
+
888
904
  #ifdef _WIN32
889
- if (!name.IsString() && !name.IsNumber()) {
890
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string or integer", GetValueType(instance, name));
891
- return false;
905
+ if (name.IsNumber()) {
906
+ out_func->ordinal_name = name.As<Napi::Number>().Int32Value();
907
+ name = name.ToString();
892
908
  }
893
- #else
909
+ #endif
894
910
  if (!name.IsString()) {
895
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, name));
911
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string or integer", GetValueType(instance, name));
896
912
  return false;
897
913
  }
898
- #endif
899
914
 
900
- func->name = DuplicateString(name.ToString().Utf8Value().c_str(), &instance->str_alloc).ptr;
915
+ out_func->name = DuplicateString(name.ToString().Utf8Value().c_str(), &instance->str_alloc).ptr;
901
916
 
902
- func->ret.type = ResolveType(ret);
903
- if (!func->ret.type)
917
+ out_func->ret.type = ResolveType(ret);
918
+ if (!out_func->ret.type)
904
919
  return false;
905
- if (!CanReturnType(func->ret.type)) {
906
- ThrowError<Napi::TypeError>(env, "You are not allowed to directly return %1 values (maybe try %1 *)", func->ret.type->name);
920
+ if (!CanReturnType(out_func->ret.type)) {
921
+ ThrowError<Napi::TypeError>(env, "You are not allowed to directly return %1 values (maybe try %1 *)", out_func->ret.type->name);
907
922
  return false;
908
923
  }
909
924
 
910
925
  if (!parameters.IsArray()) {
911
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for parameters of '%2', expected an array", GetValueType(instance, parameters), func->name);
926
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for parameters of '%2', expected an array", GetValueType(instance, parameters), out_func->name);
912
927
  return false;
913
928
  }
914
929
 
@@ -918,7 +933,7 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
918
933
  Napi::String str = parameters.Get(parameters_len - 1).As<Napi::String>();
919
934
 
920
935
  if (str.IsString() && str.Utf8Value() == "...") {
921
- func->variadic = true;
936
+ out_func->variadic = true;
922
937
  parameters_len--;
923
938
  }
924
939
  }
@@ -934,21 +949,21 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
934
949
  ThrowError<Napi::TypeError>(env, "Type %1 cannot be used as a parameter", param.type->name);
935
950
  return false;
936
951
  }
937
- if (func->parameters.len >= MaxParameters) {
952
+ if (out_func->parameters.len >= MaxParameters) {
938
953
  ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 parameters", MaxParameters);
939
954
  return false;
940
955
  }
941
- if ((param.directions & 2) && ++func->out_parameters >= MaxParameters) {
956
+ if ((param.directions & 2) && ++out_func->out_parameters >= MaxParameters) {
942
957
  ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 output parameters", MaxParameters);
943
958
  return false;
944
959
  }
945
960
 
946
961
  param.offset = (int8_t)j;
947
962
 
948
- func->parameters.Append(param);
963
+ out_func->parameters.Append(param);
949
964
  }
950
965
 
951
- func->required_parameters = (int8_t)func->parameters.len;
966
+ out_func->required_parameters = (int8_t)out_func->parameters.len;
952
967
 
953
968
  return true;
954
969
  }
@@ -962,7 +977,7 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
962
977
  RG_DEFER_N(err_guard) { instance->callbacks.RemoveLast(1); };
963
978
 
964
979
  if (info.Length() >= 3) {
965
- if (!ParseClassicFunction(env, info[0u].As<Napi::String>(), info[1u], info[2u].As<Napi::Array>(), func))
980
+ if (!ParseClassicFunction(info, func))
966
981
  return env.Null();
967
982
  } else if (info.Length() >= 1) {
968
983
  if (!info[0].IsString()) {
@@ -1519,7 +1534,7 @@ extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, Bac
1519
1534
  }
1520
1535
  }
1521
1536
 
1522
- static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConvention convention)
1537
+ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info)
1523
1538
  {
1524
1539
  Napi::Env env = info.Env();
1525
1540
  InstanceData *instance = env.GetInstanceData<InstanceData>();
@@ -1529,10 +1544,9 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
1529
1544
  RG_DEFER { func->Unref(); };
1530
1545
 
1531
1546
  func->lib = lib->Ref();
1532
- func->convention = convention;
1533
1547
 
1534
1548
  if (info.Length() >= 3) {
1535
- if (!ParseClassicFunction(env, info[0u].As<Napi::String>(), info[1u], info[2u].As<Napi::Array>(), func))
1549
+ if (!ParseClassicFunction(info, func))
1536
1550
  return env.Null();
1537
1551
  } else if (info.Length() >= 1) {
1538
1552
  if (!info[0].IsString()) {
@@ -1562,7 +1576,7 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
1562
1576
  }
1563
1577
 
1564
1578
  #ifdef _WIN32
1565
- if (info[0].IsString()) {
1579
+ if (func->ordinal_name < 0) {
1566
1580
  if (func->decorated_name) {
1567
1581
  func->native = (void *)GetProcAddress((HMODULE)lib->module, func->decorated_name);
1568
1582
  }
@@ -1570,7 +1584,7 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
1570
1584
  func->native = (void *)GetProcAddress((HMODULE)lib->module, func->name);
1571
1585
  }
1572
1586
  } else {
1573
- uint16_t ordinal = (uint16_t)info[0].As<Napi::Number>().Uint32Value();
1587
+ uint16_t ordinal = (uint16_t)func->ordinal_name;
1574
1588
 
1575
1589
  func->decorated_name = nullptr;
1576
1590
  func->native = (void *)GetProcAddress((HMODULE)lib->module, (LPCSTR)(size_t)ordinal);
@@ -1720,20 +1734,13 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
1720
1734
  func.AddFinalizer([](Napi::Env, LibraryHolder *lib) { lib->Unref(); }, lib); \
1721
1735
  obj.Set((Name), func); \
1722
1736
  } while (false)
1723
- #define ADD_CONVENTION(Name, Value) ADD_METHOD((Name), FindLibraryFunction(info, Value))
1724
-
1725
- ADD_CONVENTION("func", CallConvention::Cdecl);
1726
- ADD_CONVENTION("cdecl", CallConvention::Cdecl);
1727
- ADD_CONVENTION("stdcall", CallConvention::Stdcall);
1728
- ADD_CONVENTION("fastcall", CallConvention::Fastcall);
1729
- ADD_CONVENTION("thiscall", CallConvention::Thiscall);
1730
1737
 
1738
+ ADD_METHOD("func", FindLibraryFunction(info));
1731
1739
  ADD_METHOD("symbol", FindSymbol(info));
1732
1740
 
1733
1741
  // We can't unref the library after unload, obviously
1734
1742
  obj.Set("unload", Napi::Function::New(env, UnloadLibrary, "unload", (void *)lib->Ref()));
1735
1743
 
1736
- #undef ADD_CONVENTION
1737
1744
  #undef ADD_METHOD
1738
1745
 
1739
1746
  return obj;
@@ -2326,7 +2333,6 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2326
2333
  Napi::Object types = InitBaseTypes(env);
2327
2334
  exports.Set("types", types);
2328
2335
 
2329
- exports.Set("internal", Napi::Boolean::New(env, false));
2330
2336
  exports.Set("version", Napi::String::New(env, RG_STRINGIFY(VERSION)));
2331
2337
 
2332
2338
  return exports;
@@ -220,6 +220,9 @@ struct FunctionInfo {
220
220
 
221
221
  const char *name;
222
222
  const char *decorated_name; // Only set for some platforms/calling conventions
223
+ #ifdef _WIN32
224
+ int ordinal_name = -1;
225
+ #endif
223
226
  const LibraryHolder *lib = nullptr;
224
227
 
225
228
  void *native;
@@ -40,15 +40,7 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
40
40
  MarkError("You are not allowed to directly return %1 values (maybe try %1 *)", out_func->ret.type->name);
41
41
  return false;
42
42
  }
43
- if (Match("__cdecl")) {
44
- out_func->convention = CallConvention::Cdecl;
45
- } else if (Match("__stdcall")) {
46
- out_func->convention = CallConvention::Stdcall;
47
- } else if (Match("__fastcall")) {
48
- out_func->convention = CallConvention::Fastcall;
49
- } else if (Match("__thiscall")) {
50
- out_func->convention = CallConvention::Thiscall;
51
- }
43
+ offset += (offset < tokens.len && DetectCallConvention(tokens[offset], &out_func->convention));
52
44
  out_func->name = ParseIdentifier();
53
45
 
54
46
  Consume("(");
@@ -139,6 +139,8 @@ const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
139
139
  bucket->key = DuplicateString(str.c_str(), &instance->str_alloc).ptr;
140
140
  bucket->value = type;
141
141
  }
142
+ } else if (out_directions) {
143
+ *out_directions = 1;
142
144
  }
143
145
 
144
146
  return type;
@@ -1506,6 +1508,25 @@ Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
1506
1508
  return wrapper;
1507
1509
  }
1508
1510
 
1511
+ bool DetectCallConvention(Span<const char> name, CallConvention *out_convention)
1512
+ {
1513
+ if (name == "__cdecl") {
1514
+ *out_convention = CallConvention::Cdecl;
1515
+ return true;
1516
+ } else if (name == "__stdcall") {
1517
+ *out_convention = CallConvention::Stdcall;
1518
+ return true;
1519
+ } else if (name == "__fastcall") {
1520
+ *out_convention = CallConvention::Fastcall;
1521
+ return true;
1522
+ } else if (name == "__thiscall") {
1523
+ *out_convention = CallConvention::Thiscall;
1524
+ return true;
1525
+ } else {
1526
+ return false;
1527
+ }
1528
+ }
1529
+
1509
1530
  static int AnalyseFlatRec(const TypeInfo *type, int offset, int count, FunctionRef<void(const TypeInfo *type, int offset, int count)> func)
1510
1531
  {
1511
1532
  if (type->primitive == PrimitiveKind::Record) {
@@ -208,6 +208,8 @@ static inline Napi::Array GetOwnPropertyNames(Napi::Object obj)
208
208
 
209
209
  Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func);
210
210
 
211
+ bool DetectCallConvention(Span<const char> name, CallConvention *out_convention);
212
+
211
213
  int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
212
214
 
213
215
  void DumpMemory(const char *type, Span<const uint8_t> bytes);
Binary file