@microtronics/studio-cli 0.61.0 → 0.63.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.
@@ -1,1014 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.AutoDDEGenerator = void 0;
27
- exports.getPawnTypeDefinition = getPawnTypeDefinition;
28
- exports.generateAutoIncFromMap = generateAutoIncFromMap;
29
- exports.generateAutoUplinkIncFromMap = generateAutoUplinkIncFromMap;
30
- exports.generateMainDDEIncFromMap = generateMainDDEIncFromMap;
31
- exports.buildDefaultInc = buildDefaultInc;
32
- const semver = __importStar(require("semver"));
33
- const coreDefinitions_1 = require("../coreDefinitions");
34
- const DeviceProfiles_1 = require("../../DeviceProfiles");
35
- const manifest_1 = require("../../manifest");
36
- const helper_1 = require("../../helper");
37
- var ContainerType = coreDefinitions_1.DDE_Core.ContainerType;
38
- var TransferDirection = coreDefinitions_1.DDE_Core.TransferDirection;
39
- var regexRelation = coreDefinitions_1.DDE_Core.regexRelation;
40
- var CONFIG_CONTAINER = coreDefinitions_1.DDE_Core.CONFIG_CONTAINER;
41
- var CONTAINER_DEF_DLO_CID_BASE = coreDefinitions_1.DDE_Core.CONTAINER_DEF_DLO_CID_BASE;
42
- var CONTAINER_DEFS = coreDefinitions_1.DDE_Core.CONTAINER_DEFS;
43
- var fieldTypeDefinitions = coreDefinitions_1.DDE_Core.fieldTypeDefinitions;
44
- const vscode_uri_1 = require("vscode-uri");
45
- const defaultFiles_1 = require("../../defaultFiles");
46
- const dependencies_1 = require("../../dependencies");
47
- var isNumeric = helper_1.Helper.isNumeric;
48
- const apm_1 = require("../../package/apm");
49
- /** get effective field type for pawn access (may be overriden or skipped using attribute dlorw=...)
50
- * @return {*} | 'skip' | null - null=error occured
51
- */
52
- function getPawnTypeDefinition(field) {
53
- const tdef = fieldTypeDefinitions[field.type]; // just a shorthand
54
- // supplement default values
55
- if (!tdef.pwn.rwp) {
56
- tdef.pwn.rwp = '%n';
57
- }
58
- if (!tdef.pwn.htype) {
59
- tdef.pwn.htype = tdef.pwn.rwfunc;
60
- }
61
- // regular pawn access
62
- return tdef.pwn;
63
- }
64
- const MICROTRONICS_DLO_CORE = 'Microtronics/dlo-core';
65
- function getIncludedDloCoreVersion(manifest) {
66
- if (manifest_1.Manifest.isLibrary(manifest) && manifest.name === 'dlo-core') {
67
- return manifest.version;
68
- }
69
- else if (manifest.libraryDependencies && Object.hasOwn(manifest.libraryDependencies, MICROTRONICS_DLO_CORE)) {
70
- return dependencies_1.Dependencies.rangeToVersion(manifest.libraryDependencies[MICROTRONICS_DLO_CORE]);
71
- }
72
- else if (manifest.libraryDevDependencies && Object.hasOwn(manifest.libraryDevDependencies, MICROTRONICS_DLO_CORE)) {
73
- return dependencies_1.Dependencies.rangeToVersion(manifest.libraryDevDependencies[MICROTRONICS_DLO_CORE]);
74
- }
75
- return null;
76
- }
77
- function getApmVersion(manifest) {
78
- const requiredVersion = getIncludedDloCoreVersion(manifest);
79
- if (requiredVersion === null || semver.gte(requiredVersion, '0.3.0')) {
80
- return semver.valid(manifest.version) ? manifest.version : semver.coerce(`${manifest.version}`);
81
- }
82
- else {
83
- return semver.coerce(manifest.version)?.major;
84
- }
85
- }
86
- /**
87
- * Determines if the dlo-core library version described in the provided manifest supports live data functionality.
88
- *
89
- * @param {Manifest.Manifest} manifest - The manifest object containing details about the DLO core.
90
- * @return {boolean} Returns true if the dlo-core version supports live data, otherwise false.
91
- */
92
- function dloCoreSupportsFlags(manifest) {
93
- const requiredVersion = getIncludedDloCoreVersion(manifest);
94
- if (requiredVersion === null) {
95
- return false;
96
- }
97
- const releaseVersion = semver.coerce(requiredVersion);
98
- return semver.gte(releaseVersion, '1.1.0');
99
- }
100
- // eslint-disable-next-line sonarjs/cognitive-complexity
101
- function generateAutoIncFromMap(ddeMap, resolvedConfig, manifest) {
102
- const _pwn = []; // sample code output for pawn
103
- const pwn = _pwn.push.bind(_pwn);
104
- function pwn_section(s) {
105
- pwn(`\n// === ${s} ===\n`);
106
- }
107
- /**
108
- * generate PROJECT META definitions
109
- */
110
- pwn_section('PROJECT META');
111
- function addDefinition(name, value, noString = false) {
112
- let quotes = isNumeric(value) ? '' : '"';
113
- if (noString) {
114
- quotes = '';
115
- }
116
- pwn(`#define ${name} ${quotes}${value}${quotes}`);
117
- }
118
- const { dpid, registry } = manifest;
119
- if (!dpid) {
120
- throw new Error('Setting "dpid" is required to generate dlo files');
121
- }
122
- const { auto_inc } = DeviceProfiles_1.DeviceProfiles[dpid];
123
- addDefinition(`APM_DPID`, `${dpid}`);
124
- addDefinition(`APM_DPID_${dpid}`, `1`);
125
- addDefinition(`APM_DPID_${dpid.toUpperCase()}`, `1`);
126
- addDefinition(`APM_ID`, registry?.id || ''); //
127
- const currVersion = getApmVersion(manifest);
128
- addDefinition(`APM_VERSION`, `${currVersion}`); // 1,
129
- addDefinition(`APM_NAME`, `${manifest.name}`); // "project X",
130
- addDefinition(`APM_AUTHOR`, `${manifest.publisher}`);
131
- for (const [name, value] of Object.entries(auto_inc)) {
132
- // quote all non-numeric values
133
- if (!isNumeric(value)) {
134
- addDefinition(name, `"${value}"`);
135
- }
136
- else {
137
- addDefinition(name, `${value}`);
138
- }
139
- }
140
- /**
141
- * generate global dlo defines if there are any
142
- */
143
- const globalDefines = resolvedConfig.flat;
144
- const { definesWithSource } = resolvedConfig;
145
- pwn_section('GLOBAL DEFINES');
146
- for (const [define, value] of Object.entries(globalDefines)) {
147
- const comment = definesWithSource[define]?.comment;
148
- if (comment) {
149
- const lines = comment.split('\n');
150
- if (lines.length === 1) {
151
- pwn(`/** ${lines[0]} */`);
152
- }
153
- else {
154
- pwn('/**');
155
- for (const line of lines) {
156
- pwn(` * ${line}`);
157
- }
158
- pwn(' */');
159
- }
160
- }
161
- const valueIsDefine = Object.hasOwn(globalDefines, value);
162
- addDefinition(define, `${value}`, valueIsDefine);
163
- }
164
- /**
165
- * generate DDE-CORE definitions
166
- */
167
- let sz_max = 0; // maximum byte size over all configX and histdataX
168
- const cx_szs = Array(10).fill(0); // configX byte size
169
- let cx_isupm = 0; // configX upward - bitmask
170
- let cx_isvolatilem = 0; // configX dlo-volatile - bitmask
171
- let cx_isdnm = 0; // configX downward - bitmask
172
- let cx_isvlm = 0; // configX variable length - bitmask
173
- const cx_isrdef = 0; // configX variable length - bitmask
174
- const hx_szs = Array(10).fill(0); // histdataX byte size
175
- let hx_isvlm = 0; // histdataX variable length - bitmask
176
- let aloha_varlen = undefined;
177
- for (const [containerName, containerDefinition] of Object.entries(ddeMap.containers)) {
178
- if (containerDefinition.containerType === ContainerType.cx &&
179
- containerDefinition.transferDirection !== TransferDirection.backendOnly) {
180
- const cx = parseInt(containerName.substring(6));
181
- const cmsk = 1 << cx;
182
- cx_szs[cx] = containerDefinition.size;
183
- cx_isupm |= [
184
- TransferDirection.both,
185
- TransferDirection.none,
186
- TransferDirection.deviceOnly,
187
- TransferDirection.up,
188
- TransferDirection.upPlus
189
- ].includes(containerDefinition.transferDirection)
190
- ? cmsk
191
- : 0;
192
- cx_isvolatilem |= containerDefinition.volatile ? cmsk : 0;
193
- cx_isdnm |= [
194
- TransferDirection.both,
195
- TransferDirection.none,
196
- TransferDirection.deviceOnly,
197
- TransferDirection.down,
198
- TransferDirection.downPlus
199
- ].includes(containerDefinition.transferDirection)
200
- ? cmsk
201
- : 0;
202
- cx_isvlm |= [TransferDirection.bothPlus, TransferDirection.upPlus, TransferDirection.downPlus].includes(containerDefinition.transferDirection)
203
- ? cmsk
204
- : 0;
205
- // cx_isrdef |= cont.rdef ? 1 << cx : 0; //validation for down/down+ is don in the dde
206
- sz_max = Math.max(sz_max, containerDefinition.size);
207
- }
208
- else if (containerDefinition.containerType === ContainerType.hx) {
209
- const hx = parseInt(containerName.substring(8));
210
- hx_szs[hx] = containerDefinition.size;
211
- hx_isvlm |= [TransferDirection.upPlus].includes(containerDefinition.transferDirection) ? 1 << hx : 0;
212
- sz_max = Math.max(sz_max, containerDefinition.size);
213
- }
214
- else if (containerDefinition.containerType === ContainerType.aloha) {
215
- aloha_varlen = [TransferDirection.upPlus].includes(containerDefinition.transferDirection);
216
- sz_max = Math.max(sz_max, containerDefinition.size);
217
- }
218
- }
219
- pwn_section('DDE CORE');
220
- pwn(`#define _DDE_BUF_BYTES (${sz_max}+10)`); // todo rem +10 ??? round to next multiple of 4 ???
221
- pwn('');
222
- pwn('// c0\tc1\tc2\tc3\tc4\tc5\tc6\tc7\tc8\tc9');
223
- pwn(`stock _DDE_CONFIGS_size[] =[ ${cx_szs.join(',\t')}];`);
224
- pwn(`#define _DDE_CONFIGS_upm 0b${cx_isupm.toString(2)} // ..is tolerant when reading back container with under-length`);
225
- pwn(`#define _DDE_CONFIGS_volatilem 0b${cx_isvolatilem.toString(2)} // inits container as volatile`);
226
- pwn(`#define _DDE_CONFIGS_downm 0b${cx_isdnm.toString(2)} // reading the container expects strict length`);
227
- pwn(`#define _DDE_CONFIGS_varlenm 0b${cx_isvlm.toString(2)} // allow partial write (dde_wxxx)`);
228
- pwn(`#define _DDE_CONFIGS_rdef 0b${cx_isrdef.toString(2)} // ..apply defaults reading a container with under-length`);
229
- pwn('');
230
- pwn('// h0\th1\th2\th3\th4\th5\th6\th7\th8\th9');
231
- pwn(`stock _DDE_HISTS_size[] =[ ${hx_szs.join(',\t')}];`);
232
- pwn(`#define _DDE_HISTS_varlenm 0b${hx_isvlm.toString(2)} // allow partial write (dde_wxxx)`);
233
- //see #RS-279 for more information about the _DDE_HISTS_maxsize
234
- const szs = [...hx_szs];
235
- if (Object.hasOwn(ddeMap, 'applog')) {
236
- szs.push(125);
237
- }
238
- if (Object.hasOwn(ddeMap, 'alerts')) {
239
- szs.push(13);
240
- }
241
- pwn(`#define _DDE_HISTS_maxsize ${Math.max(...szs)}`);
242
- pwn('');
243
- if (aloha_varlen !== undefined) {
244
- pwn(`#define _DDE_ALOHA_varlen ${aloha_varlen ? 1 : 0}`);
245
- pwn('');
246
- }
247
- // generate
248
- // #define DDE_xxx_id
249
- // #define DDE_xxx_sz
250
- // #define DDE_xxx_idx
251
- for (const [containerName, containerDefinition] of Object.entries(ddeMap.containers)) {
252
- //special handling for applog container is handled afterwards
253
- if (containerDefinition.containerType === 'applog') {
254
- continue;
255
- }
256
- pwn_section(`${containerDefinition.title.toUpperCase()} - ${containerDefinition.transferDirection} via #${containerName}`);
257
- const cid_base = CONTAINER_DEF_DLO_CID_BASE(containerDefinition.containerType, containerDefinition.transferDirection);
258
- if (!cid_base) {
259
- pwn(`// ... container not available in DLO`);
260
- continue;
261
- }
262
- const preAlias = `DDE_${containerDefinition.containerType === ContainerType.aloha ? ContainerType.aloha : containerDefinition.title}`;
263
- const CDEF = CONTAINER_DEFS[containerName];
264
- pwn(`// ${preAlias}_id - container identifier required for ${preAlias}_read/_write operations`);
265
- pwn(`#define ${preAlias}_id (${cid_base}+${CDEF.cnum || 0})`);
266
- pwn(`// ${preAlias}_sz - [byte] container total size`);
267
- pwn(`#define ${preAlias}_sz ${containerDefinition.size}`);
268
- if (CDEF.cnum !== undefined) {
269
- pwn(`// ${preAlias}_idx - 0+ container index number`);
270
- pwn(`#define ${preAlias}_idx ${CDEF.cnum}`);
271
- }
272
- }
273
- // setup results
274
- return _pwn.join('\n');
275
- }
276
- class AutoDDEGenerator {
277
- manifest;
278
- ddeMap;
279
- context;
280
- globalVariables = [];
281
- pawnGlobalSource = [];
282
- pawnHelperSource = [];
283
- timeSeriesSource = [];
284
- readWriteSource = [];
285
- definesSource = [];
286
- defaultDefinesSource = [];
287
- knownDefines = [];
288
- pawnIndent = 0;
289
- sourceType;
290
- constructor(manifest, ddeMap, context) {
291
- this.manifest = manifest;
292
- this.ddeMap = ddeMap;
293
- this.context = context;
294
- this.sourceType = 'pawnSource';
295
- }
296
- pawn(a, b) {
297
- if (b && a === '<') {
298
- this.pawnIndent--;
299
- }
300
- const sourceToPush = {
301
- pawnSource: this.pawnGlobalSource,
302
- globalVariables: this.globalVariables,
303
- timeseries: this.timeSeriesSource,
304
- readWrite: this.readWriteSource,
305
- defines: this.definesSource,
306
- defaultDefines: this.defaultDefinesSource
307
- }[this.sourceType];
308
- sourceToPush.push('\t'.repeat(this.pawnIndent) + (b || a));
309
- if (b && a === '>') {
310
- this.pawnIndent++;
311
- }
312
- }
313
- generate() {
314
- for (const [containerName, containerDefinition] of Object.entries(this.ddeMap.containers)) {
315
- // check if the given library uses this container
316
- if (this.context && !containerDefinition.libraries.includes(this.context)) {
317
- continue;
318
- }
319
- const containerIdBase = CONTAINER_DEF_DLO_CID_BASE(containerDefinition.containerType, containerDefinition.transferDirection);
320
- //container is not available in dlo or has any fields
321
- if (!containerIdBase || !containerDefinition.fields) {
322
- continue;
323
- }
324
- // only generate the apps rw functions if the app has defined fields
325
- if (!this.context && !coreDefinitions_1.DDE_Core.hasContainerAppFields(containerDefinition)) {
326
- continue;
327
- }
328
- const CONTDEF = CONTAINER_DEFS[containerName];
329
- if (CONTDEF.ctype !== ContainerType.cx && this.context) {
330
- continue;
331
- }
332
- this.generateGlobalVarsForContainer(containerDefinition);
333
- this.generateReadWriteFunctions(containerDefinition);
334
- }
335
- this.mergeSourceTypes();
336
- return { globals: this.pawnGlobalSource, helper: this.pawnHelperSource };
337
- }
338
- createGlobalVar(variableName, field) {
339
- this.sourceType = 'globalVariables';
340
- const varName = field ? this.variableNameForPawnDefinition(variableName, field) : variableName;
341
- if (field) {
342
- const comment = this.generateCommentForField(field);
343
- if (comment) {
344
- if (Array.isArray(comment)) {
345
- this.pawn('/**');
346
- comment.forEach(line => {
347
- this.pawn(` * ${line}`);
348
- });
349
- this.pawn(' */');
350
- }
351
- else {
352
- this.pawn(`// ${comment}`);
353
- }
354
- }
355
- }
356
- this.pawn(`stock ${varName};`);
357
- }
358
- insertSection(title) {
359
- this.pawn('');
360
- this.pawn('// =============================================================================');
361
- this.pawn(`// ${title}`);
362
- this.pawn('// =============================================================================');
363
- this.pawn('');
364
- }
365
- mergeSourceTypes() {
366
- this.sourceType = 'pawnSource';
367
- if (this.definesSource.length) {
368
- this.insertSection('Defines');
369
- this.pawnGlobalSource.push(...this.definesSource);
370
- }
371
- if (this.defaultDefinesSource.length) {
372
- this.insertSection('Field defaults');
373
- this.pawnGlobalSource.push(...this.defaultDefinesSource);
374
- }
375
- if (this.globalVariables.length) {
376
- this.insertSection('Global Variables');
377
- this.pawnGlobalSource.push(...this.globalVariables);
378
- }
379
- if (this.readWriteSource.length) {
380
- this.insertSection('Internal read/write calls');
381
- this.pawnHelperSource.push(...this.readWriteSource);
382
- }
383
- this.pawn('');
384
- }
385
- generateGlobalVarsForContainer(containerDefinition) {
386
- // this.globalVariables.push('// === Global variables ===');
387
- this.sourceType = 'globalVariables';
388
- this.pawn('');
389
- this.pawn(`// Container '${containerDefinition.title.replace('_', ' ')}'`);
390
- this.pawn('');
391
- const pre = `DDE_${containerDefinition.title}`;
392
- // defines for arrays
393
- for (const arrayInfo of Object.values(containerDefinition.arrays)) {
394
- if (this.context !== arrayInfo.library) {
395
- continue;
396
- }
397
- const arrayDimension = `${pre}_${arrayInfo.name}_dim`;
398
- this.sourceType = 'defines';
399
- this.pawn(`#define ${arrayDimension} ${arrayInfo.length}`);
400
- if (arrayInfo.fields) {
401
- // generate _dim defines for blob-type subfields within structured arrays
402
- for (const subField of arrayInfo.fields) {
403
- const subFieldTypeDef = fieldTypeDefinitions[subField.type];
404
- if (subFieldTypeDef?.isBlob && subField.byteSize) {
405
- this.addDefine(`${pre}_${arrayInfo.name}_${subField.name}_dim`, subField.byteSize);
406
- }
407
- }
408
- const fakeDDEContainer = {
409
- ...containerDefinition
410
- };
411
- fakeDDEContainer.fields = [];
412
- arrayInfo.fields.forEach(field => {
413
- fakeDDEContainer.fields.push({
414
- arrayRef: null,
415
- shadowRef: null,
416
- byteOffset: 0,
417
- byteSize: field.byteSize,
418
- id: field.name,
419
- library: arrayInfo.library,
420
- name: field.name,
421
- type: field.type,
422
- title: null,
423
- index: 0
424
- });
425
- });
426
- const arrayStructure = `${pre}_${arrayInfo.name}_def`;
427
- this.generateTypeDefinitions(fakeDDEContainer, arrayStructure);
428
- this.createGlobalVar(`${pre}_${arrayInfo.name}[${arrayDimension}][${arrayStructure}]`);
429
- }
430
- else {
431
- this.createGlobalVar(`${pre}_${arrayInfo.name}[${arrayDimension}]`);
432
- }
433
- }
434
- for (const field of containerDefinition.fields) {
435
- if (field.type === 'shadow' || field.shadowRef || field.library !== this.context) {
436
- continue;
437
- }
438
- // generate defines for array fields
439
- if (field.arrayRef !== null) {
440
- const ref = containerDefinition.arrays[field.arrayRef.name];
441
- let defineName = `${pre}_${field.arrayRef.name}`;
442
- // this is a structured array, add the field name to the define
443
- if (ref.fields?.length) {
444
- defineName += `_${field.name.split('.')[1]}`;
445
- }
446
- this.createDefaultDefineForField(defineName, field);
447
- continue;
448
- }
449
- const variableName = this.generateFieldVariableName(pre, field);
450
- this.createDefaultDefineForField(variableName, field);
451
- this.createGlobalVar(`${variableName}`, field);
452
- }
453
- }
454
- generateCommentForField(field) {
455
- const fieldComment = [`@type ${field.type}`];
456
- if (field.description) {
457
- fieldComment.unshift(field.description);
458
- }
459
- if (field.defaultValue !== undefined) {
460
- const { value, reason } = this.parseFieldDefault(field);
461
- fieldComment.push(`@default ${value} ${reason || ''}`);
462
- }
463
- return fieldComment;
464
- }
465
- generateFieldVariableName(pre, field) {
466
- const fieldVariableName = `${pre}_${field.name}`;
467
- const isBlob = Object.hasOwn(fieldTypeDefinitions, field.type) && fieldTypeDefinitions[field.type].isBlob;
468
- const dim = field.byteSize;
469
- if (dim && isBlob) {
470
- const loopVar = 'i';
471
- this.sourceType = 'defines';
472
- this.pawn(`#define ${pre}_${field.name}_dim ${dim}`);
473
- this.pawn(`#define ${pre}_${field.name}_iter() for(new ${loopVar}=0;${loopVar}<${dim};${loopVar}++)`);
474
- }
475
- this.sourceType = 'globalVariables';
476
- return fieldVariableName;
477
- }
478
- // generate type declarations
479
- // eslint-disable-next-line sonarjs/cognitive-complexity
480
- generateTypeDefinitions(containerDefinition, base) {
481
- this.sourceType = 'defines';
482
- const xfields = containerDefinition.fields;
483
- if (!xfields) {
484
- return;
485
- }
486
- const knownArrays = [];
487
- this.pawn('>', `#define ${base} [`);
488
- for (const field of xfields) {
489
- if (field.type === 'shadow' || field.shadowRef) {
490
- continue;
491
- }
492
- // validate context of field
493
- if (field.library !== this.context) {
494
- continue;
495
- }
496
- // avoid creating multiple definitions if the field is part of an array
497
- const arrayRef = field.arrayRef;
498
- if (arrayRef) {
499
- const arrayInfo = containerDefinition.arrays[arrayRef.name];
500
- if (!knownArrays.includes(arrayRef.name) && !arrayInfo.fields) {
501
- knownArrays.push(arrayRef.name);
502
- }
503
- else {
504
- continue;
505
- }
506
- }
507
- const fieldName = field.arrayRef ? field.arrayRef.name : field.name;
508
- const fld_dim = field.arrayRef ? `[${base}_${fieldName}_dim]` : '';
509
- // let comment = fld.xfields ? `${base}_${fld.name}` : fld.type; // original DDE field type as comment
510
- let fld_def = '';
511
- if (field.type === 'struct') {
512
- fld_def = '// .' + fieldName + fld_dim; // comment out if it's a struct field
513
- }
514
- else {
515
- const tdef_pwn = getPawnTypeDefinition(field);
516
- if (!tdef_pwn) {
517
- continue;
518
- } // error - do nothing
519
- if (tdef_pwn === 'skip') {
520
- fld_def = `// skipped - .${fieldName}${fld_dim}`; // '.xyz[5]'
521
- }
522
- else {
523
- fld_def += tdef_pwn.rwp.replace('%n', `.${fieldName}${fld_dim}`).replace('%l', field.byteSize);
524
- }
525
- }
526
- fld_def += ',';
527
- // add library comment if the field comes from an library
528
- if (field.library) {
529
- fld_def += `\t // declared by ${field.library} library`;
530
- }
531
- this.pawn(fld_def);
532
- }
533
- this.pawn('<', ']');
534
- }
535
- variableNameForPawnDefinition(variableName, field) {
536
- // variable name based on the pawn definitions
537
- const pawnTypeDefinition = getPawnTypeDefinition(field);
538
- if (pawnTypeDefinition && pawnTypeDefinition !== 'skip') {
539
- return pawnTypeDefinition.rwp.replace('%n', `${variableName}`).replace('%l', field.byteSize);
540
- }
541
- return variableName;
542
- }
543
- createDefaultDefineForField(variableName, field) {
544
- this.sourceType = 'defaultDefines';
545
- if (field.scale !== undefined) {
546
- this.addDefine(`${variableName}_scale`, field.scale);
547
- }
548
- if (field.offset !== undefined) {
549
- this.addDefine(`${variableName}_offset`, field.offset);
550
- }
551
- if (field.defaultValue !== undefined) {
552
- const { value, reason } = this.parseFieldDefault(field);
553
- const defineName = `${variableName}_default`;
554
- field.defaultDloDefine = defineName;
555
- this.addDefine(defineName, value, reason);
556
- }
557
- }
558
- /**
559
- * Add given variable as define to the dlo source
560
- * @param name of define
561
- * @param value of define
562
- * @param reason comment for define
563
- * @private
564
- */
565
- addDefine(name, value, reason) {
566
- const containerRelation = regexRelation.exec(`${value}`);
567
- if (containerRelation) {
568
- return;
569
- }
570
- if (!this.knownDefines.includes(name)) {
571
- if (reason) {
572
- this.pawn(`// ${reason}`);
573
- }
574
- this.pawn(`#define ${name} ${value}`);
575
- this.knownDefines.push(name);
576
- }
577
- }
578
- generateReadWriteFunctions(containerDefinition) {
579
- const containerName = containerDefinition.name;
580
- const CONTDEF = CONTAINER_DEFS[containerName];
581
- const pre = `DDE_${containerDefinition.containerType === ContainerType.aloha ? ContainerType.aloha : containerDefinition.title}`;
582
- // ---
583
- // add write method - but for UP_ward containers only
584
- // ---
585
- if ([
586
- TransferDirection.both,
587
- TransferDirection.bothPlus,
588
- TransferDirection.none,
589
- TransferDirection.deviceOnly,
590
- TransferDirection.up,
591
- TransferDirection.upPlus
592
- ].includes(containerDefinition.transferDirection)) {
593
- this.generateWriteMethod(pre, containerDefinition);
594
- }
595
- // ---
596
- // add read method - but for CONFIG0-9 containers only
597
- // ---
598
- if (CONTDEF.ctype === ContainerType.cx) {
599
- this.generateReadMethod(pre, containerDefinition);
600
- }
601
- }
602
- generateWriteMethod(pre, containerDefinition) {
603
- this.sourceType = 'readWrite';
604
- const containerID = `DDE_${containerDefinition.title}_id`;
605
- const isTimeseriesOrAloha = [ContainerType.hx, ContainerType.aloha].includes(containerDefinition.containerType);
606
- const isTimeseriesContainer = containerDefinition.containerType === ContainerType.hx;
607
- const isAlohaContainer = containerDefinition.containerType === ContainerType.aloha;
608
- const funcWrite = `_${pre}_write`;
609
- const timeseriesFlags = dloCoreSupportsFlags(this.manifest) ? ', flags' : '';
610
- const timeseriesOrAlohaArguments = isTimeseriesContainer ? `stamp${timeseriesFlags}` : '';
611
- const funcWriteFlags = dloCoreSupportsFlags(this.manifest) ? 'const stamp=0, const flags=0' : 'const stamp=0';
612
- this.pawn('>', `stock ${funcWrite}(${isTimeseriesContainer ? funcWriteFlags : ''}) {`);
613
- // only aloha and time series write directly to the container
614
- if (isTimeseriesOrAloha) {
615
- this.pawn(`dde_wbegin(DDE_${isAlohaContainer ? ContainerType.aloha : containerDefinition.title}_id);`); // " dde_wbegin( DDE_status_id);"
616
- }
617
- this.generateRWFunctionBody(pre, containerDefinition, 'dde_w');
618
- // only aloha and time series write directly to the container
619
- if (isTimeseriesOrAloha) {
620
- this.pawn(`return dde_wend(${timeseriesOrAlohaArguments});`); // " dde_wend();"
621
- }
622
- this.pawn('<', '}');
623
- this.pawn('');
624
- // flush function
625
- this.sourceType = 'globalVariables';
626
- const funcFlush = `${pre}_transfer`;
627
- const funcPersist = `${pre}_persist`;
628
- const funcArgs = this.functionArgumentsForDdeWrite(isTimeseriesContainer, isTimeseriesOrAloha);
629
- this.pawn('>', `${this.context ? 'stock ' : ''}${funcFlush}(${funcArgs}) {`);
630
- if (isTimeseriesOrAloha) {
631
- this.pawn(`${funcWrite}(${timeseriesOrAlohaArguments});`);
632
- }
633
- else {
634
- const containerNumber = containerDefinition.name.slice(-1);
635
- this.pawn(`dde_flush(${containerNumber}, immediate);`);
636
- }
637
- this.pawn('<', '}');
638
- this.pawn('');
639
- if (containerDefinition.volatile) {
640
- // generate persist function declaration
641
- this.pawn('>', `stock ${funcPersist}() {`);
642
- this.pawn(`return rM2M_CfgFlush(${containerID});`);
643
- this.pawn('<', '}');
644
- }
645
- }
646
- /**
647
- * if it's a timeseries container the argument is `const stamp=0`
648
- * if it's a configuration container the argument is `bool:immediate=false`
649
- * @param isTimeseriesContainer
650
- * @param isTimeseriesOrAloha
651
- * @private
652
- */
653
- functionArgumentsForDdeWrite(isTimeseriesContainer, isTimeseriesOrAloha) {
654
- const timeseriesFlags = dloCoreSupportsFlags(this.manifest) ? ', const flags=0' : '';
655
- return isTimeseriesContainer
656
- ? `const stamp=0${timeseriesFlags}`
657
- : isTimeseriesOrAloha
658
- ? ''
659
- : 'bool:immediate=false';
660
- }
661
- generateReadMethod(pre, containerDefinition) {
662
- this.sourceType = 'readWrite';
663
- // const containerID = `${pre}_id`;
664
- // todo implement as "hidden" function
665
- const funcRead = `_${pre}_read`;
666
- this.pawn('>', `stock ${funcRead}() {`);
667
- this.generateRWFunctionBody(pre, containerDefinition, 'dde_r');
668
- this.pawn('<', '}');
669
- this.pawn('');
670
- }
671
- generateRWFunctionBody(pre, containerDefinition, ddeFunc) {
672
- const xfields = containerDefinition.fields;
673
- for (const fld of xfields) {
674
- // validate context of field
675
- if (fld.type === 'shadow' || fld.shadowRef || fld.library !== this.context) {
676
- continue;
677
- }
678
- // assert(!fld.xfields);
679
- const tdef_pwn = getPawnTypeDefinition(fld); // pawn access methods to use
680
- if (!tdef_pwn || tdef_pwn === 'skip') {
681
- continue;
682
- }
683
- // set the byte offset for the next field
684
- this.pawn(`_dde_idx = ${fld.byteOffset};`);
685
- let s = ''; // resulting pawn line e.g. " dde_wu32( o.live_trg);"
686
- s += ddeFunc;
687
- s += tdef_pwn.rwfunc;
688
- const fieldName = `${pre}_${fld.name}`;
689
- s += `(${fieldName}`;
690
- if (tdef_pwn.rwlen) {
691
- s += `, ${fld.byteSize}`;
692
- } // add byte/cellcount on strings & buffers
693
- // add the default field value to the read function only
694
- if (fld.defaultDloDefine !== undefined && ddeFunc === 'dde_r') {
695
- s += `, ${fld.defaultDloDefine}`;
696
- }
697
- this.pawn(s + `);`);
698
- }
699
- }
700
- parseFieldDefault(field) {
701
- const typeDefinitions = getPawnTypeDefinition(field);
702
- let defaultValue = field.defaultValue;
703
- function buildReturnObject(value, reason) {
704
- return { value, reason };
705
- }
706
- //modify the default value based on the string type. Either " or '';
707
- switch (field.type) {
708
- case 'astring':
709
- case 'nstring':
710
- case 'cstring': {
711
- return buildReturnObject(`"${defaultValue}"`);
712
- }
713
- case 'wstring': {
714
- return buildReturnObject(`''${defaultValue}''`);
715
- }
716
- case 'ustring': {
717
- return buildReturnObject(`/* default not supported: ${defaultValue} */`);
718
- }
719
- case 'binary': {
720
- // convert hex value to byte array equivalent...
721
- const splitted = defaultValue.substring(2).match(/.{1,2}/g) || [];
722
- const byteArray = `{ 0x${splitted.join(', 0x')} }`;
723
- return buildReturnObject(byteArray);
724
- }
725
- }
726
- if (defaultValue === 'NaN') {
727
- const dataType = typeDefinitions.rwfunc;
728
- return buildReturnObject(`${dataType}_NaN`.toUpperCase());
729
- }
730
- const scaledDefault = this.parseFieldScaleOffset(field);
731
- if (scaledDefault) {
732
- return buildReturnObject(scaledDefault.calculated, scaledDefault.reason);
733
- }
734
- // add missing fractionDigits to float types
735
- if (defaultValue !== undefined &&
736
- !regexRelation.exec(`${defaultValue}`) &&
737
- field.type.startsWith('float') &&
738
- defaultValue % 1 === 0) {
739
- defaultValue = defaultValue.toFixed(field.decimalPlaces || 1);
740
- }
741
- return buildReturnObject(`${defaultValue}`);
742
- }
743
- /**
744
- * Try to calculate the default value based on scale and offset
745
- * @param field
746
- * @private
747
- */
748
- parseFieldScaleOffset(field) {
749
- const defaultValue = field.defaultValue;
750
- // validate if any of the given fields has a relation to another container
751
- const isAnyRelation = !!regexRelation.exec(`${field.offset}`) ||
752
- !!regexRelation.exec(`${field.scale}`) ||
753
- !!regexRelation.exec(`${field.defaultValue}`);
754
- // scale || offset is set
755
- if (!isAnyRelation && (field.offset !== undefined || field.scale !== undefined)) {
756
- const offset = field.offset !== undefined ? Number(field.offset) : 0;
757
- const scale = field.scale !== undefined ? Number(field.scale) : 1;
758
- // calculate the original value without scale and offset
759
- let calculated = (Number(defaultValue) - offset) / scale;
760
- let reason = `(defaultValue - offset) / scale -> (${defaultValue} - ${offset}) / ${scale}`;
761
- // field type is no float - round to integer
762
- if (!field.type.startsWith('float')) {
763
- calculated = Math.round(calculated);
764
- reason = `Rounded value of: ${reason}`;
765
- }
766
- else if (calculated % 1 === 0) {
767
- calculated = calculated.toFixed(1);
768
- }
769
- return { calculated, reason };
770
- }
771
- return null;
772
- }
773
- }
774
- exports.AutoDDEGenerator = AutoDDEGenerator;
775
- // eslint-disable-next-line sonarjs/cognitive-complexity
776
- function generateAutoUplinkIncFromMap(ddeMap,
777
- /**
778
- * The names of the included libraries
779
- */
780
- includedLibNames) {
781
- const _pwn = [];
782
- const pwn = _pwn.push.bind(_pwn);
783
- // collect containers to apply/restore23
784
- const containerApply = [];
785
- const containerRestore = [];
786
- function buildUplinkApplyCall(applyName) {
787
- const funcName = `onUplinkApply_${applyName}()`;
788
- return `${funcName};`;
789
- }
790
- function buildLibraryRestoreApplyCall(cont, restoreApply) {
791
- cont.libraries.forEach(libraryName => {
792
- const hashedLib = helper_1.Helper.generateHashForLibraryName(libraryName);
793
- pwn(`\t#ifdef _${hashedLib}${restoreApply}_${cont.title}`);
794
- pwn(`\t\t_${hashedLib}${restoreApply}_${cont.title}();\t// ${libraryName}`);
795
- pwn('\t#endif');
796
- });
797
- }
798
- //generate onUplinkEvent dispatcher
799
- pwn(`stock _onUplinkEvent(ev, param) {`);
800
- // insert library calls...
801
- includedLibNames.forEach(libraryName => {
802
- const hashedName = helper_1.Helper.generateHashForLibraryName(libraryName);
803
- const funcName = `_${hashedName}UplinkEvent`;
804
- pwn(`\t#ifdef ${funcName}`);
805
- pwn(`\t\t${funcName}(ev, param);`);
806
- pwn(`\t#endif`);
807
- });
808
- pwn(`\tonUplinkEvent(ev, param);`);
809
- pwn(`}`);
810
- for (const [containerName, containerDefinition] of Object.entries(ddeMap.containers)) {
811
- const CONTDEF = CONTAINER_DEFS[containerName];
812
- if (CONTDEF.ctype !== ContainerType.cx) {
813
- continue;
814
- }
815
- if ([TransferDirection.up, TransferDirection.upPlus, TransferDirection.deviceOnly].includes(containerDefinition.transferDirection)) {
816
- containerRestore.push(containerDefinition);
817
- }
818
- if ([TransferDirection.bothPlus, TransferDirection.both, TransferDirection.downPlus, TransferDirection.down].includes(containerDefinition.transferDirection)) {
819
- containerApply.push(containerDefinition);
820
- }
821
- }
822
- if (containerRestore.length) {
823
- pwn('');
824
- }
825
- // generate restore code
826
- for (const cont of containerRestore) {
827
- cont.knownNames.forEach((libAlias) => {
828
- pwn(`forward onUplinkRestore_${libAlias}();`);
829
- });
830
- pwn('');
831
- pwn(`stock restoreUplink${cont.name}() {`);
832
- pwn(`\t_DDE_${cont.name}_read();`);
833
- buildLibraryRestoreApplyCall(cont, 'Restore');
834
- if (coreDefinitions_1.DDE_Core.hasContainerAppFields(cont)) {
835
- pwn(`\tonUplinkRestore_${cont.title}();`);
836
- }
837
- pwn(`}`);
838
- }
839
- pwn(`#pragma warning push`);
840
- pwn(`stock _onUplinkRestore(cfgId) {`);
841
- if (containerRestore.length) {
842
- pwn(`\tswitch(cfgId) {`);
843
- for (const cont of containerRestore) {
844
- pwn(`\t\tcase DDE_${cont.title}_id: restoreUplink${cont.name}(); // ${cont.name}`);
845
- }
846
- pwn(`\t}`);
847
- }
848
- else {
849
- pwn(`\t#pragma warning disable 203`);
850
- pwn(`\t// no containers to restore`);
851
- }
852
- pwn(`}`);
853
- pwn(`#pragma warning pop`);
854
- if (containerApply.length) {
855
- pwn('');
856
- }
857
- // generate apply code
858
- for (const cont of containerApply) {
859
- cont.knownNames.forEach((libAlias) => {
860
- pwn(`forward onUplinkApply_${libAlias}();`);
861
- });
862
- pwn('');
863
- pwn(`stock applyUplink${cont.name}() {`);
864
- pwn(`\t_DDE_${cont.name}_read();`);
865
- buildLibraryRestoreApplyCall(cont, 'Apply');
866
- if (coreDefinitions_1.DDE_Core.hasContainerAppFields(cont)) {
867
- pwn(`\t${buildUplinkApplyCall(cont.title)}`);
868
- }
869
- pwn(`\treturn(OK);`);
870
- pwn(`}`);
871
- }
872
- pwn(`#pragma warning push`);
873
- pwn(`stock _onUplinkApply(cfgId) {`);
874
- if (containerApply.length) {
875
- pwn(`\tswitch(cfgId) {`);
876
- for (const cont of containerApply) {
877
- pwn(`\t\tcase DDE_${cont.title}_id: return applyUplink${cont.name}(); // ${cont.name}`);
878
- }
879
- pwn(`\t}`);
880
- pwn(`\treturn ERROR;`);
881
- }
882
- else {
883
- pwn(`\t#pragma warning disable 203`);
884
- pwn(`\t// no containers to apply`);
885
- pwn(`\treturn OK;`);
886
- }
887
- pwn(`}`);
888
- pwn(`#pragma warning pop`);
889
- return _pwn.join('\n');
890
- }
891
- const ALL_CONFIG_WRITE_NAMES = CONFIG_CONTAINER.map(containerName => `_DDE_${containerName}_write`);
892
- function generateMainDDEIncFromMap(ddeMap) {
893
- const _pawnSource = [];
894
- const pawnSource = _pawnSource.push.bind(_pawnSource);
895
- const dummyWriteFunctions = [...ALL_CONFIG_WRITE_NAMES];
896
- for (const [containerName, containerDefinition] of Object.entries(ddeMap.containers)) {
897
- const cid_base = CONTAINER_DEF_DLO_CID_BASE(containerDefinition.containerType, containerDefinition.transferDirection);
898
- const CONTDEF = CONTAINER_DEFS[containerName];
899
- if (!cid_base || !containerDefinition.fields || CONTDEF.ctype !== ContainerType.cx) {
900
- //container is not available in dlo
901
- continue;
902
- }
903
- const pre = `DDE_${containerDefinition.name}`;
904
- const containerID = `DDE_${containerDefinition.title}_id`;
905
- // ---
906
- // add write method - but for configuration UP_ward containers only
907
- // ---
908
- if ([
909
- TransferDirection.both,
910
- TransferDirection.bothPlus,
911
- TransferDirection.none,
912
- TransferDirection.deviceOnly,
913
- TransferDirection.up,
914
- TransferDirection.upPlus
915
- ].includes(containerDefinition.transferDirection)) {
916
- const funcWrite = `_${pre}_write`;
917
- // pawnSource(`#define ${funcWrite}_def 01`);
918
- pawnSource(`stock ${funcWrite}() {`);
919
- pawnSource(`\tdde_wbegin(${containerID});`);
920
- generateMainDDEFunctionBody(pawnSource, containerDefinition, 'write');
921
- pawnSource(`\treturn dde_wend();`);
922
- pawnSource(`}`);
923
- // remove from dummy array
924
- dummyWriteFunctions.splice(dummyWriteFunctions.indexOf(funcWrite), 1);
925
- }
926
- // ---
927
- // add read method - but for CONFIG0-9 containers only
928
- // ---
929
- if (CONTDEF.ctype === ContainerType.cx) {
930
- const funcRead = `_${pre}_read`;
931
- pawnSource(`stock ${funcRead}() {`);
932
- pawnSource(`\tif (dde_rbegin(${containerID})) return ERROR;`);
933
- generateMainDDEFunctionBody(pawnSource, containerDefinition, 'read');
934
- pawnSource(`\tdde_rend();`);
935
- pawnSource('\treturn OK;');
936
- pawnSource(`}`);
937
- }
938
- }
939
- if (dummyWriteFunctions.length) {
940
- pawnSource('');
941
- pawnSource(`// Dummy functions needed by the dde library`);
942
- for (const dummyFunc of dummyWriteFunctions) {
943
- pawnSource(`stock ${dummyFunc}() { return OK; }`);
944
- }
945
- }
946
- return _pawnSource.join('\n');
947
- }
948
- function generateMainDDEFunctionBody(pawnSource, containerDefinition, readWrite) {
949
- containerDefinition.libraries.forEach(libraryName => {
950
- const libraryHash = helper_1.Helper.generateHashForLibraryName(libraryName);
951
- pawnSource(`\t#ifdef __${libraryHash}${containerDefinition.title}_${readWrite}`);
952
- pawnSource(`\t\t__${libraryHash}${containerDefinition.title}_${readWrite}();`);
953
- pawnSource(`\t#endif`);
954
- });
955
- if (coreDefinitions_1.DDE_Core.hasContainerAppFields(containerDefinition)) {
956
- pawnSource(`\t#ifdef _DDE_${containerDefinition.title}_${readWrite}`);
957
- pawnSource(`\t\t_DDE_${containerDefinition.title}_${readWrite}();`);
958
- pawnSource(`\t#endif`);
959
- }
960
- }
961
- /**
962
- * Default INC handling
963
- */
964
- /**
965
- * Generate the default.inc file
966
- * @param cwd
967
- * @param fs
968
- */
969
- async function buildDefaultInc(cwd, fs) {
970
- const fileContent = [];
971
- const dloLibs = await dependencies_1.Dependencies.getApmPartDependencies(cwd, fs, apm_1.APM.Part.dlo);
972
- await addInclude(cwd, fs, fileContent, defaultFiles_1.DefaultFiles.fileNames.autoInc);
973
- const autoDdeIncs = await getAutoDDEIncludes(cwd, fs, dloLibs);
974
- for (const dloLib of dloLibs) {
975
- // todo use relative path as include?
976
- if (dloLib.name === 'local-data-interface') {
977
- await addInclude(cwd, fs, fileContent, defaultFiles_1.DefaultFiles.fileNames.autoLocalDataInc);
978
- }
979
- fileContent.push(`#include <${dloLib.name}>`);
980
- if (dloLib.name === 'dlo-core') {
981
- fileContent.push(...autoDdeIncs);
982
- await addInclude(cwd, fs, fileContent, defaultFiles_1.DefaultFiles.fileNames.autoDdeInc.replace('X', 'app'));
983
- await addInclude(cwd, fs, fileContent, defaultFiles_1.DefaultFiles.fileNames.autoDdeInc.replace('X', 'main'));
984
- await addInclude(cwd, fs, fileContent, defaultFiles_1.DefaultFiles.fileNames.autoUplinkInc);
985
- }
986
- }
987
- return fileContent.join('\n');
988
- }
989
- /**
990
- * Get all <library-name>-dde.inc files
991
- * @param cwd
992
- * @param fs
993
- * @param dependencies
994
- */
995
- async function getAutoDDEIncludes(cwd, fs, dependencies) {
996
- const includes = [];
997
- for (const dependency of dependencies) {
998
- const includePath = defaultFiles_1.DefaultFiles.filePaths.studio.auto.dlo.autoDdeInc.replace('X', dependency.name);
999
- if (await fs.stat(vscode_uri_1.Utils.joinPath(cwd, includePath))) {
1000
- includes.push(`#include "${defaultFiles_1.DefaultFiles.fileNames.autoDdeInc.replace('X', dependency.name)}"`);
1001
- }
1002
- }
1003
- return includes;
1004
- }
1005
- /**
1006
- * Validate if the given file exist within the .studio/auto/dlo directory
1007
- */
1008
- async function addInclude(cwd, fs, fileContent, fileName) {
1009
- const basePath = vscode_uri_1.Utils.joinPath(cwd, defaultFiles_1.DefaultFiles.filePaths.studio.auto.dlo.path, fileName);
1010
- if (await fs.stat(basePath)) {
1011
- fileContent.push(`#include "${fileName}"`);
1012
- }
1013
- }
1014
- //# sourceMappingURL=dlo.js.map