Browse Source

Added cmTextTemplate.c/h

master
kpl 12 years ago
parent
commit
0927f05ec2
2 changed files with 398 additions and 0 deletions
  1. 373
    0
      cmTextTemplate.c
  2. 25
    0
      cmTextTemplate.h

+ 373
- 0
cmTextTemplate.c View File

1
+#include "cmPrefix.h"
2
+#include "cmGlobal.h"
3
+#include "cmRpt.h"
4
+#include "cmErr.h"
5
+#include "cmCtx.h"
6
+#include "cmMem.h"
7
+#include "cmMallocDebug.h"
8
+#include "cmLinkedHeap.h"
9
+#include "cmText.h"
10
+#include "cmFile.h"
11
+#include "cmTextTemplate.h"
12
+
13
+/*
14
+  $var$      // global var
15
+
16
+  ${name$ $var0$ $var1$ $}$   // name.var0 name.var1 
17
+
18
+  ${name$ $var0$ $var1$ $}$   // name.var0 name.var1 
19
+
20
+
21
+  replace(tpl,"val","var0")               // var0 = val
22
+  replace(tpl,"val","name","var0",NULL)   // name.var0 = val          - named assignment
23
+  replace(tpl,"val0","val0","name")       // name.0=val0; name.1=val1 - place assignment
24
+  repeat(  tpl, "name" )                  // create a copy of "name" just after name
25
+  clean(   tpl, "name" )                  // remove unused variables from "name"
26
+*/
27
+
28
+
29
+cmTtH_t cmTtNullHandle = cmSTATIC_NULL_HANDLE;
30
+
31
+enum
32
+{
33
+  kVarTtId,   // variable node
34
+  kValTtId,   // value (leaf) node
35
+  kTextTtId   // text
36
+};
37
+
38
+typedef struct cmTtToken_str
39
+{
40
+  unsigned              typeId;
41
+  cmChar_t*             text;
42
+  cmChar_t*             end;
43
+  struct cmTtToken_str* next;
44
+  struct cmTtToken_str* prev;
45
+} cmTtToken_t;
46
+
47
+typedef struct cmTtNode_str
48
+{
49
+  unsigned             typeId;
50
+  cmChar_t*            label;
51
+  cmTtToken_t*         token;
52
+  struct cmTtNode_str* parent;
53
+  struct cmTtNode_str* children;
54
+  struct cmTtNode_str* sibling;
55
+} cmTtNode_t;
56
+
57
+typedef struct
58
+{
59
+  cmErr_t      err;
60
+  cmLHeapH_t   lhH;
61
+  cmChar_t*    buf;
62
+  cmChar_t*    fn;
63
+  cmTtNode_t*  tree;
64
+  cmTtToken_t* tokens;
65
+} cmTt_t;
66
+
67
+cmTt_t* _cmTtHandleToPtr( cmTtH_t h )
68
+{
69
+  cmTt_t* p = (cmTt_t*)h.h;
70
+  assert( p != NULL );
71
+  return p;
72
+}
73
+
74
+cmTtRC_t _cmTtFinalize( cmTt_t* p )
75
+{
76
+  cmTtRC_t rc = kOkTtRC;
77
+  if( p == NULL )
78
+    return rc;
79
+
80
+  cmLHeapDestroy(&p->lhH);
81
+  cmMemPtrFree(&p->buf);
82
+  cmMemFree(p);
83
+  return rc;
84
+}
85
+
86
+cmTtToken_t*  _cmTtCreateToken( cmTt_t* p, unsigned typeId, cmChar_t* s0, cmChar_t* s1 )
87
+{
88
+  cmTtToken_t* tp = p->tokens;
89
+  cmTtToken_t* t = cmLhAllocZ(p->lhH,cmTtToken_t,1);
90
+  t->typeId      = kVarTtId;
91
+  t->text        = s0;
92
+  t->end         = s1;
93
+  
94
+  if( tp == NULL )
95
+    p->tokens = t;
96
+  else
97
+  {
98
+    while( tp->next!=NULL )
99
+      tp=tp->next;
100
+      
101
+    tp->next = t;
102
+    t->prev  = tp;
103
+  }
104
+
105
+  return tp;
106
+}
107
+
108
+
109
+cmTtRC_t  _cmTtScan( cmTt_t* p, cmChar_t* s)
110
+{
111
+  enum { kBeg, kEnd, kQuote };
112
+
113
+  cmTtRC_t  rc    = kOkTtRC;
114
+  unsigned  i     = 0;
115
+  unsigned  line  = 1;
116
+  unsigned  state = kBeg;
117
+  cmChar_t* s0    = s;
118
+
119
+  for(; rc==kOkTtRC && s[i]; ++i)
120
+  {
121
+    cmChar_t c = s[i];
122
+
123
+    if( c == '\n')
124
+      ++line;
125
+
126
+    switch(state)
127
+    {
128
+      case kBeg:  // searching for begin '$'
129
+        switch( c )
130
+        {
131
+          case '$':
132
+            {
133
+              _cmTtCreateToken(p,kTextTtId,s0,s+i-1);          
134
+              state = kEnd;
135
+              s0    = s + i;
136
+            }
137
+            break;
138
+
139
+          case '"':
140
+            state = kQuote;
141
+            break;
142
+        }
143
+
144
+      case kEnd:  // searching for end '$'
145
+        switch(c)
146
+        {
147
+          case '$':
148
+            {
149
+              _cmTtCreateToken(p,kVarTtId,s0,s+i);
150
+              state = kBeg;
151
+              s0    = s + i + 1;
152
+            }
153
+            break;
154
+
155
+          case '\n':
156
+            rc = cmErrMsg(&p->err,kSyntaxErrTtRC,"A end-of-line was encountered inside a template variable on line %i in '%s'.",line,p->fn);
157
+            break;
158
+
159
+          case '"':
160
+            rc = cmErrMsg(&p->err,kSyntaxErrTtRC,"A double-quote character was found inside a template variable on line %i in '%s'.",line,p->fn);
161
+            break;
162
+        }
163
+        break;
164
+
165
+      case kQuote: // searching for '"'
166
+        switch(c)
167
+        {
168
+          case '"':   
169
+            state = kBeg; 
170
+            break;
171
+
172
+          case '\n':
173
+            rc = cmErrMsg(&p->err,kSyntaxErrTtRC,"A double-quote character was found inside a quoted string on line %i in '%s'.",line,p->fn);
174
+            break;
175
+        }
176
+        break;
177
+
178
+      default:
179
+        { assert(0); }
180
+    }
181
+  }
182
+
183
+  return rc;
184
+}
185
+
186
+bool _cmTtTokenIsBegin( cmTtToken_t* tp ) 
187
+{ 
188
+  assert(tp->text!=NULL && tp->text[0]=='$'); 
189
+  return tp->typeId==kVarTtId && tp->text[1]=='{'; 
190
+}
191
+
192
+bool _cmTtTokenIsEnd( cmTtToken_t* tp ) 
193
+{ 
194
+  assert(tp->text!=NULL && tp->text[0]=='$'); 
195
+  return tp->typeId==kVarTtId && tp->text[1]=='}'; 
196
+}
197
+
198
+cmTtNode_t* _cmTtCreateNode( cmTt_t* p, cmTtNode_t* parent, unsigned typeId, cmTtToken_t* tp )
199
+{
200
+  cmTtNode_t* nnp = cmLhAllocZ(p->lhH,cmTtNode_t,1);
201
+  nnp->typeId = typeId;
202
+  nnp->token  = tp;
203
+  nnp->parent = parent;
204
+  
205
+  if( parent != NULL )
206
+  {
207
+    if( parent->children == NULL )
208
+      parent->children = nnp;
209
+    else
210
+    {
211
+      cmTtNode_t* np = nnp->children;
212
+      while( np->sibling != NULL )
213
+        np=np->sibling;
214
+      
215
+      np->sibling = nnp;
216
+    }
217
+  }
218
+
219
+  return nnp;
220
+}
221
+
222
+cmTtToken_t*  _cmTtBuildTree( cmTt_t* p, cmTtNode_t* np, cmTtToken_t* tp )
223
+{
224
+  cmTtToken_t* ftp = tp;
225
+  int          cnt = 0;
226
+  while( tp != NULL )
227
+  {
228
+    if( _cmTtTokenIsBegin(tp) )
229
+    {      
230
+      // attach preceding text to new right-most leaf-node on 'np'.
231
+      _cmTtCreateNode(p,np,kTextTtId,ftp); 
232
+
233
+      // break the token chain before the 'begin' token
234
+      if( tp->prev != NULL )
235
+        tp->prev->next = NULL;
236
+      tp->prev = NULL;
237
+      
238
+      // create a new child variable node and advance to token string
239
+      tp  = _cmTtBuildTree(p, _cmTtCreateNode(p,np,kVarTtId,NULL), tp->next );
240
+      ftp = tp;
241
+      ++cnt;
242
+    }
243
+
244
+    
245
+    if( _cmTtTokenIsEnd(tp) )
246
+    {
247
+      --cnt;
248
+
249
+      // break the token chain after the 'end' token
250
+      if( tp->next != NULL )
251
+        tp->next->prev = NULL;
252
+      tp->next = NULL;
253
+
254
+      // create a new right-most leaf-node 
255
+      _cmTtCreateNode(p,np,kTextTtId,ftp);
256
+
257
+      tp = tp->next;
258
+      break;
259
+    }
260
+
261
+    tp = tp->next;
262
+  }
263
+
264
+  if( cnt != 0 )
265
+    cmErrMsg(&p->err,kSyntaxErrTtRC,"The template file '%s' appears to have unbalanced begin/end markers.",cmStringNullGuard(p->fn));
266
+  
267
+  return tp;
268
+}
269
+
270
+
271
+
272
+cmTtRC_t cmTextTemplateInitialize( cmCtx_t* ctx, cmTtH_t* hp, const cmChar_t* fn )
273
+{
274
+  cmTtRC_t rc;
275
+
276
+  if((rc = cmTextTemplateFinalize(hp)) != kOkTtRC )
277
+    return rc;
278
+
279
+  cmTt_t* p = cmMemAllocZ(cmTt_t,1);
280
+
281
+  cmErrSetup(&p->err,&ctx->rpt,"TextTemplate");
282
+
283
+  // create the local linked heap
284
+  if( cmLHeapIsValid(p->lhH = cmLHeapCreate(1024, ctx )) == false )
285
+  {
286
+    rc = cmErrMsg(&p->err,kLHeapFailTtRC,"Lheap Mgr. allocation failed.");
287
+    goto errLabel;
288
+  }
289
+  
290
+  // read the template file 
291
+  if((p->buf = cmFileFnToBuf(fn,p->err.rpt,NULL)) == NULL )
292
+  {
293
+    rc = cmErrMsg(&p->err,kFileFailTtRC,"Unable to open the file '%s'.",cmStringNullGuard(fn));
294
+    goto errLabel;
295
+  }
296
+  
297
+  // store the template file name
298
+  p->fn   = cmLhAllocStr(p->lhH,fn);
299
+
300
+  // break the template file into tokens
301
+  if((rc = _cmTtScan(p,p->buf)) != kOkTtRC )
302
+    goto errLabel;
303
+
304
+  // create the root node
305
+  p->tree = _cmTtCreateNode(p,NULL,kVarTtId,NULL);
306
+
307
+  // build the node tree
308
+  _cmTtBuildTree(p,p->tree,p->tokens);
309
+
310
+  // check for errors
311
+  rc = cmErrLastRC(&p->err);
312
+  
313
+ errLabel:
314
+
315
+  if( rc != kOkTtRC )
316
+    _cmTtFinalize(p);
317
+  
318
+  return rc;
319
+}
320
+
321
+cmTtRC_t cmTextTemplateFinalize( cmTtH_t* hp )
322
+{
323
+  cmTtRC_t rc = kOkTtRC;
324
+
325
+  if( hp==NULL || cmTextTemplateIsValid(*hp)==false ) 
326
+    return rc;
327
+
328
+  cmTt_t* p = _cmTtHandleToPtr(*hp);
329
+
330
+  if((rc = _cmTtFinalize(p)) != kOkTtRC )
331
+    return rc;
332
+
333
+  hp->h = NULL;
334
+
335
+  return rc;
336
+}
337
+
338
+bool     cmTextTemplateIsValid( cmTtH_t h )
339
+{ return h.h != NULL; }
340
+
341
+void cmTextTemplatePrintTokens( cmTtH_t h, cmRpt_t* rpt )
342
+{
343
+  cmTt_t* p = _cmTtHandleToPtr(h);
344
+
345
+  cmTtToken_t* tp = p->tokens;
346
+  cmChar_t* ep = p->buf + strlen(p->buf);
347
+  for(; tp!=NULL; tp=tp->next)
348
+  {
349
+    bool     fl = tp->end < ep;
350
+    cmChar_t c  =  fl ? tp->end[1] : 0;
351
+
352
+    cmRptPrintf(rpt,"%s",tp->text);
353
+
354
+    if( fl )
355
+      tp->end[1] = c;    
356
+  }
357
+}
358
+
359
+
360
+cmTtRC_t cmTextTemplateTest( cmCtx_t* ctx, const cmChar_t* fn )
361
+{
362
+  cmTtRC_t rc;
363
+  cmTtH_t h = cmTtNullHandle;
364
+
365
+  if((rc = cmTextTemplateInitialize(ctx,&h,fn)) != kOkTtRC )
366
+    return rc;
367
+
368
+  cmTextTemplatePrintTokens(h,&ctx->rpt);
369
+
370
+  cmTextTemplateFinalize(&h);
371
+
372
+  return rc;
373
+}

+ 25
- 0
cmTextTemplate.h View File

1
+#ifndef cmTextTemplate_h
2
+#define cmTextTemplate_h
3
+
4
+
5
+enum
6
+{
7
+  kOkTtRC = cmOkRC,
8
+  kFileFailTtRC,
9
+  kLHeapFailTtRC,
10
+  kSyntaxErrTtRC
11
+};
12
+
13
+typedef cmHandle_t cmTtH_t;
14
+typedef unsigned   cmTtRC_t;
15
+extern cmTtH_t cmTtNullHandle;
16
+
17
+
18
+cmTtRC_t cmTextTemplateInitialize( cmCtx_t* ctx, cmTtH_t* hp, const cmChar_t* fn );
19
+cmTtRC_t cmTextTemplateFinalize( cmTtH_t* hp );
20
+bool     cmTextTemplateIsValid( cmTtH_t h );
21
+cmTtRC_t cmTextTemplateTest( cmCtx_t* ctx, const cmChar_t* fn );
22
+
23
+
24
+
25
+#endif

Loading…
Cancel
Save