|
@@ -1,85 +1,430 @@
|
|
1
|
+#include "cmPrefix.h"
|
|
2
|
+#include "cmGlobal.h"
|
|
3
|
+#include "cmFloatTypes.h"
|
|
4
|
+#include "cmComplexTypes.h"
|
|
5
|
+#include "cmRpt.h"
|
|
6
|
+#include "cmErr.h"
|
|
7
|
+#include "cmCtx.h"
|
|
8
|
+#include "cmMem.h"
|
|
9
|
+#include "cmMallocDebug.h"
|
|
10
|
+#include "cmLinkedHeap.h"
|
|
11
|
+#include "cmSymTbl.h"
|
|
12
|
+#include "cmJson.h"
|
|
13
|
+#include "cmText.h"
|
|
14
|
+#include "cmDspPgmJsonToDot.h"
|
|
15
|
+#include "cmFile.h"
|
|
16
|
+#include "cmFileSys.h"
|
|
17
|
+
|
|
18
|
+struct cmDotProc_str;
|
1
|
19
|
|
2
|
20
|
typedef struct cmDotPort_str
|
3
|
21
|
{
|
4
|
|
- cmChar_t* label;
|
|
22
|
+ struct cmDotProc_str* proc;
|
|
23
|
+ cmChar_t* labelStr;
|
|
24
|
+ unsigned portNo;
|
|
25
|
+ unsigned connCnt; // count of connections to this port
|
5
|
26
|
struct cmDotPort_str* link;
|
6
|
27
|
} cmDotPort_t;
|
7
|
28
|
|
8
|
29
|
typedef struct cmDotProc_str
|
9
|
30
|
{
|
10
|
|
- cmChar_t* class;
|
11
|
|
- cmChar_t* inst;
|
|
31
|
+ cmChar_t* classStr;
|
|
32
|
+ cmChar_t* instStr;
|
|
33
|
+ cmChar_t* outStr;
|
|
34
|
+ unsigned portCnt;
|
|
35
|
+ bool skipFl;
|
12
|
36
|
|
13
|
|
- cmDotPort_t* list;
|
|
37
|
+ cmDotPort_t* ports;
|
14
|
38
|
struct cmDotProc_str* link;
|
15
|
39
|
} cmDotProc_t;
|
16
|
40
|
|
|
41
|
+typedef struct cmDotConn_str
|
|
42
|
+{
|
|
43
|
+ cmDotPort_t* srcPort; // output
|
|
44
|
+ cmDotPort_t* dstPort; // input
|
|
45
|
+ bool skipFl;
|
|
46
|
+ struct cmDotConn_str* link;
|
|
47
|
+} cmDotConn_t;
|
|
48
|
+
|
|
49
|
+
|
17
|
50
|
typedef struct cmDot_str
|
18
|
51
|
{
|
19
|
|
- cmDotProc_t* list;
|
|
52
|
+ cmErr_t err;
|
|
53
|
+ cmLHeapH_t lH;
|
|
54
|
+ cmDotProc_t* procs;
|
|
55
|
+ cmDotConn_t* conns;
|
20
|
56
|
} cmDot_t;
|
21
|
57
|
|
|
58
|
+typedef struct
|
|
59
|
+{
|
|
60
|
+ const cmChar_t* s0;
|
|
61
|
+ const cmChar_t* s1;
|
|
62
|
+} cmDotSubst_t;
|
|
63
|
+
|
|
64
|
+cmDotSubst_t _cmDotSubstArray[] =
|
|
65
|
+{
|
|
66
|
+ { "Router", "Rtr" },
|
|
67
|
+ { "Scalar", "Sc" },
|
|
68
|
+ { "ScaleRange", "SR" },
|
|
69
|
+ { "MsgList", "ML" },
|
|
70
|
+ { "Button", "Btn" },
|
|
71
|
+ { "PortToSym", "PtS" },
|
|
72
|
+ { "1ofN", "lOfN"},
|
|
73
|
+ { NULL, NULL }
|
|
74
|
+};
|
|
75
|
+
|
|
76
|
+const cmChar_t* _cmDotSkipClassArray[] =
|
|
77
|
+{
|
|
78
|
+ "Scalar",
|
|
79
|
+ NULL
|
|
80
|
+};
|
|
81
|
+
|
|
82
|
+void _cmDotReplaceDash( cmChar_t* str )
|
|
83
|
+{
|
|
84
|
+ cmChar_t* s = str;
|
|
85
|
+ for(; *s; ++s )
|
|
86
|
+ if( *s == '-' )
|
|
87
|
+ *s = '_';
|
|
88
|
+}
|
|
89
|
+
|
|
90
|
+cmChar_t* _cmDotSubstitute( cmDot_t* p, const cmChar_t* label )
|
|
91
|
+{
|
|
92
|
+ unsigned i;
|
|
93
|
+ cmChar_t* s = cmLhAllocStr(p->lH,label);
|
|
94
|
+
|
|
95
|
+ for(i=0; _cmDotSubstArray[i].s0 != NULL; ++i)
|
|
96
|
+ {
|
|
97
|
+ unsigned n0 = cmTextLength(_cmDotSubstArray[i].s0);
|
|
98
|
+
|
|
99
|
+ if( cmTextCmpN( _cmDotSubstArray[i].s0, s, n0 ) == 0 )
|
|
100
|
+ {
|
|
101
|
+ unsigned n1 = cmTextLength(_cmDotSubstArray[i].s1);
|
|
102
|
+ assert(n0>=n1);
|
|
103
|
+ cmTextShrinkS(s,s+n1,n0-n1);
|
|
104
|
+ strncpy(s,_cmDotSubstArray[i].s1,n1);
|
|
105
|
+ }
|
|
106
|
+ }
|
|
107
|
+
|
|
108
|
+ return s;
|
|
109
|
+}
|
22
|
110
|
|
23
|
|
-void _cmDotNewProc( cmDot_t* p, const cmChar_t* class, const cmChar_t* inst )
|
|
111
|
+bool _cmDotIsSkipClass( const cmChar_t* classStr )
|
24
|
112
|
{
|
|
113
|
+ unsigned i;
|
|
114
|
+
|
|
115
|
+ for(i=0; _cmDotSkipClassArray[i]!=NULL; ++i)
|
|
116
|
+ if( cmTextCmp(_cmDotSkipClassArray[i],classStr) == 0 )
|
|
117
|
+ return true;
|
25
|
118
|
|
|
119
|
+ return false;
|
26
|
120
|
}
|
27
|
121
|
|
28
|
|
-void _cmDotNewPort( cmDot_t* p, const cmChar_t* srcStr, const cmChar_t* srcPortStr, const cmChar_t* dstStr, const cmChar_t* dstPortStr )
|
|
122
|
+cmDotPort_t* _cmDotFindPort( cmDotProc_t* proc, const cmChar_t* labelStr )
|
29
|
123
|
{
|
|
124
|
+ cmDotPort_t* port = proc->ports;
|
|
125
|
+ for(; port!=NULL; port=port->link)
|
|
126
|
+ if( cmTextCmp(port->labelStr,labelStr) == 0 )
|
|
127
|
+ return port;
|
|
128
|
+
|
|
129
|
+ return NULL;
|
30
|
130
|
}
|
31
|
131
|
|
|
132
|
+cmDotProc_t* _cmDotFindProc( cmDot_t* p, const cmChar_t* instStr )
|
|
133
|
+{
|
|
134
|
+ cmDotProc_t* dp = p->procs;
|
|
135
|
+ for(; dp!=NULL; dp=dp->link)
|
|
136
|
+ if( cmTextCmp(dp->instStr,instStr) == 0 )
|
|
137
|
+ return dp;
|
32
|
138
|
|
33
|
|
-cmDotRC_t cmDspPgmJsonToDot( cmCtx_t* ctx, const cmChar_t* inFn, const cmChar_t* outFn )
|
|
139
|
+ return NULL;
|
|
140
|
+}
|
|
141
|
+
|
|
142
|
+cmDotPort_t* _cmDotNewPort( cmDot_t* p, cmDotProc_t* proc, const cmChar_t* labelStr )
|
|
143
|
+{
|
|
144
|
+ cmDotPort_t* port = NULL;
|
|
145
|
+
|
|
146
|
+ if( labelStr==NULL || cmTextLength(labelStr)==0 )
|
|
147
|
+ {
|
|
148
|
+ cmErrMsg(&p->err,kInvalidArgDotRC,"A blank port label was encountered.");
|
|
149
|
+ return NULL;
|
|
150
|
+ }
|
|
151
|
+
|
|
152
|
+ if((port = _cmDotFindPort(proc,labelStr)) != NULL )
|
|
153
|
+ return port;
|
|
154
|
+
|
|
155
|
+ port = cmLhAllocZ(p->lH,cmDotPort_t,1);
|
|
156
|
+
|
|
157
|
+ port->proc = proc;
|
|
158
|
+ port->labelStr = cmLhAllocStr(p->lH,labelStr);
|
|
159
|
+ port->portNo = proc->portCnt;
|
|
160
|
+
|
|
161
|
+ proc->portCnt += 1;
|
|
162
|
+
|
|
163
|
+ cmDotPort_t* p0 = NULL;
|
|
164
|
+ cmDotPort_t* p1 = proc->ports;
|
|
165
|
+ for(; p1!=NULL; p1=p1->link)
|
|
166
|
+ p0 = p1;
|
|
167
|
+
|
|
168
|
+ if( p0 == NULL )
|
|
169
|
+ proc->ports = port;
|
|
170
|
+ else
|
|
171
|
+ p0->link = port;
|
|
172
|
+
|
|
173
|
+ return port;
|
|
174
|
+}
|
|
175
|
+
|
|
176
|
+cmDotRC_t _cmDotNewConnection( cmDot_t* p, const cmChar_t* srcProcStr, const cmChar_t* srcPortStr, const cmChar_t* dstProcStr, const cmChar_t* dstPortStr )
|
|
177
|
+{
|
|
178
|
+ cmDotRC_t rc = kOkDotRC;
|
|
179
|
+ cmDotProc_t* srcProc;
|
|
180
|
+ cmDotProc_t* dstProc;
|
|
181
|
+ cmDotPort_t* srcPort;
|
|
182
|
+ cmDotPort_t* dstPort;
|
|
183
|
+ cmDotConn_t* conn;
|
|
184
|
+ cmDotConn_t* c0 = NULL;
|
|
185
|
+ cmDotConn_t* c1 = p->conns;
|
|
186
|
+
|
|
187
|
+ // find the source (output) proc
|
|
188
|
+ if((srcProc = _cmDotFindProc(p,srcProcStr)) == NULL )
|
|
189
|
+ {
|
|
190
|
+ rc = cmErrMsg(&p->err,kInvalidArgDotRC,"The connection source proc instance '%s' could not be found.",cmStringNullGuard(srcProcStr));
|
|
191
|
+ goto errLabel;
|
|
192
|
+ }
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+ // find the dest (input) proc
|
|
196
|
+ if((dstProc = _cmDotFindProc(p,dstProcStr)) == NULL )
|
|
197
|
+ {
|
|
198
|
+ rc = cmErrMsg(&p->err,kInvalidArgDotRC,"The connection destination proc instance '%s' could not be found.",cmStringNullGuard(dstProcStr));
|
|
199
|
+ goto errLabel;
|
|
200
|
+ }
|
|
201
|
+
|
|
202
|
+ // find the source port
|
|
203
|
+ if((srcPort = _cmDotNewPort(p,srcProc,srcPortStr)) == NULL )
|
|
204
|
+ {
|
|
205
|
+ rc = cmErrMsg(&p->err,kInvalidArgDotRC,"The source port %s:%s could not be found or allocated.",cmStringNullGuard(srcProc->instStr),cmStringNullGuard(srcPortStr));
|
|
206
|
+ goto errLabel;
|
|
207
|
+ }
|
|
208
|
+
|
|
209
|
+ // find the dest port
|
|
210
|
+ if((dstPort = _cmDotNewPort(p,dstProc,dstPortStr)) == NULL )
|
|
211
|
+ {
|
|
212
|
+ rc = cmErrMsg(&p->err,kInvalidArgDotRC,"The destination port %s:%s could not be found or allocated.",cmStringNullGuard(dstProc->instStr),cmStringNullGuard(dstPortStr));
|
|
213
|
+ goto errLabel;
|
|
214
|
+ }
|
|
215
|
+
|
|
216
|
+ conn = cmLhAllocZ(p->lH,cmDotConn_t,1);
|
|
217
|
+
|
|
218
|
+ conn->srcPort = srcPort;
|
|
219
|
+ conn->dstPort = dstPort;
|
|
220
|
+ conn->skipFl = _cmDotIsSkipClass(srcProc->classStr) || _cmDotIsSkipClass(dstProc->classStr);
|
|
221
|
+
|
|
222
|
+ // track the number of connections to each port
|
|
223
|
+ if( !conn->skipFl )
|
|
224
|
+ {
|
|
225
|
+ conn->dstPort->connCnt += 1;
|
|
226
|
+ conn->srcPort->connCnt += 1;
|
|
227
|
+ }
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+ // set c0 to point to the last connection record
|
|
231
|
+ for(; c1!=NULL; c1=c1->link)
|
|
232
|
+ c0 = c1;
|
|
233
|
+
|
|
234
|
+ // make conn the last connection record
|
|
235
|
+ if( c0 == NULL )
|
|
236
|
+ p->conns = conn;
|
|
237
|
+ else
|
|
238
|
+ c0->link = conn;
|
|
239
|
+
|
|
240
|
+ errLabel:
|
|
241
|
+ return rc;
|
|
242
|
+}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+cmDotRC_t _cmDotNewProc( cmDot_t* p, const cmChar_t* classStr, const cmChar_t* instStr )
|
|
246
|
+{
|
|
247
|
+ cmDotRC_t rc = kOkDotRC;
|
|
248
|
+
|
|
249
|
+ if( instStr==NULL || cmTextLength(instStr)==0 )
|
|
250
|
+ return cmErrMsg(&p->err,kInvalidArgDotRC,"A blank or NULL instance label was encountered.");
|
|
251
|
+
|
|
252
|
+ if( _cmDotFindProc( p, instStr ) )
|
|
253
|
+ return cmErrMsg(&p->err,kInvalidArgDotRC,"A duplicate processor instance was encountered ('%s').",instStr);
|
|
254
|
+
|
|
255
|
+ cmDotProc_t* ndp = cmLhAllocZ(p->lH,cmDotProc_t,1);
|
|
256
|
+
|
|
257
|
+ ndp->classStr = cmLhAllocStr(p->lH,classStr);
|
|
258
|
+ ndp->instStr = cmLhAllocStr(p->lH,instStr);
|
|
259
|
+ ndp->outStr = _cmDotSubstitute(p,instStr);
|
|
260
|
+ ndp->skipFl = _cmDotIsSkipClass(classStr);
|
|
261
|
+
|
|
262
|
+ cmDotProc_t* d0p = NULL;
|
|
263
|
+ cmDotProc_t* d1p = p->procs;
|
|
264
|
+
|
|
265
|
+ for(; d1p!=NULL; d1p=d1p->link )
|
|
266
|
+ d0p = d1p;
|
|
267
|
+
|
|
268
|
+ if( d0p == NULL )
|
|
269
|
+ p->procs = ndp;
|
|
270
|
+ else
|
|
271
|
+ d0p->link = ndp;
|
|
272
|
+
|
|
273
|
+ return rc;
|
|
274
|
+}
|
|
275
|
+
|
|
276
|
+unsigned _cmDotProcConnCount( cmDotProc_t* proc )
|
34
|
277
|
{
|
35
|
|
- cmDotRC_t rc = kOkDotRC;
|
36
|
|
- cmJsonH_t jsH = cmJsonNullHandle;
|
37
|
|
- cmErr_t err;
|
38
|
|
- cmJsonNode_t* arr;
|
39
|
|
- cmJsonNode_t* rp;
|
40
|
|
- const char* errLbl = NULL;
|
|
278
|
+ unsigned connN = 0;
|
41
|
279
|
|
42
|
|
- cmErrSetup(&err,&ctx->rpt,"cmDspPgmJsonToDot");
|
|
280
|
+ cmDotPort_t* port = proc->ports;
|
|
281
|
+ for(; port!=NULL; port=port->link)
|
|
282
|
+ connN += port->connCnt;
|
|
283
|
+
|
|
284
|
+ return connN;
|
|
285
|
+}
|
|
286
|
+
|
|
287
|
+cmDotRC_t _cmDotWriteOutput( cmDot_t* p, const cmChar_t* outFn )
|
|
288
|
+{
|
|
289
|
+ cmDotRC_t rc = kOkDotRC;
|
|
290
|
+
|
|
291
|
+ cmFileH_t fH = cmFileNullHandle;
|
|
292
|
+
|
|
293
|
+ cmFileSysPathPart_t* pathParts = cmFsPathParts(outFn);
|
|
294
|
+ const cmChar_t* fn = NULL;
|
43
|
295
|
|
|
296
|
+ if( pathParts == NULL )
|
|
297
|
+ {
|
|
298
|
+ rc = cmErrMsg(&p->err,kFileFailDotRC,"The output file name '%s' could be parsed.",cmStringNullGuard(outFn));
|
|
299
|
+ goto errLabel;
|
|
300
|
+ }
|
|
301
|
+
|
|
302
|
+ if((fn = cmFsMakeFn( pathParts->dirStr, pathParts->fnStr, "dot", NULL )) == NULL )
|
|
303
|
+ {
|
|
304
|
+ rc = cmErrMsg(&p->err,kFileFailDotRC,"The output file name could not be formed.");
|
|
305
|
+ goto errLabel;
|
|
306
|
+ }
|
|
307
|
+
|
|
308
|
+ if( cmFileOpen(&fH,fn,kWriteFileFl,p->err.rpt) != kOkFileRC )
|
|
309
|
+ {
|
|
310
|
+ rc = cmErrMsg(&p->err,kFileFailDotRC,"The output file '%s' could not be created.",cmStringNullGuard(outFn));
|
|
311
|
+ goto errLabel;
|
|
312
|
+ }
|
|
313
|
+
|
|
314
|
+ cmFilePrintf(fH,"digraph dsppgm\n{\n node [shape=record]\n");
|
|
315
|
+
|
|
316
|
+ cmDotProc_t* proc = p->procs;
|
|
317
|
+ for(; proc!=NULL; proc=proc->link )
|
|
318
|
+ if( proc->skipFl==false && _cmDotProcConnCount(proc)>0 )
|
|
319
|
+ {
|
|
320
|
+ cmFilePrintf(fH,"\"%s\" [label=\"<n> %s",proc->outStr,proc->outStr);
|
|
321
|
+
|
|
322
|
+ cmDotPort_t* port = proc->ports;
|
|
323
|
+ for(; port!=NULL; port=port->link)
|
|
324
|
+ if( port->connCnt > 0 )
|
|
325
|
+ cmFilePrintf(fH,"|<p%i> %s",port->portNo,port->labelStr);
|
|
326
|
+
|
|
327
|
+ cmFilePrintf(fH,"\"];\n");
|
|
328
|
+ }
|
|
329
|
+
|
|
330
|
+ cmDotConn_t* c = p->conns;
|
|
331
|
+ for(; c!=NULL; c=c->link)
|
|
332
|
+ if( !c->skipFl )
|
|
333
|
+ {
|
|
334
|
+ cmFilePrintf(fH,"\"%s\":p%i -> \"%s\":p%i;\n",
|
|
335
|
+ c->srcPort->proc->outStr,c->srcPort->portNo,
|
|
336
|
+ c->dstPort->proc->outStr,c->dstPort->portNo );
|
|
337
|
+ }
|
|
338
|
+
|
|
339
|
+ cmFilePrintf(fH,"}\n");
|
|
340
|
+
|
|
341
|
+ errLabel:
|
|
342
|
+ cmFileClose(&fH);
|
|
343
|
+ cmFsFreeFn(fn);
|
|
344
|
+ cmFsFreePathParts(pathParts);
|
|
345
|
+ return rc;
|
|
346
|
+}
|
|
347
|
+
|
|
348
|
+cmDotRC_t cmDspPgmJsonToDot( cmCtx_t* ctx, const cmChar_t* inFn, const cmChar_t* outFn )
|
|
349
|
+{
|
|
350
|
+ cmDotRC_t rc = kOkDotRC;
|
|
351
|
+ cmJsonH_t jsH = cmJsonNullHandle;
|
|
352
|
+ cmJsonNode_t* arr = NULL;
|
|
353
|
+ cmJsonNode_t* rp = NULL;
|
|
354
|
+ const char* errLbl = NULL;
|
|
355
|
+ cmDot_t dot;
|
|
356
|
+ unsigned i;
|
|
357
|
+ cmDot_t* p = ˙
|
|
358
|
+
|
|
359
|
+ memset(p,0,sizeof(dot));
|
|
360
|
+
|
|
361
|
+ cmErrSetup(&p->err,&ctx->rpt,"cmDspPgmJsonToDot");
|
|
362
|
+
|
|
363
|
+ // open the pgm description json file
|
44
|
364
|
if( cmJsonInitializeFromFile( &jsH, inFn, ctx ) != kOkJsRC )
|
45
|
|
- return cmErrMsg(&err,kJsonFailDotRC,"The program description file '%s' could not be opened.",cmStringNullGuard(inFn));
|
|
365
|
+ return cmErrMsg(&p->err,kJsonFailDotRC,"The program description file '%s' could not be opened.",cmStringNullGuard(inFn));
|
|
366
|
+
|
|
367
|
+ // create an lheap to hold internal data objects
|
|
368
|
+ if(cmLHeapIsValid( p->lH = cmLHeapCreate( 8192, ctx))==false )
|
|
369
|
+ {
|
|
370
|
+ rc = cmErrMsg(&p->err,kLHeapFailDotRC,"The internal LHeap could not be created.");
|
|
371
|
+ goto errLabel;
|
|
372
|
+ }
|
46
|
373
|
|
|
374
|
+ // locate the proc instance desc. array in the JSON tree
|
47
|
375
|
if((arr = cmJsonFindValue(jsH, "inst_array", NULL, kArrayTId )) == NULL )
|
48
|
376
|
{
|
|
377
|
+ rc = cmErrMsg(&p->err,kJsonSyntaxErrDotRC,"The 'inst_array' tag was not found.");
|
|
378
|
+ goto errLabel;
|
49
|
379
|
}
|
50
|
380
|
|
|
381
|
+ // get a count of proc instances
|
51
|
382
|
unsigned n = cmJsonChildCount(arr);
|
52
|
|
-
|
|
383
|
+
|
|
384
|
+ // parse each proc instance
|
53
|
385
|
for(i=0; i<n; ++i)
|
54
|
386
|
{
|
55
|
387
|
|
56
|
388
|
if((rp = cmJsonArrayElement(arr,i)) == NULL )
|
57
|
389
|
{
|
|
390
|
+ rc = cmErrMsg(&p->err,kJsonSyntaxErrDotRC,"The 'inst_array' element %i was not found.",i);
|
|
391
|
+ goto errLabel;
|
58
|
392
|
}
|
59
|
393
|
|
60
|
394
|
cmChar_t* classStr = NULL;
|
61
|
395
|
cmChar_t* instStr = NULL;
|
62
|
396
|
if( cmJsonMemberValues(rp, &errLbl,
|
63
|
397
|
"class", kStringTId, &classStr,
|
64
|
|
- "label", kStringTId, &instStr
|
|
398
|
+ "label", kStringTId, &instStr,
|
65
|
399
|
NULL ) != kOkJsRC )
|
66
|
400
|
{
|
|
401
|
+ rc = cmErrMsg(&p->err,kJsonSyntaxErrDotRC,"The 'inst_array' element %i parse failed.",i);
|
|
402
|
+ goto errLabel;
|
67
|
403
|
}
|
68
|
404
|
|
|
405
|
+ // create a proc instance data record
|
69
|
406
|
_cmDotNewProc( p, classStr, instStr );
|
70
|
407
|
|
71
|
408
|
}
|
72
|
409
|
|
|
410
|
+ // locate the connection desc array in the JSON tree
|
73
|
411
|
if((arr = cmJsonFindValue(jsH, "conn_array", NULL, kArrayTId)) == NULL )
|
74
|
412
|
{
|
|
413
|
+ rc = cmErrMsg(&p->err,kJsonSyntaxErrDotRC,"The 'conn_array' tag was not found.");
|
|
414
|
+ goto errLabel;
|
75
|
415
|
}
|
76
|
416
|
|
77
|
|
- unsigned n = cmJsonChildCount(arr);
|
|
417
|
+ // get a count of the connections
|
|
418
|
+ n = cmJsonChildCount(arr);
|
78
|
419
|
|
|
420
|
+ // for each connection
|
79
|
421
|
for(i=0; i<n; ++i)
|
80
|
422
|
{
|
|
423
|
+
|
81
|
424
|
if((rp = cmJsonArrayElement(arr,i)) == NULL )
|
82
|
425
|
{
|
|
426
|
+ rc = cmErrMsg(&p->err,kJsonSyntaxErrDotRC,"The 'conn_array' element %i was not found.",i);
|
|
427
|
+ goto errLabel;
|
83
|
428
|
}
|
84
|
429
|
|
85
|
430
|
cmChar_t* srcStr = NULL;
|
|
@@ -94,17 +439,21 @@ cmDotRC_t cmDspPgmJsonToDot( cmCtx_t* ctx, const cmChar_t* inFn, const cmChar_t*
|
94
|
439
|
"dvar", kStringTId, &dstPortStr,
|
95
|
440
|
NULL) != kOkJsRC )
|
96
|
441
|
{
|
|
442
|
+ rc = cmErrMsg(&p->err,kJsonSyntaxErrDotRC,"The 'conn_array' element %i parse failed.",i);
|
|
443
|
+ goto errLabel;
|
97
|
444
|
}
|
98
|
445
|
|
99
|
|
- _cmDotNewPort( p, srcStr, srcPortStr, dstStr, dstPortStr );
|
100
|
|
-
|
|
446
|
+ // create a connection data record
|
|
447
|
+ _cmDotNewConnection( p, srcStr, srcPortStr, dstStr, dstPortStr );
|
101
|
448
|
|
102
|
449
|
}
|
103
|
450
|
|
|
451
|
+ rc = _cmDotWriteOutput(p, outFn );
|
104
|
452
|
|
105
|
453
|
|
106
|
454
|
errLabel:
|
107
|
455
|
cmJsonFinalize(&jsH);
|
|
456
|
+ cmLHeapDestroy(&p->lH);
|
108
|
457
|
|
109
|
458
|
return rc;
|
110
|
459
|
}
|