Browse Source

cmDspPgmJsonToDot.h/c, Makefile : Initial working version of cmDspPgmJsonToDot

master
kevin 9 years ago
parent
commit
6c792e240d
3 changed files with 379 additions and 26 deletions
  1. 2
    2
      Makefile.am
  2. 370
    21
      app/cmDspPgmJsonToDot.c
  3. 7
    3
      app/cmDspPgmJsonToDot.h

+ 2
- 2
Makefile.am View File

@@ -77,8 +77,8 @@ cmSRC += src/libcm/cmProcObj.c src/libcm/cmProc.c src/libcm/cmProc2.c src/libcm/
77 77
 cmHDR += src/libcm/app/cmOnset.h src/libcm/app/cmTimeLine.h src/libcm/app/cmScore.h src/libcm/app/cmScoreProc.h 
78 78
 cmSRC += src/libcm/app/cmOnset.c src/libcm/app/cmTimeLine.c src/libcm/app/cmScore.c src/libcm/app/cmScoreProc.c 
79 79
 
80
-cmHDR += src/libcm/app/cmSdb.h  src/libcm/app/cmTakeSeqBldr.h
81
-cmSRC += src/libcm/app/cmSdb.c  src/libcm/app/cmTakeSeqBldr.c
80
+cmHDR += src/libcm/app/cmSdb.h  src/libcm/app/cmTakeSeqBldr.h  src/libcm/app/cmDspPgmJsonToDot.h
81
+cmSRC += src/libcm/app/cmSdb.c  src/libcm/app/cmTakeSeqBldr.c  src/libcm/app/cmDspPgmJsonToDot.c
82 82
 
83 83
 cmHDR += src/libcm/app/cmPickup.h src/libcm/cmRbm.h src/libcm/cmTaskMgr.h  src/libcm/cmSyncRecd.h
84 84
 cmSRC += src/libcm/app/cmPickup.c src/libcm/cmRbm.c src/libcm/cmTaskMgr.c  src/libcm/cmSyncRecd.c

+ 370
- 21
app/cmDspPgmJsonToDot.c View File

@@ -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 = &dot;
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
 }

+ 7
- 3
app/cmDspPgmJsonToDot.h View File

@@ -7,13 +7,17 @@ extern "C" {
7 7
 
8 8
   enum
9 9
   {
10
-    kOkDotRC,
11
-    kJsonFailDotRC
10
+    kOkDotRC = cmOkRC,
11
+    kJsonFailDotRC,
12
+    kJsonSyntaxErrDotRC,
13
+    kInvalidArgDotRC,
14
+    kLHeapFailDotRC,
15
+    kFileFailDotRC
12 16
   };
13 17
 
14 18
   typedef unsigned cmDotRC_t;
15 19
 
16
-  
20
+  cmDotRC_t cmDspPgmJsonToDot( cmCtx_t* ctx, const cmChar_t* inFn, const cmChar_t* outFn );
17 21
   
18 22
 #ifdef __cplusplus
19 23
 }

Loading…
Cancel
Save