@microtronics/studio-cli 0.61.0 → 0.62.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.
- package/CHANGELOG.md +9 -3
- package/README.md +17 -0
- package/dist/main.js +54 -57
- package/dist/studio-cli.d.ts +1 -0
- package/out/api.js +137 -149
- package/out/studio-cli.d.ts +5297 -0
- package/package.json +4 -4
- package/out/DeviceProfiles.js +0 -436
- package/out/FS.js +0 -43
- package/out/crc.js +0 -93
- package/out/dde/coreDefinitions.js +0 -541
- package/out/dde/dde.js +0 -618
- package/out/dde/dynamic-dde.schema.json +0 -1061
- package/out/dde/fileGenerators/api.js +0 -688
- package/out/dde/fileGenerators/dlo.js +0 -1014
- package/out/dde/fileGenerators/dloLocalData.js +0 -387
- package/out/dde/fileGenerators/xml.js +0 -180
- package/out/dde/yamlDdePreCompiler.js +0 -889
- package/out/defaultFiles.js +0 -114
- package/out/dependencies.js +0 -578
- package/out/dfiles/dfiles.js +0 -205
- package/out/diagnostics.js +0 -10
- package/out/dlo/CustomWasmFS.js +0 -258
- package/out/dlo/compiler.js +0 -231
- package/out/dlo/dlo.js +0 -33
- package/out/dlo/dlocc.js +0 -3799
- package/out/dlo/fileSequencer.js +0 -40
- package/out/dlo/preCompiler.js +0 -442
- package/out/dotenv.js +0 -28
- package/out/globals.js +0 -402
- package/out/helper.js +0 -145
- package/out/log.js +0 -60
- package/out/manifest.js +0 -492
- package/out/myDatanetClient.js +0 -291
- package/out/package/apm.js +0 -294
- package/out/package/library.js +0 -165
- package/out/package/package.js +0 -518
- package/out/registryAPI.js +0 -326
- package/out/scriptRunner.js +0 -107
- package/out/typings/registry.js +0 -7
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateDloLocalDataIncFromMap = generateDloLocalDataIncFromMap;
|
|
4
|
-
const coreDefinitions_1 = require("../coreDefinitions");
|
|
5
|
-
var TransferDirection = coreDefinitions_1.DDE_Core.TransferDirection;
|
|
6
|
-
const dlo_1 = require("./dlo");
|
|
7
|
-
const helper_1 = require("../../helper");
|
|
8
|
-
const PAWN_SZTEMP_DECL = '\tnew szTemp{64};';
|
|
9
|
-
const PAWN_STRCAT_RETURN = '\treturn strcat(aData, szTemp, sizeof(szTemp));';
|
|
10
|
-
/**
|
|
11
|
-
* Determines if a field type can use a format helper function, and which one.
|
|
12
|
-
* Returns null if the field type needs inline code (packed types, wstring, etc.)
|
|
13
|
-
*/
|
|
14
|
-
function getHelperFormatType(tdefPwn) {
|
|
15
|
-
// Binary (memtostr) fields - check before printf since printf is null for binary
|
|
16
|
-
if (!tdefPwn.printf && tdefPwn.printfFormat === 'memtostr') {
|
|
17
|
-
return 'bin';
|
|
18
|
-
}
|
|
19
|
-
if (!tdefPwn.printf) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const rwp = tdefPwn.rwp || '%n';
|
|
23
|
-
const hasCellArray = rwp.includes('[');
|
|
24
|
-
const hasPackedArray = rwp.includes('{');
|
|
25
|
-
const isComplex = hasPackedArray || hasCellArray;
|
|
26
|
-
if (tdefPwn.printfFormat === 'stampToISOString') {
|
|
27
|
-
return isComplex ? null : 'stamp';
|
|
28
|
-
}
|
|
29
|
-
switch (tdefPwn.printf) {
|
|
30
|
-
case '%d':
|
|
31
|
-
return isComplex ? null : 'd';
|
|
32
|
-
case '%f':
|
|
33
|
-
return isComplex ? null : 'f';
|
|
34
|
-
case '%s':
|
|
35
|
-
return hasCellArray ? null : 's';
|
|
36
|
-
default:
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Gets the format type for a field, handling shadow/skip filtering.
|
|
42
|
-
* Returns null if the field should be skipped or needs inline code.
|
|
43
|
-
*/
|
|
44
|
-
function getFieldFormatType(field) {
|
|
45
|
-
if (field.type === 'shadow' || field.shadowRef) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
const tdefPwn = (0, dlo_1.getPawnTypeDefinition)(field);
|
|
49
|
-
if (!tdefPwn || tdefPwn === 'skip') {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
return getHelperFormatType(tdefPwn);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Checks if a container is device-side (hx or cx) and not backend-only.
|
|
56
|
-
*/
|
|
57
|
-
function isDeviceContainer(containerDefinition) {
|
|
58
|
-
return ([coreDefinitions_1.DDE_Core.ContainerType.hx, coreDefinitions_1.DDE_Core.ContainerType.cx].includes(containerDefinition.containerType) &&
|
|
59
|
-
containerDefinition.transferDirection !== TransferDirection.backendOnly);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Checks if a field is valid for code generation (not shadow, not skipped).
|
|
63
|
-
*/
|
|
64
|
-
function isValidField(field) {
|
|
65
|
-
if (field.type === 'shadow' || field.shadowRef) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
const tdefPwn = (0, dlo_1.getPawnTypeDefinition)(field);
|
|
69
|
-
return !!tdefPwn && tdefPwn !== 'skip';
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Adds an array field to the appropriate group in the group map.
|
|
73
|
-
*/
|
|
74
|
-
function addFieldToGroup(field, formatType, groupMap) {
|
|
75
|
-
const bracketEnd = field.name.indexOf(']');
|
|
76
|
-
const subField = bracketEnd >= 0 ? field.name.substring(bracketEnd + 1) : '';
|
|
77
|
-
const groupKey = `${field.arrayRef.name}|${subField}|${formatType}`;
|
|
78
|
-
if (!groupMap.has(groupKey)) {
|
|
79
|
-
groupMap.set(groupKey, { fields: [], formatType });
|
|
80
|
-
}
|
|
81
|
-
groupMap.get(groupKey).fields.push(field);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Classifies fields into array-groupable and standalone categories.
|
|
85
|
-
*/
|
|
86
|
-
function classifyFields(fields) {
|
|
87
|
-
const standaloneFields = [];
|
|
88
|
-
const groupMap = new Map();
|
|
89
|
-
const usedFormats = new Set();
|
|
90
|
-
let hasInlineFields = false;
|
|
91
|
-
for (const field of fields) {
|
|
92
|
-
if (!isValidField(field)) {
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
const formatType = getFieldFormatType(field);
|
|
96
|
-
if (field.arrayRef && formatType) {
|
|
97
|
-
addFieldToGroup(field, formatType, groupMap);
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
standaloneFields.push(field);
|
|
101
|
-
if (formatType) {
|
|
102
|
-
usedFormats.add(formatType);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
hasInlineFields = true;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return { standaloneFields, groupMap, usedFormats, hasInlineFields };
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Converts a group map entry into an ArrayFieldGroup if it has consistent stepping.
|
|
113
|
-
* Returns null if the group should be treated as standalone fields.
|
|
114
|
-
*/
|
|
115
|
-
function tryBuildArrayGroup(containerTitle, groupKey, groupFields) {
|
|
116
|
-
groupFields.sort((a, b) => a.arrayRef.index - b.arrayRef.index);
|
|
117
|
-
const offsets = groupFields.map(f => f.byteOffset);
|
|
118
|
-
const step = offsets[1] - offsets[0];
|
|
119
|
-
const isConsistent = step > 0 && offsets.every((o, i) => i === 0 || o - offsets[i - 1] === step);
|
|
120
|
-
if (!isConsistent) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
const [arrayName, subField] = groupKey.split('|');
|
|
124
|
-
const fieldNamePrefix = groupFields[0].library
|
|
125
|
-
? `_${helper_1.Helper.generateHashForLibraryName(groupFields[0].library)}`
|
|
126
|
-
: 'DDE_';
|
|
127
|
-
return {
|
|
128
|
-
arrayName,
|
|
129
|
-
subField,
|
|
130
|
-
fields: groupFields,
|
|
131
|
-
startOffset: offsets[0],
|
|
132
|
-
endOffset: offsets[offsets.length - 1],
|
|
133
|
-
step,
|
|
134
|
-
formatType: getFieldFormatType(groupFields[0]),
|
|
135
|
-
pawnVarBase: `${fieldNamePrefix}${containerTitle}_${arrayName}`
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Analyzes container fields and groups array elements that can be collapsed
|
|
140
|
-
* into arithmetic if-blocks for reduced AMX binary size.
|
|
141
|
-
*/
|
|
142
|
-
function analyzeContainerFields(containerTitle, fields) {
|
|
143
|
-
const { standaloneFields, groupMap, usedFormats, hasInlineFields } = classifyFields(fields);
|
|
144
|
-
const arrayGroups = [];
|
|
145
|
-
for (const [groupKey, groupData] of groupMap) {
|
|
146
|
-
const { fields: groupFields, formatType } = groupData;
|
|
147
|
-
if (groupFields.length < 2) {
|
|
148
|
-
standaloneFields.push(...groupFields);
|
|
149
|
-
usedFormats.add(formatType);
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
const group = tryBuildArrayGroup(containerTitle, groupKey, groupFields);
|
|
153
|
-
if (group) {
|
|
154
|
-
usedFormats.add(formatType);
|
|
155
|
-
arrayGroups.push(group);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
standaloneFields.push(...groupFields);
|
|
159
|
-
usedFormats.add(formatType);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
standaloneFields.sort((a, b) => a.byteOffset - b.byteOffset);
|
|
163
|
-
return { arrayGroups, standaloneFields, usedFormats, hasInlineFields };
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Scans all eligible container fields to determine which helper format types are needed.
|
|
167
|
-
*/
|
|
168
|
-
function collectUsedFormats(ddeMap) {
|
|
169
|
-
const usedFormats = new Set();
|
|
170
|
-
for (const [, containerDefinition] of Object.entries(ddeMap.containers)) {
|
|
171
|
-
if (!isDeviceContainer(containerDefinition)) {
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
for (const field of containerDefinition.fields) {
|
|
175
|
-
const formatType = getFieldFormatType(field);
|
|
176
|
-
if (formatType) {
|
|
177
|
-
usedFormats.add(formatType);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return usedFormats;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Generates Pawn helper functions that encapsulate the sprintf+strcat pattern.
|
|
185
|
-
* Only generates the helpers that are actually used, reducing dead code.
|
|
186
|
-
* Each helper replaces 3 lines of repeated code per field with a single call.
|
|
187
|
-
*/
|
|
188
|
-
function buildHelperFunctions(pawnSource, usedFormats) {
|
|
189
|
-
if (usedFormats.has('d')) {
|
|
190
|
-
pawnSource('stock _DDE_fmt_d(aData{}, value) {');
|
|
191
|
-
pawnSource(PAWN_SZTEMP_DECL);
|
|
192
|
-
pawnSource('\tsprintf(szTemp, _, "%d", value);');
|
|
193
|
-
pawnSource(PAWN_STRCAT_RETURN);
|
|
194
|
-
pawnSource('}');
|
|
195
|
-
}
|
|
196
|
-
if (usedFormats.has('f')) {
|
|
197
|
-
pawnSource('');
|
|
198
|
-
pawnSource('stock _DDE_fmt_f(aData{}, Float:value) {');
|
|
199
|
-
pawnSource(PAWN_SZTEMP_DECL);
|
|
200
|
-
pawnSource('\tsprintf(szTemp, _, "%.3f", value);');
|
|
201
|
-
pawnSource(PAWN_STRCAT_RETURN);
|
|
202
|
-
pawnSource('}');
|
|
203
|
-
}
|
|
204
|
-
if (usedFormats.has('s')) {
|
|
205
|
-
pawnSource('');
|
|
206
|
-
pawnSource('stock _DDE_fmt_s(aData{}, value{}) {');
|
|
207
|
-
pawnSource(PAWN_SZTEMP_DECL);
|
|
208
|
-
pawnSource('\tsprintf(szTemp, _, "%s", value);');
|
|
209
|
-
pawnSource(PAWN_STRCAT_RETURN);
|
|
210
|
-
pawnSource('}');
|
|
211
|
-
}
|
|
212
|
-
if (usedFormats.has('stamp')) {
|
|
213
|
-
pawnSource('');
|
|
214
|
-
pawnSource('stock _DDE_fmt_stamp(aData{}, value) {');
|
|
215
|
-
pawnSource(PAWN_SZTEMP_DECL);
|
|
216
|
-
pawnSource('\tsprintf(szTemp, _, "%s", (stampToISOString(value)));');
|
|
217
|
-
pawnSource(PAWN_STRCAT_RETURN);
|
|
218
|
-
pawnSource('}');
|
|
219
|
-
}
|
|
220
|
-
if (usedFormats.has('bin')) {
|
|
221
|
-
pawnSource('');
|
|
222
|
-
pawnSource('stock _DDE_fmt_bin(aData{}, mem{}, dim) {');
|
|
223
|
-
pawnSource('\t#pragma warning disable 224');
|
|
224
|
-
pawnSource('\tmemtostr(aData, mem, 0, dim);');
|
|
225
|
-
pawnSource('\t#pragma warning disable 224');
|
|
226
|
-
pawnSource('\treturn dim;');
|
|
227
|
-
pawnSource('}');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Builds the Pawn index expression for accessing an array element by byte offset.
|
|
232
|
-
*/
|
|
233
|
-
function buildIndexExpression(startOffset, step) {
|
|
234
|
-
if (step === 1) {
|
|
235
|
-
return startOffset === 0 ? 'idx' : `idx - ${startOffset}`;
|
|
236
|
-
}
|
|
237
|
-
return startOffset === 0 ? `idx / ${step}` : `(idx - ${startOffset}) / ${step}`;
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Builds the Pawn condition for matching a byte offset to an array group.
|
|
241
|
-
*/
|
|
242
|
-
function buildConditionExpression(startOffset, endOffset, step) {
|
|
243
|
-
const rangeCheck = `idx >= ${startOffset} && idx <= ${endOffset}`;
|
|
244
|
-
if (step === 1) {
|
|
245
|
-
return rangeCheck;
|
|
246
|
-
}
|
|
247
|
-
const modCheck = startOffset === 0 ? `idx % ${step} == 0` : `(idx - ${startOffset}) % ${step} == 0`;
|
|
248
|
-
return `${rangeCheck} && ${modCheck}`;
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Generates an if-block that collapses an array group into arithmetic index calculation.
|
|
252
|
-
*/
|
|
253
|
-
function buildArrayGroupBlock(pawnSource, group) {
|
|
254
|
-
const { startOffset, endOffset, step, formatType, pawnVarBase, subField } = group;
|
|
255
|
-
const indexExpr = buildIndexExpression(startOffset, step);
|
|
256
|
-
const condition = buildConditionExpression(startOffset, endOffset, step);
|
|
257
|
-
pawnSource(`\tif (${condition}) {`);
|
|
258
|
-
if (formatType === 'bin') {
|
|
259
|
-
const fieldAccess = `${pawnVarBase}[${indexExpr}]${subField}`;
|
|
260
|
-
const subFieldName = subField ? subField.substring(1) : '';
|
|
261
|
-
const dimDefine = subFieldName ? `${pawnVarBase}_${subFieldName}_dim` : `${pawnVarBase}_dim`;
|
|
262
|
-
pawnSource(`\t\treturn _DDE_fmt_bin(aData, ${fieldAccess}, ${dimDefine});`);
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
pawnSource(`\t\treturn _DDE_fmt_${formatType}(aData, ${pawnVarBase}[${indexExpr}]${subField});`);
|
|
266
|
-
}
|
|
267
|
-
pawnSource(`\t}`);
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Builds a case statement for a standalone field.
|
|
271
|
-
* Uses compact helper function calls when available, falls back to inline code
|
|
272
|
-
* for packed types (s64, f64, stamp40) and memtostr (binary).
|
|
273
|
-
*/
|
|
274
|
-
function buildOptimizedCaseForField(pawnSource, containerTitle, field) {
|
|
275
|
-
if (field.type === 'shadow' || field.shadowRef) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
const tdefPwn = (0, dlo_1.getPawnTypeDefinition)(field);
|
|
279
|
-
if (!tdefPwn || tdefPwn === 'skip') {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
const fieldNamePrefix = field.library ? `_${helper_1.Helper.generateHashForLibraryName(field.library)}` : 'DDE_';
|
|
283
|
-
const ddeFieldName = `${fieldNamePrefix}${containerTitle}_${field.name}`;
|
|
284
|
-
const formatType = getHelperFormatType(tdefPwn);
|
|
285
|
-
if (formatType === 'bin') {
|
|
286
|
-
// Compact single-line case using binary helper function
|
|
287
|
-
pawnSource(`\t\tcase ${field.byteOffset}: return _DDE_fmt_bin(aData, ${ddeFieldName}, ${ddeFieldName}_dim);`);
|
|
288
|
-
}
|
|
289
|
-
else if (formatType) {
|
|
290
|
-
// Compact single-line case using helper function
|
|
291
|
-
pawnSource(`\t\tcase ${field.byteOffset}: return _DDE_fmt_${formatType}(aData, ${ddeFieldName});`);
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
// Fall back to inline code (packed types, wstring, etc.)
|
|
295
|
-
pawnSource(`\t\tcase ${field.byteOffset}: {`);
|
|
296
|
-
if (tdefPwn.printf) {
|
|
297
|
-
let printfInsert = ddeFieldName;
|
|
298
|
-
if (tdefPwn.printfFormat) {
|
|
299
|
-
printfInsert = `(${tdefPwn.printfFormat}(${printfInsert}))`;
|
|
300
|
-
}
|
|
301
|
-
pawnSource(`\t\t\tsprintf(szTemp, _, "${tdefPwn.printf}", ${printfInsert});`);
|
|
302
|
-
pawnSource(`\t\t\treturn (strcat(aData, szTemp, sizeof(szTemp)));`);
|
|
303
|
-
}
|
|
304
|
-
pawnSource(`\t\t}`);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
function buildCaseForContainerName(pawnSource, containerName, containerDefinition) {
|
|
308
|
-
pawnSource(`\t\t\tcase '${containerName.at(-1)}': {`);
|
|
309
|
-
pawnSource(`\t\t\t\treturn _DDE_local_${containerDefinition.title}(aData, idx);`);
|
|
310
|
-
pawnSource(`\t\t\t}`);
|
|
311
|
-
}
|
|
312
|
-
function buildIfWithSwitchForContainerType(pawnSource, ddeMap, type) {
|
|
313
|
-
const cname0 = type === coreDefinitions_1.DDE_Core.ContainerType.cx ? 'c' : 'h';
|
|
314
|
-
const nameFilter = type === coreDefinitions_1.DDE_Core.ContainerType.cx ? 'config' : 'histdata';
|
|
315
|
-
pawnSource(`\tif(cname{0} == '${cname0}'){`);
|
|
316
|
-
pawnSource(`\t\tswitch(cname{1}) {`);
|
|
317
|
-
for (const [containerName, containerDefinition] of Object.entries(ddeMap.containers)) {
|
|
318
|
-
if (type === containerDefinition.containerType &&
|
|
319
|
-
containerName.startsWith(nameFilter) &&
|
|
320
|
-
containerDefinition.transferDirection !== TransferDirection.backendOnly) {
|
|
321
|
-
buildCaseForContainerName(pawnSource, containerName, containerDefinition);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
pawnSource(`\t\t\tdefault:`);
|
|
325
|
-
pawnSource(`\t\t\t\treturn OK;`);
|
|
326
|
-
pawnSource(`\t\t}`);
|
|
327
|
-
pawnSource(`\t\treturn OK;`);
|
|
328
|
-
pawnSource(`\t}`);
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Generates an optimized per-container local data return function.
|
|
332
|
-
* Uses if-blocks for collapsed array groups and a switch for standalone fields.
|
|
333
|
-
* Only declares szTemp when inline (non-helper) fields are present.
|
|
334
|
-
*/
|
|
335
|
-
function buildOptimizedLocalDataReturnFunction(pawnSource, containerDefinition) {
|
|
336
|
-
const analysis = analyzeContainerFields(containerDefinition.title, containerDefinition.fields);
|
|
337
|
-
pawnSource('');
|
|
338
|
-
pawnSource(`stock _DDE_local_${containerDefinition.title}(aData{}, idx) {`);
|
|
339
|
-
// Declare szTemp only if there are inline fields that need it
|
|
340
|
-
if (analysis.hasInlineFields) {
|
|
341
|
-
pawnSource(`\tnew szTemp{64};`);
|
|
342
|
-
}
|
|
343
|
-
// Generate if-blocks for array groups (before the switch)
|
|
344
|
-
for (const group of analysis.arrayGroups) {
|
|
345
|
-
buildArrayGroupBlock(pawnSource, group);
|
|
346
|
-
}
|
|
347
|
-
// Generate switch for standalone fields
|
|
348
|
-
if (analysis.standaloneFields.length > 0) {
|
|
349
|
-
pawnSource(`\tswitch(idx) {`);
|
|
350
|
-
for (const field of analysis.standaloneFields) {
|
|
351
|
-
buildOptimizedCaseForField(pawnSource, containerDefinition.title, field);
|
|
352
|
-
}
|
|
353
|
-
pawnSource(`\t\tdefault:`);
|
|
354
|
-
pawnSource(`\t\t\treturn OK;`);
|
|
355
|
-
pawnSource(`\t}`);
|
|
356
|
-
}
|
|
357
|
-
pawnSource(`\treturn OK;`);
|
|
358
|
-
pawnSource(`}`);
|
|
359
|
-
}
|
|
360
|
-
function buildOptimizedLocalDataReturnFunctions(pawnSource, ddeMap) {
|
|
361
|
-
for (const [, containerDefinition] of Object.entries(ddeMap.containers)) {
|
|
362
|
-
if (!isDeviceContainer(containerDefinition)) {
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
buildOptimizedLocalDataReturnFunction(pawnSource, containerDefinition);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
function generateDloLocalDataIncFromMap(ddeMap) {
|
|
369
|
-
const _pwn = [];
|
|
370
|
-
const pwn = _pwn.push.bind(_pwn);
|
|
371
|
-
// Generate helper functions based on which format types are actually used
|
|
372
|
-
const usedFormats = collectUsedFormats(ddeMap);
|
|
373
|
-
buildHelperFunctions(pwn, usedFormats);
|
|
374
|
-
// Generate main dispatch function
|
|
375
|
-
if (usedFormats.size > 0) {
|
|
376
|
-
pwn('');
|
|
377
|
-
}
|
|
378
|
-
pwn(`stock DDE_get_local_data(cname{}, aData{}, idx) {`);
|
|
379
|
-
buildIfWithSwitchForContainerType(pwn, ddeMap, coreDefinitions_1.DDE_Core.ContainerType.cx);
|
|
380
|
-
buildIfWithSwitchForContainerType(pwn, ddeMap, coreDefinitions_1.DDE_Core.ContainerType.hx);
|
|
381
|
-
pwn(`\treturn OK;`);
|
|
382
|
-
pwn(`}`);
|
|
383
|
-
// Generate optimized per-container functions
|
|
384
|
-
buildOptimizedLocalDataReturnFunctions(pwn, ddeMap);
|
|
385
|
-
return _pwn.join('\n');
|
|
386
|
-
}
|
|
387
|
-
//# sourceMappingURL=dloLocalData.js.map
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateXMLFromMap = generateXMLFromMap;
|
|
4
|
-
const coreDefinitions_1 = require("../coreDefinitions");
|
|
5
|
-
var TransferDirection = coreDefinitions_1.DDE_Core.TransferDirection;
|
|
6
|
-
var parseXMLValueWithRelation = coreDefinitions_1.DDE_Core.parseXMLValueWithRelation;
|
|
7
|
-
var parseXMLBitmask = coreDefinitions_1.DDE_Core.parseXMLBitmask;
|
|
8
|
-
var parseXMLDefaultValue = coreDefinitions_1.DDE_Core.parseXMLDefaultValue;
|
|
9
|
-
var fieldTypeDefinitions = coreDefinitions_1.DDE_Core.fieldTypeDefinitions;
|
|
10
|
-
const helper_1 = require("../../helper");
|
|
11
|
-
const manifest_1 = require("../../manifest");
|
|
12
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
13
|
-
function generateXMLFromMap(manifest, ddeMap) {
|
|
14
|
-
const indent = '';
|
|
15
|
-
const xml_ = [];
|
|
16
|
-
function xml(s, condition = true) {
|
|
17
|
-
if (!condition) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
if (Array.isArray(s)) {
|
|
21
|
-
xml_.push.apply(xml_, s);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
xml_.push(indent + s);
|
|
25
|
-
}
|
|
26
|
-
function xmlAttr(attribute, val) {
|
|
27
|
-
if (attribute === 'mergeofs') {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
xml(`${attribute}=${val}`);
|
|
31
|
-
}
|
|
32
|
-
xml('// DDE STRUCTURE created by Microtronics Studio');
|
|
33
|
-
const rm2mraw = 'source=rm2mraw';
|
|
34
|
-
for (const [containerName, containerDefinition] of Object.entries(ddeMap.containers)) {
|
|
35
|
-
if (containerName.startsWith('histdata') &&
|
|
36
|
-
containerDefinition.transferDirection !== TransferDirection.deviceOnly) {
|
|
37
|
-
xml('<split>');
|
|
38
|
-
xml(rm2mraw);
|
|
39
|
-
xml('target=' + containerName);
|
|
40
|
-
xml('key=0' + containerName.substr(-1, 1));
|
|
41
|
-
xml('</split>');
|
|
42
|
-
}
|
|
43
|
-
xml('<table>');
|
|
44
|
-
xmlAttr('name', containerName); // output container-name as very first line (mandatory!)
|
|
45
|
-
xmlAttr('alias', containerDefinition.title);
|
|
46
|
-
xmlAttr('title', containerDefinition.title.replace('_', ' '));
|
|
47
|
-
const containerAttributes = {};
|
|
48
|
-
// enforce container's direction - 'up','up+','down','down+','both','both+'
|
|
49
|
-
// .upload/.download are reserved container attributes (already claimed during parsing)
|
|
50
|
-
if ([
|
|
51
|
-
TransferDirection.none,
|
|
52
|
-
TransferDirection.backendOnly,
|
|
53
|
-
TransferDirection.deviceOnly,
|
|
54
|
-
TransferDirection.down,
|
|
55
|
-
TransferDirection.downPlus
|
|
56
|
-
].includes(containerDefinition.transferDirection)) {
|
|
57
|
-
// containerAttributes['upload'] = '0';
|
|
58
|
-
xmlAttr('upload', '0');
|
|
59
|
-
}
|
|
60
|
-
if ([
|
|
61
|
-
TransferDirection.none,
|
|
62
|
-
TransferDirection.backendOnly,
|
|
63
|
-
TransferDirection.deviceOnly,
|
|
64
|
-
TransferDirection.up,
|
|
65
|
-
TransferDirection.upPlus
|
|
66
|
-
].includes(containerDefinition.transferDirection)) {
|
|
67
|
-
// containerAttributes['download'] = '0';
|
|
68
|
-
xmlAttr('download', '0');
|
|
69
|
-
}
|
|
70
|
-
// set edit=99 on upward containers to reject write access via API
|
|
71
|
-
// only for IoT apps and libraries. For addons or analytics this is not needed.
|
|
72
|
-
if ((manifest_1.Manifest.isIotApp(manifest) || manifest_1.Manifest.isLibrary(manifest)) &&
|
|
73
|
-
[TransferDirection.up, TransferDirection.upPlus].includes(containerDefinition.transferDirection)) {
|
|
74
|
-
xmlAttr('edit', '99');
|
|
75
|
-
}
|
|
76
|
-
//insert fields:
|
|
77
|
-
for (const field of containerDefinition.fields) {
|
|
78
|
-
if (field.type === 'shadow') {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const patchedField = patchFieldWithArrayInfo(field);
|
|
82
|
-
const typeDefinition = fieldTypeDefinitions[patchedField.type];
|
|
83
|
-
// build the field title:
|
|
84
|
-
let fieldTitle = parseXMLValueWithRelation('title', patchedField, ddeMap) || patchedField.name;
|
|
85
|
-
// only add the library prefix if the attribute is not referenced
|
|
86
|
-
if (!fieldTitle.startsWith('%') && patchedField.library) {
|
|
87
|
-
fieldTitle = `${patchedField.library}: ${fieldTitle}`;
|
|
88
|
-
}
|
|
89
|
-
const xmlField = {
|
|
90
|
-
title: fieldTitle,
|
|
91
|
-
alias: patchedField.name,
|
|
92
|
-
index: field.index,
|
|
93
|
-
...containerAttributes
|
|
94
|
-
};
|
|
95
|
-
xmlField.byteofs = `${patchedField.byteOffset}`;
|
|
96
|
-
// add xml attributes based on field type
|
|
97
|
-
for (const [attribute, value] of Object.entries(typeDefinition.xml)) {
|
|
98
|
-
//@ts-ignore
|
|
99
|
-
xmlField[attribute] = value;
|
|
100
|
-
}
|
|
101
|
-
if (Object.hasOwn(typeDefinition, 'xmlOut')) {
|
|
102
|
-
typeDefinition.xmlOut(xmlField, patchedField, ddeMap);
|
|
103
|
-
}
|
|
104
|
-
// additional attributes from the dde
|
|
105
|
-
xmlField.units = parseXMLValueWithRelation('unit', patchedField, ddeMap);
|
|
106
|
-
xmlField.chmode = parseXMLValueWithRelation('channelMode', patchedField, ddeMap);
|
|
107
|
-
// warn and alarm thresholds
|
|
108
|
-
xmlField.ialarm_high = parseXMLValueWithRelation('chartAlarmHigh', patchedField, ddeMap);
|
|
109
|
-
xmlField.ialarm_low = parseXMLValueWithRelation('chartAlarmLow', patchedField, ddeMap);
|
|
110
|
-
xmlField.iwarn_high = parseXMLValueWithRelation('chartWarningHigh', patchedField, ddeMap);
|
|
111
|
-
xmlField.iwarn_low = parseXMLValueWithRelation('chartWarningLow', patchedField, ddeMap);
|
|
112
|
-
xmlField.hysterese = parseXMLValueWithRelation('chartHysteresis', patchedField, ddeMap);
|
|
113
|
-
xmlField.itrigger = parseXMLValueWithRelation('chartTriggerThreshold', patchedField, ddeMap);
|
|
114
|
-
xmlField.itriggerus = parseXMLValueWithRelation('chartTriggerRelation', patchedField, ddeMap);
|
|
115
|
-
xmlField.setpoint = parseXMLValueWithRelation('chartSetPoint', patchedField, ddeMap);
|
|
116
|
-
xmlField.bitmask = parseXMLBitmask(patchedField);
|
|
117
|
-
// process field as hex
|
|
118
|
-
if (patchedField.hex) {
|
|
119
|
-
xmlField.editmask = '%HEX%';
|
|
120
|
-
}
|
|
121
|
-
if (patchedField.readPermission) {
|
|
122
|
-
xmlField.view = patchedField.readPermission;
|
|
123
|
-
}
|
|
124
|
-
if (patchedField.writePermission) {
|
|
125
|
-
xmlField.edit = patchedField.writePermission;
|
|
126
|
-
}
|
|
127
|
-
if (patchedField.defaultValue !== undefined) {
|
|
128
|
-
xmlField.default = parseXMLDefaultValue(patchedField);
|
|
129
|
-
}
|
|
130
|
-
if (patchedField.utilsTransferInterval === true) {
|
|
131
|
-
xmlField.param0 = '%FFFF0005%transfer_interval';
|
|
132
|
-
}
|
|
133
|
-
xml('<field>');
|
|
134
|
-
if (patchedField.library) {
|
|
135
|
-
xml(`// declared by ${patchedField.library} library`, true);
|
|
136
|
-
}
|
|
137
|
-
for (const [attribute, value] of Object.entries(xmlField)) {
|
|
138
|
-
// if (attribute === 'byteofs') {
|
|
139
|
-
// xml(`// patching byte offset due to removed field`);
|
|
140
|
-
// }
|
|
141
|
-
if (value !== undefined) {
|
|
142
|
-
xmlAttr(attribute, `${value}`);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
xml('</field>');
|
|
146
|
-
}
|
|
147
|
-
// end of container
|
|
148
|
-
if (!['alerts', 'applog'].includes(containerName)) {
|
|
149
|
-
xml('</table>');
|
|
150
|
-
xml('// ' + containerDefinition.size + ' bytes total size');
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// insert alerts stream
|
|
154
|
-
xml('<split>');
|
|
155
|
-
xml(rm2mraw);
|
|
156
|
-
xml('target=alarm0');
|
|
157
|
-
xml('key=20'); // implicit hex!
|
|
158
|
-
xml('</split>');
|
|
159
|
-
// insert applog stream
|
|
160
|
-
xml('<split>');
|
|
161
|
-
xml(rm2mraw);
|
|
162
|
-
xml('target=applog0');
|
|
163
|
-
xml('key=28'); // implicit hex!
|
|
164
|
-
xml('</split>');
|
|
165
|
-
return xml_.join('\n');
|
|
166
|
-
}
|
|
167
|
-
function patchFieldWithArrayInfo(ddeField) {
|
|
168
|
-
const clonedField = structuredClone(ddeField);
|
|
169
|
-
const arrayIndex = ddeField.arrayRef?.index;
|
|
170
|
-
if (arrayIndex === undefined) {
|
|
171
|
-
return clonedField;
|
|
172
|
-
}
|
|
173
|
-
// eslint-disable-next-line prefer-const
|
|
174
|
-
for (let [attribute, value] of Object.entries(clonedField)) {
|
|
175
|
-
// @ts-ignore
|
|
176
|
-
clonedField[attribute] = helper_1.Helper.patchValueWithArrayInfo(value, arrayIndex);
|
|
177
|
-
}
|
|
178
|
-
return clonedField;
|
|
179
|
-
}
|
|
180
|
-
//# sourceMappingURL=xml.js.map
|