650 lines
19 KiB
JavaScript
650 lines
19 KiB
JavaScript
import CloudLog from '../../logging/CloudLog';
|
|
import Signal from './signal';
|
|
import Frame from './frame';
|
|
import BoardUnit from './BoardUnit';
|
|
import DbcUtils from '../../utils/dbc';
|
|
|
|
const DBC_COMMENT_RE = /^CM_ *"(.*)";/;
|
|
const DBC_COMMENT_MULTI_LINE_RE = /^CM_ *"(.*)/;
|
|
|
|
const MSG_RE = /^BO_ (\w+) (\w+) *: (\w+) (\w+)/;
|
|
|
|
const SIGNAL_RE = /^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([+|-]) \(([0-9.+-eE]+),([0-9.+-eE]+)\) \[([0-9.+-eE]+)\|([0-9.+-eE]+)\] "(.*)" (.*)/;
|
|
// Multiplexed signal
|
|
const MP_SIGNAL_RE = /^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([+|-]) \(([0-9.+-eE]+),([0-9.+-eE]+)\) \[([0-9.+-eE]+)\|([0-9.+-eE]+)\] "(.*)" (.*)/;
|
|
|
|
const VAL_RE = /^VAL_ (\w+) (\w+) (.*);/;
|
|
const VAL_TABLE_RE = /^VAL_TABLE_ (\w+) (.*);/;
|
|
|
|
const MSG_TRANSMITTER_RE = /^BO_TX_BU_ ([0-9]+) *: *(.+);/;
|
|
|
|
const SIGNAL_COMMENT_RE = /^CM_ SG_ *(\w+) *(\w+) *"(.*)";/;
|
|
const SIGNAL_COMMENT_MULTI_LINE_RE = /^CM_ SG_ *(\w+) *(\w+) *"(.*)/;
|
|
|
|
// Message Comments (CM_ BO_ )
|
|
const MESSAGE_COMMENT_RE = /^CM_ BO_ *(\w+) *"(.*)";/;
|
|
const MESSAGE_COMMENT_MULTI_LINE_RE = /^CM_ BO_ *(\w+) *"(.*)/;
|
|
|
|
const BOARD_UNIT_RE = /^BU_:(.*)/;
|
|
const BOARD_UNIT_COMMENT_RE = /^CM_ BU_ *(\w+) *"(.*)";/;
|
|
const BOARD_UNIT_COMMENT_MULTI_LINE_RE = /^CM_ BU_ *(\w+) *"(.*)/;
|
|
|
|
// Follow ups are used to parse multi-line comment definitions
|
|
const FOLLOW_UP_DBC_COMMENT = 'FollowUpDbcComment';
|
|
const FOLLOW_UP_SIGNAL_COMMENT = 'FollowUpSignalComment';
|
|
const FOLLOW_UP_MSG_COMMENT = 'FollowUpMsgComment';
|
|
const FOLLOW_UP_BOARD_UNIT_COMMENT = 'FollowUpBoardUnitComment';
|
|
|
|
/* global BigInt */
|
|
|
|
function floatOrInt(numericStr) {
|
|
if (Number.isInteger(numericStr)) {
|
|
return parseInt(numericStr, 10);
|
|
}
|
|
return parseFloat(numericStr);
|
|
}
|
|
|
|
export function swapOrder(arr, wordSize, gSize) {
|
|
const swappedWords = [];
|
|
|
|
for (let i = 0; i < arr.length; i += wordSize) {
|
|
const word = arr.slice(i, i + wordSize);
|
|
for (let j = wordSize - gSize; j > -gSize; j -= gSize) {
|
|
swappedWords.push(word.slice(j, j + gSize));
|
|
}
|
|
}
|
|
|
|
return swappedWords.join('');
|
|
}
|
|
|
|
export default class DBC {
|
|
constructor(dbcString) {
|
|
this.boardUnits = [];
|
|
this.comments = [];
|
|
this.messages = new Map();
|
|
|
|
if (dbcString !== undefined) {
|
|
this.dbcText = dbcString;
|
|
this.importDbcString(dbcString);
|
|
}
|
|
}
|
|
|
|
getMessageFrame(address) {
|
|
return this.messages.get(address);
|
|
}
|
|
|
|
nextNewFrameName() {
|
|
const messageNames = [];
|
|
|
|
for (const msg of this.messages.values()) {
|
|
messageNames.push(msg.name);
|
|
}
|
|
|
|
let msgNum = 1;
|
|
let msgName;
|
|
do {
|
|
msgName = `NEW_MSG_${msgNum}`;
|
|
msgNum++;
|
|
} while (messageNames.indexOf(msgName) !== -1);
|
|
|
|
return msgName;
|
|
}
|
|
|
|
updateBoardUnits() {
|
|
const boardUnitNames = this.boardUnits.map((bu) => bu.name);
|
|
const missingBoardUnits = Array.from(this.messages.entries())
|
|
.map(([msgId, frame]) => Object.values(frame.signals))
|
|
.reduce((arr, signals) => arr.concat(signals), [])
|
|
.map((signal) => signal.receiver)
|
|
.reduce((arr, receivers) => arr.concat(receivers), [])
|
|
.filter((recv, idx, array) => array.indexOf(recv) === idx)
|
|
.filter((recv) => boardUnitNames.indexOf(recv) === -1)
|
|
.map((recv) => new BoardUnit(recv));
|
|
|
|
this.boardUnits = this.boardUnits.concat(missingBoardUnits);
|
|
}
|
|
|
|
text() {
|
|
this.updateBoardUnits();
|
|
|
|
let txt = 'VERSION ""\n\n\n';
|
|
txt += `NS_ :${this._newSymbols()}`;
|
|
txt += '\n\nBS_:\n';
|
|
|
|
const boardUnitsText = this.boardUnits.map((bu) => bu.text()).join(' ');
|
|
txt += `\nBU_: ${boardUnitsText}\n\n\n`;
|
|
|
|
const frames = [];
|
|
for (const frame of this.messages.values()) {
|
|
frames.push(frame);
|
|
}
|
|
txt += `${frames.map((f) => f.text()).join('\n\n')}\n\n`;
|
|
|
|
const messageTxs = frames
|
|
.map((f) => [f.id, f.transmitters.slice(1)])
|
|
.filter(([addr, txs]) => txs.length > 0);
|
|
txt += `${messageTxs
|
|
.map(([addr, txs]) => `BO_TX_BU_ ${addr} : ${txs.join(',')};`)
|
|
.join('\n')}\n\n\n`;
|
|
|
|
txt += this.boardUnits
|
|
.filter((bu) => bu.comment !== null)
|
|
.map((bu) => `CM_ BU_ ${bu.name} "${bu.comment}";`)
|
|
.join('\n');
|
|
|
|
txt += frames
|
|
.filter((f) => f.comment !== null)
|
|
.map((msg) => `CM_ BO_ ${msg.address} "${msg.comment}";`)
|
|
.join('\n');
|
|
|
|
const signalsByMsgId = frames
|
|
.map((f) => Object.values(f.signals).map((sig) => [f.id, sig]))
|
|
.reduce((s1, s2) => s1.concat(s2), []);
|
|
|
|
txt += `${signalsByMsgId
|
|
.filter(([msgAddr, sig]) => sig.comment !== null)
|
|
.map(
|
|
([msgAddr, sig]) => `CM_ SG_ ${msgAddr} ${sig.name} "${sig.comment}";`
|
|
)
|
|
.join('\n')}\n`;
|
|
|
|
txt += `${signalsByMsgId
|
|
.filter(([msgAddr, sig]) => sig.valueDescriptions.size > 0)
|
|
.map(([msgAddr, sig]) => sig.valueDescriptionText(msgAddr))
|
|
.join('\n')}\n`;
|
|
|
|
txt += this.comments.map((comment) => `CM_ "${comment}";`).join('\n');
|
|
|
|
return `${txt.trim()}\n`;
|
|
}
|
|
|
|
getMessageName(msgId) {
|
|
const msg = this.getMessageFrame(msgId);
|
|
if (msg && msg.frame) return msg.frame.name;
|
|
return null;
|
|
}
|
|
|
|
getSignals(msgId) {
|
|
const msg = this.getMessageFrame(msgId);
|
|
if (msg) return msg.signals;
|
|
return {};
|
|
}
|
|
|
|
createFrame(msgId, size=64) {
|
|
const msg = new Frame({
|
|
name: this.nextNewFrameName(),
|
|
id: msgId,
|
|
size: size,
|
|
});
|
|
|
|
this.messages.set(msgId, msg);
|
|
return msg;
|
|
}
|
|
|
|
setSignals(msgId, signals, frameSize) {
|
|
const msg = this.getMessageFrame(msgId); // TODO conform frameSize
|
|
if (msg) {
|
|
const newMsg = Object.assign(Object.create(msg), msg);
|
|
newMsg.signals = signals;
|
|
this.messages.set(msgId, newMsg);
|
|
} else {
|
|
const msg = this.createFrame(msgId, frameSize);
|
|
msg.signals = signals;
|
|
|
|
this.messages.set(msgId, msg);
|
|
this.updateBoardUnits();
|
|
}
|
|
}
|
|
|
|
addSignal(msgId, signal) {
|
|
const msg = this.getMessageFrame(msgId);
|
|
|
|
if (msg) {
|
|
msg.signals[signal.name] = signal;
|
|
this.updateBoardUnits();
|
|
}
|
|
}
|
|
|
|
importDbcString(dbcString) {
|
|
const warnings = [];
|
|
const messages = new Map();
|
|
let boardUnits = [];
|
|
const valueTables = new Map();
|
|
let id = 0;
|
|
let followUp = null;
|
|
|
|
const lines = dbcString.split('\n');
|
|
for (let i = 0; i < lines.length; i++) {
|
|
let line = lines[i].trim();
|
|
|
|
if (line.length === 0) continue;
|
|
|
|
if (followUp != null) {
|
|
const { type, data } = followUp;
|
|
line = line.replace(/" *;/, '');
|
|
let followUpLine = `\n${line.substr(0, line.length)}`;
|
|
if (line.indexOf('"') !== -1) {
|
|
followUp = null;
|
|
followUpLine = followUpLine.substr(0, followUpLine.length - 1);
|
|
}
|
|
if (type === FOLLOW_UP_SIGNAL_COMMENT) {
|
|
const signal = data;
|
|
signal.comment += followUpLine;
|
|
} else if (type === FOLLOW_UP_MSG_COMMENT) {
|
|
const msg = data;
|
|
msg.comment += followUpLine;
|
|
} else if (type === FOLLOW_UP_BOARD_UNIT_COMMENT) {
|
|
const boardUnit = data;
|
|
boardUnit.comment += followUpLine;
|
|
} else if (type === FOLLOW_UP_DBC_COMMENT) {
|
|
// const comment = data;
|
|
const partialComment = this.comments[this.comments.length - 1];
|
|
this.comments[this.comments.length - 1] = partialComment + followUpLine;
|
|
}
|
|
}
|
|
|
|
if (line.indexOf('BO_ ') === 0) {
|
|
const matches = line.match(MSG_RE);
|
|
if (matches === null) {
|
|
warnings.push(
|
|
`failed to parse message definition on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
let [idString, name, size, transmitter] = matches.slice(1);
|
|
id = parseInt(idString, 0); // 0 radix parses hex or dec
|
|
size = parseInt(size, 10);
|
|
const frame = new Frame({
|
|
name,
|
|
id,
|
|
size,
|
|
transmitters: [transmitter]
|
|
});
|
|
messages.set(id, frame);
|
|
} else if (line.indexOf('SG_') === 0) {
|
|
let matches = line.match(SIGNAL_RE);
|
|
|
|
if (matches === null) {
|
|
matches = line.match(MP_SIGNAL_RE);
|
|
if (matches === null) {
|
|
warnings.push(
|
|
`failed to parse signal definition on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
// for now, ignore multiplex which is matches[1]
|
|
matches = matches[1] + matches.slice(3);
|
|
} else {
|
|
matches = matches.slice(1);
|
|
}
|
|
|
|
let [
|
|
name,
|
|
startBit,
|
|
size,
|
|
isLittleEndian,
|
|
isSigned,
|
|
factor,
|
|
offset,
|
|
min,
|
|
max,
|
|
unit,
|
|
receiverStr
|
|
] = matches;
|
|
startBit = parseInt(startBit, 10);
|
|
size = parseInt(size, 10);
|
|
isLittleEndian = parseInt(isLittleEndian, 10) === 1;
|
|
isSigned = isSigned === '-';
|
|
factor = floatOrInt(factor);
|
|
offset = floatOrInt(offset);
|
|
min = floatOrInt(min);
|
|
max = floatOrInt(max);
|
|
const receiver = receiverStr.split(',').map((s) => s.trim());
|
|
|
|
const signalProperties = {
|
|
name,
|
|
startBit,
|
|
size,
|
|
isLittleEndian,
|
|
isSigned,
|
|
factor,
|
|
offset,
|
|
unit,
|
|
min,
|
|
max,
|
|
receiver
|
|
};
|
|
const signal = new Signal(signalProperties);
|
|
|
|
if (messages.get(id) !== undefined) {
|
|
messages.get(id).signals[name] = signal;
|
|
} else {
|
|
CloudLog.warn(
|
|
`importDbcString: could not add signal: ${name} due to missing message: ${id}`
|
|
);
|
|
}
|
|
} else if (line.indexOf('VAL_ ') === 0) {
|
|
const matches = line.match(VAL_RE);
|
|
|
|
if (matches !== null) {
|
|
let [messageId, signalName, vals] = matches.slice(1);
|
|
vals = vals
|
|
.split('"')
|
|
.map((s) => s.trim())
|
|
.filter((s) => s.length > 0);
|
|
|
|
messageId = parseInt(messageId, 10);
|
|
const msg = messages.get(messageId);
|
|
const signal = msg.signals[signalName];
|
|
if (signal === undefined) {
|
|
warnings.push(
|
|
`could not find signal for value description on line ${i
|
|
+ 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
for (let i = 0; i < vals.length; i += 2) {
|
|
const value = vals[i].trim();
|
|
const description = vals[i + 1].trim();
|
|
signal.valueDescriptions.set(value, description);
|
|
}
|
|
} else {
|
|
warnings.push(
|
|
`failed to parse value description on line ${i + 1} -- ${line}`
|
|
);
|
|
}
|
|
} else if (line.indexOf('VAL_TABLE_ ') === 0) {
|
|
const matches = line.match(VAL_TABLE_RE);
|
|
|
|
if (matches !== null) {
|
|
const table = new Map();
|
|
let [tableName, items] = matches.slice(1);
|
|
items = items
|
|
.split('"')
|
|
.map((s) => s.trim())
|
|
.filter((s) => s.length > 0);
|
|
|
|
for (let i = 0; i < items.length; i += 2) {
|
|
const key = items[i];
|
|
const value = items[i + 1];
|
|
table.set(key, value);
|
|
}
|
|
valueTables.set(tableName, table);
|
|
} else {
|
|
warnings.push(
|
|
`failed to parse value table on line ${i + 1} -- ${line}`
|
|
);
|
|
}
|
|
} else if (line.indexOf('BO_TX_BU_ ') === 0) {
|
|
const matches = line.match(MSG_TRANSMITTER_RE);
|
|
|
|
if (matches !== null) {
|
|
let [messageId, transmitter] = matches.slice(1);
|
|
messageId = parseInt(messageId, 10);
|
|
|
|
const msg = messages.get(messageId);
|
|
msg.transmitters.push(transmitter);
|
|
messages.set(messageId, msg);
|
|
} else {
|
|
warnings.push(
|
|
`failed to parse message transmitter definition on line ${i
|
|
+ 1} -- ${line}`
|
|
);
|
|
}
|
|
} else if (line.indexOf('CM_ SG_ ') === 0) {
|
|
let matches = line.match(SIGNAL_COMMENT_RE);
|
|
let hasFollowUp = false;
|
|
if (matches === null) {
|
|
matches = line.match(SIGNAL_COMMENT_MULTI_LINE_RE);
|
|
hasFollowUp = true;
|
|
}
|
|
if (matches === null) {
|
|
warnings.push(
|
|
`failed to parse signal comment on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
|
|
let [messageId, signalName, comment] = matches.slice(1);
|
|
|
|
messageId = parseInt(messageId, 10);
|
|
const msg = messages.get(messageId);
|
|
if (msg === undefined) {
|
|
warnings.push(`failed to parse signal comment on line ${i
|
|
+ 1} -- ${line}:
|
|
message id ${messageId} does not exist prior to this line`);
|
|
continue;
|
|
}
|
|
const signal = msg.signals[signalName];
|
|
if (signal === undefined) {
|
|
warnings.push(
|
|
`failed to parse signal comment on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
} else {
|
|
signal.comment = comment;
|
|
messages.set(messageId, msg);
|
|
}
|
|
|
|
if (hasFollowUp) {
|
|
followUp = { type: FOLLOW_UP_SIGNAL_COMMENT, data: signal };
|
|
}
|
|
} else if (line.indexOf('CM_ BO_ ') === 0) {
|
|
let matches = line.match(MESSAGE_COMMENT_RE);
|
|
let hasFollowUp = false;
|
|
if (matches === null) {
|
|
matches = line.match(MESSAGE_COMMENT_MULTI_LINE_RE);
|
|
hasFollowUp = true;
|
|
if (matches === null) {
|
|
warnings.push(
|
|
`failed to message comment on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
let [messageId, comment] = matches.slice(1);
|
|
messageId = parseInt(messageId, 10);
|
|
const msg = messages.get(messageId);
|
|
if (msg === undefined) {
|
|
warnings.push(
|
|
`failed to find message to add comment to, msg id: ${messageId}`
|
|
);
|
|
continue;
|
|
}
|
|
msg.comment = comment;
|
|
|
|
if (hasFollowUp) {
|
|
followUp = { type: FOLLOW_UP_MSG_COMMENT, data: msg };
|
|
}
|
|
} else if (line.indexOf('BU_: ') === 0) {
|
|
const matches = line.match(BOARD_UNIT_RE);
|
|
|
|
if (matches !== null) {
|
|
const [boardUnitNameStr] = matches.slice(1);
|
|
const newBoardUnits = boardUnitNameStr
|
|
.split(' ')
|
|
.map((s) => s.trim())
|
|
.filter((s) => s.length > 0)
|
|
.map((name) => new BoardUnit(name));
|
|
|
|
boardUnits = boardUnits.concat(newBoardUnits);
|
|
} else {
|
|
warnings.push(
|
|
`failed to parse board unit definition on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
} else if (line.indexOf('CM_ BU_ ') === 0) {
|
|
let matches = line.match(BOARD_UNIT_COMMENT_RE);
|
|
let hasFollowUp = false;
|
|
if (matches === null) {
|
|
matches = line.match(BOARD_UNIT_COMMENT_MULTI_LINE_RE);
|
|
hasFollowUp = true;
|
|
if (matches === null) {
|
|
warnings.push(
|
|
`failed to parse board unit comment on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
const [boardUnitName, comment] = matches.slice(1);
|
|
const boardUnit = boardUnits.find((bu) => bu.name === boardUnitName);
|
|
if (boardUnit) {
|
|
boardUnit.comment = comment;
|
|
}
|
|
|
|
if (hasFollowUp) {
|
|
followUp = { type: FOLLOW_UP_BOARD_UNIT_COMMENT, data: boardUnit };
|
|
}
|
|
} else if (line.indexOf('CM_ ') === 0) {
|
|
let matches = line.match(DBC_COMMENT_RE);
|
|
let hasFollowUp = false;
|
|
if (matches === null) {
|
|
matches = line.match(DBC_COMMENT_MULTI_LINE_RE);
|
|
if (matches === null) {
|
|
warnings.push(
|
|
`failed to parse dbc comment on line ${i + 1} -- ${line}`
|
|
);
|
|
continue;
|
|
} else {
|
|
hasFollowUp = true;
|
|
}
|
|
}
|
|
|
|
const [comment] = matches.slice(1);
|
|
this.comments.push(comment);
|
|
if (hasFollowUp) {
|
|
followUp = { type: FOLLOW_UP_DBC_COMMENT, data: comment };
|
|
}
|
|
}
|
|
}
|
|
|
|
// Disabled b/c live mode frequently calls this function
|
|
// and executes way too many network requests
|
|
if (warnings.length > 0) {
|
|
// warnings.forEach((warning) => CloudLog.warn('importDbcString: ' + warning));
|
|
// warnings.forEach((warning) => console.log('importDbcString: ' + warning));
|
|
}
|
|
|
|
this.messages = messages;
|
|
this.boardUnits = boardUnits;
|
|
this.valueTables = valueTables;
|
|
}
|
|
|
|
valueForIntSignal(signalSpec, view) {
|
|
let sig_lsb, sig_msb;
|
|
if (signalSpec.isLittleEndian) {
|
|
sig_lsb = signalSpec.startBit;
|
|
sig_msb = signalSpec.startBit + signalSpec.size - 1;
|
|
} else {
|
|
sig_lsb = DbcUtils.matrixBitNumber(DbcUtils.bigEndianBitIndex(signalSpec.startBit) + signalSpec.size - 1);
|
|
sig_msb = signalSpec.startBit;
|
|
}
|
|
|
|
let ret = signalSpec.size > 32 ? 0n : 0;
|
|
let i = Math.floor(sig_msb / 8);
|
|
let bits = signalSpec.size;
|
|
while (i >= 0 && i < view.byteLength && bits > 0) {
|
|
let lsb = Math.floor(sig_lsb / 8) === i ? sig_lsb : i*8;
|
|
let msb = Math.floor(sig_msb / 8) === i ? sig_msb : (i+1)*8 - 1;
|
|
let size = msb - lsb + 1;
|
|
|
|
let d = (view.getUint8(i) >>> (lsb - (i*8))) & ((1 << size) - 1);
|
|
if (signalSpec.size > 32) {
|
|
ret |= BigInt(d) << BigInt(bits - size);
|
|
} else {
|
|
ret |= d << (bits - size);
|
|
}
|
|
|
|
bits -= size;
|
|
i = signalSpec.isLittleEndian ? i-1 : i+1;
|
|
}
|
|
|
|
if (signalSpec.size > 32) {
|
|
ret = signalSpec.isSigned ? BigInt.asIntN(64, ret) : ret;
|
|
return ret * BigInt(signalSpec.factor) + BigInt(signalSpec.offset);
|
|
} else {
|
|
if (signalSpec.isSigned) {
|
|
ret -= ((ret >> (signalSpec.size-1)) & 1) ? (1 << signalSpec.size) : 0;
|
|
}
|
|
return ret * signalSpec.factor + signalSpec.offset;
|
|
}
|
|
}
|
|
|
|
getSignalValues(messageId, data) {
|
|
if (!this.messages.has(messageId)) {
|
|
return {};
|
|
}
|
|
const frame = this.getMessageFrame(messageId);
|
|
const view = new DataView(data.buffer);
|
|
const signalValuesByName = {};
|
|
Object.values(frame.signals).forEach((signalSpec) => {
|
|
if (isNaN(signalSpec.startBit)) {
|
|
return;
|
|
}
|
|
signalValuesByName[signalSpec.name] = this.valueForIntSignal(signalSpec, view);
|
|
});
|
|
|
|
return signalValuesByName;
|
|
}
|
|
|
|
getChffrMetricMappings() {
|
|
const metricComment = this.comments.find(
|
|
(comment) => comment.indexOf('CHFFR_METRIC') === 0
|
|
);
|
|
if (!metricComment) {
|
|
return null;
|
|
}
|
|
|
|
return metricComment
|
|
.split(';')
|
|
.map((metric) => metric.trim().split(' '))
|
|
.reduce(
|
|
(metrics, [_, messageId, signalName, metricName, factor, offset]) => {
|
|
metrics[metricName] = {
|
|
messageId: parseInt(messageId, 10),
|
|
signalName,
|
|
factor: parseFloat(factor),
|
|
offset: parseFloat(offset)
|
|
};
|
|
return metrics;
|
|
},
|
|
{}
|
|
);
|
|
}
|
|
|
|
_newSymbols() {
|
|
return `
|
|
NS_DESC_
|
|
CM_
|
|
BA_DEF_
|
|
BA_
|
|
VAL_
|
|
CAT_DEF_
|
|
CAT_
|
|
FILTER
|
|
BA_DEF_DEF_
|
|
EV_DATA_
|
|
ENVVAR_DATA_
|
|
SGTYPE_
|
|
SGTYPE_VAL_
|
|
BA_DEF_SGTYPE_
|
|
BA_SGTYPE_
|
|
SIG_TYPE_REF_
|
|
VAL_TABLE_
|
|
SIG_GROUP_
|
|
SIG_VALTYPE_
|
|
SIGTYPE_VALTYPE_
|
|
BO_TX_BU_
|
|
BA_DEF_REL_
|
|
BA_REL_
|
|
BA_DEF_DEF_REL_
|
|
BU_SG_REL_
|
|
BU_EV_REL_
|
|
BU_BO_REL_
|
|
SG_MUL_VAL_`;
|
|
}
|
|
}
|