Revision 49

View differences:

logic/trunk/eneraptor.cbp
16 16
				</Compiler>
17 17
				<Linker>
18 18
					<Add library="pthread" />
19
					<Add library="mxml" />
20 19
				</Linker>
21 20
			</Target>
22 21
			<Target title="Release">
......
68 67
			<Option compilerVar="CC" />
69 68
		</Unit>
70 69
		<Unit filename="src/logics/scenario_threads.h" />
70
		<Unit filename="src/mxml/config.h" />
71
		<Unit filename="src/mxml/mxml-attr.c">
72
			<Option compilerVar="CC" />
73
		</Unit>
74
		<Unit filename="src/mxml/mxml-entity.c">
75
			<Option compilerVar="CC" />
76
		</Unit>
77
		<Unit filename="src/mxml/mxml-file.c">
78
			<Option compilerVar="CC" />
79
		</Unit>
80
		<Unit filename="src/mxml/mxml-index.c">
81
			<Option compilerVar="CC" />
82
		</Unit>
83
		<Unit filename="src/mxml/mxml-node.c">
84
			<Option compilerVar="CC" />
85
		</Unit>
86
		<Unit filename="src/mxml/mxml-private.c">
87
			<Option compilerVar="CC" />
88
		</Unit>
89
		<Unit filename="src/mxml/mxml-private.h" />
90
		<Unit filename="src/mxml/mxml-search.c">
91
			<Option compilerVar="CC" />
92
		</Unit>
93
		<Unit filename="src/mxml/mxml-set.c">
94
			<Option compilerVar="CC" />
95
		</Unit>
96
		<Unit filename="src/mxml/mxml-string.c">
97
			<Option compilerVar="CC" />
98
		</Unit>
99
		<Unit filename="src/mxml/mxml.h" />
71 100
		<Unit filename="src/startup/main.c">
72 101
			<Option compilerVar="CC" />
73 102
			<Option weight="0" />
logic/trunk/src/mxml/mxml-node.c
1
/*
2
 * "$Id: mxml-node.c 363 2008-10-26 18:28:05Z mike $"
3
 *
4
 * Node support code for Mini-XML, a small XML-like file parsing library.
5
 *
6
 * Copyright 2003-2007 by Michael Sweet.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Library General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * Contents:
19
 *
20
 *   mxmlAdd()        - Add a node to a tree.
21
 *   mxmlDelete()     - Delete a node and all of its children.
22
 *   mxmlNewCDATA()   - Create a new CDATA node.
23
 *   mxmlNewCustom()  - Create a new custom data node.
24
 *   mxmlNewElement() - Create a new element node.
25
 *   mxmlNewInteger() - Create a new integer node.
26
 *   mxmlNewOpaque()  - Create a new opaque string.
27
 *   mxmlNewReal()    - Create a new real number node.
28
 *   mxmlNewText()    - Create a new text fragment node.
29
 *   mxmlNewTextf()   - Create a new formatted text fragment node.
30
 *   mxmlNewXML()     - Create a new XML document tree.
31
 *   mxmlRelease()    - Release a node.
32
 *   mxmlRemove()     - Remove a node from its parent.
33
 *   mxmlRetain()     - Retain a node.
34
 *   mxml_new()       - Create a new node.
35
 */
36

  
37
/*
38
 * Include necessary headers...
39
 */
40

  
41
#include "config.h"
42
#include "mxml.h"
43

  
44

  
45
/*
46
 * Local functions...
47
 */
48

  
49
static mxml_node_t	*mxml_new(mxml_node_t *parent, mxml_type_t type);
50

  
51

  
52
/*
53
 * 'mxmlAdd()' - Add a node to a tree.
54
 *
55
 * Adds the specified node to the parent. If the child argument is not
56
 * NULL, puts the new node before or after the specified child depending
57
 * on the value of the where argument. If the child argument is NULL,
58
 * puts the new node at the beginning of the child list (MXML_ADD_BEFORE)
59
 * or at the end of the child list (MXML_ADD_AFTER). The constant
60
 * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
61
 */
62

  
63
void
64
mxmlAdd(mxml_node_t *parent,		/* I - Parent node */
65
        int         where,		/* I - Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER */
66
        mxml_node_t *child,		/* I - Child node for where or MXML_ADD_TO_PARENT */
67
	mxml_node_t *node)		/* I - Node to add */
68
{
69
#ifdef DEBUG
70
  fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
71
          where, child, node);
72
#endif /* DEBUG */
73

  
74
 /*
75
  * Range check input...
76
  */
77

  
78
  if (!parent || !node)
79
    return;
80

  
81
#if DEBUG > 1
82
  fprintf(stderr, "    BEFORE: node->parent=%p\n", node->parent);
83
  if (parent)
84
  {
85
    fprintf(stderr, "    BEFORE: parent->child=%p\n", parent->child);
86
    fprintf(stderr, "    BEFORE: parent->last_child=%p\n", parent->last_child);
87
    fprintf(stderr, "    BEFORE: parent->prev=%p\n", parent->prev);
88
    fprintf(stderr, "    BEFORE: parent->next=%p\n", parent->next);
89
  }
90
#endif /* DEBUG > 1 */
91

  
92
 /*
93
  * Remove the node from any existing parent...
94
  */
95

  
96
  if (node->parent)
97
    mxmlRemove(node);
98

  
99
 /*
100
  * Reset pointers...
101
  */
102

  
103
  node->parent = parent;
104

  
105
  switch (where)
106
  {
107
    case MXML_ADD_BEFORE :
108
        if (!child || child == parent->child || child->parent != parent)
109
	{
110
	 /*
111
	  * Insert as first node under parent...
112
	  */
113

  
114
	  node->next = parent->child;
115

  
116
	  if (parent->child)
117
	    parent->child->prev = node;
118
	  else
119
	    parent->last_child = node;
120

  
121
	  parent->child = node;
122
	}
123
	else
124
	{
125
	 /*
126
	  * Insert node before this child...
127
	  */
128

  
129
	  node->next = child;
130
	  node->prev = child->prev;
131

  
132
	  if (child->prev)
133
	    child->prev->next = node;
134
	  else
135
	    parent->child = node;
136

  
137
	  child->prev = node;
138
	}
139
        break;
140

  
141
    case MXML_ADD_AFTER :
142
        if (!child || child == parent->last_child || child->parent != parent)
143
	{
144
	 /*
145
	  * Insert as last node under parent...
146
	  */
147

  
148
	  node->parent = parent;
149
	  node->prev   = parent->last_child;
150

  
151
	  if (parent->last_child)
152
	    parent->last_child->next = node;
153
	  else
154
	    parent->child = node;
155

  
156
	  parent->last_child = node;
157
        }
158
	else
159
	{
160
	 /*
161
	  * Insert node after this child...
162
	  */
163

  
164
	  node->prev = child;
165
	  node->next = child->next;
166

  
167
	  if (child->next)
168
	    child->next->prev = node;
169
	  else
170
	    parent->last_child = node;
171

  
172
	  child->next = node;
173
	}
174
        break;
175
  }
176

  
177
#if DEBUG > 1
178
  fprintf(stderr, "    AFTER: node->parent=%p\n", node->parent);
179
  if (parent)
180
  {
181
    fprintf(stderr, "    AFTER: parent->child=%p\n", parent->child);
182
    fprintf(stderr, "    AFTER: parent->last_child=%p\n", parent->last_child);
183
    fprintf(stderr, "    AFTER: parent->prev=%p\n", parent->prev);
184
    fprintf(stderr, "    AFTER: parent->next=%p\n", parent->next);
185
  }
186
#endif /* DEBUG > 1 */
187
}
188

  
189

  
190
/*
191
 * 'mxmlDelete()' - Delete a node and all of its children.
192
 *
193
 * If the specified node has a parent, this function first removes the
194
 * node from its parent using the mxmlRemove() function.
195
 */
196

  
197
void
198
mxmlDelete(mxml_node_t *node)		/* I - Node to delete */
199
{
200
  int	i;				/* Looping var */
201

  
202

  
203
#ifdef DEBUG
204
  fprintf(stderr, "mxmlDelete(node=%p)\n", node);
205
#endif /* DEBUG */
206

  
207
 /*
208
  * Range check input...
209
  */
210

  
211
  if (!node)
212
    return;
213

  
214
 /*
215
  * Remove the node from its parent, if any...
216
  */
217

  
218
  mxmlRemove(node);
219

  
220
 /*
221
  * Delete children...
222
  */
223

  
224
  while (node->child)
225
    mxmlDelete(node->child);
226

  
227
 /*
228
  * Now delete any node data...
229
  */
230

  
231
  switch (node->type)
232
  {
233
    case MXML_ELEMENT :
234
        if (node->value.element.name)
235
	  free(node->value.element.name);
236

  
237
	if (node->value.element.num_attrs)
238
	{
239
	  for (i = 0; i < node->value.element.num_attrs; i ++)
240
	  {
241
	    if (node->value.element.attrs[i].name)
242
	      free(node->value.element.attrs[i].name);
243
	    if (node->value.element.attrs[i].value)
244
	      free(node->value.element.attrs[i].value);
245
	  }
246

  
247
          free(node->value.element.attrs);
248
	}
249
        break;
250
    case MXML_INTEGER :
251
       /* Nothing to do */
252
        break;
253
    case MXML_OPAQUE :
254
        if (node->value.opaque)
255
	  free(node->value.opaque);
256
        break;
257
    case MXML_REAL :
258
       /* Nothing to do */
259
        break;
260
    case MXML_TEXT :
261
        if (node->value.text.string)
262
	  free(node->value.text.string);
263
        break;
264
    case MXML_CUSTOM :
265
        if (node->value.custom.data &&
266
	    node->value.custom.destroy)
267
	  (*(node->value.custom.destroy))(node->value.custom.data);
268
	break;
269
    default :
270
        break;
271
  }
272

  
273
 /*
274
  * Free this node...
275
  */
276

  
277
  free(node);
278
}
279

  
280

  
281
/*
282
 * 'mxmlNewCDATA()' - Create a new CDATA node.
283
 *
284
 * The new CDATA node is added to the end of the specified parent's child
285
 * list. The constant MXML_NO_PARENT can be used to specify that the new
286
 * CDATA node has no parent. The data string must be nul-terminated and
287
 * is copied into the new node. CDATA nodes use the MXML_ELEMENT type.
288
 *
289
 * @since Mini-XML 2.3@
290
 */
291

  
292
mxml_node_t *				/* O - New node */
293
mxmlNewCDATA(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
294
	     const char  *data)		/* I - Data string */
295
{
296
  mxml_node_t	*node;			/* New node */
297

  
298

  
299
#ifdef DEBUG
300
  fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
301
          parent, data ? data : "(null)");
302
#endif /* DEBUG */
303

  
304
 /*
305
  * Range check input...
306
  */
307

  
308
  if (!data)
309
    return (NULL);
310

  
311
 /*
312
  * Create the node and set the name value...
313
  */
314

  
315
  if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
316
    node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
317

  
318
  return (node);
319
}
320

  
321

  
322
/*
323
 * 'mxmlNewCustom()' - Create a new custom data node.
324
 *
325
 * The new custom node is added to the end of the specified parent's child
326
 * list. The constant MXML_NO_PARENT can be used to specify that the new
327
 * element node has no parent. NULL can be passed when the data in the
328
 * node is not dynamically allocated or is separately managed.
329
 *
330
 * @since Mini-XML 2.1@
331
 */
332

  
333
mxml_node_t *				/* O - New node */
334
mxmlNewCustom(
335
    mxml_node_t              *parent,	/* I - Parent node or MXML_NO_PARENT */
336
    void                     *data,	/* I - Pointer to data */
337
    mxml_custom_destroy_cb_t destroy)	/* I - Function to destroy data */
338
{
339
  mxml_node_t	*node;			/* New node */
340

  
341

  
342
#ifdef DEBUG
343
  fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
344
          data, destroy);
345
#endif /* DEBUG */
346

  
347
 /*
348
  * Create the node and set the value...
349
  */
350

  
351
  if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL)
352
  {
353
    node->value.custom.data    = data;
354
    node->value.custom.destroy = destroy;
355
  }
356

  
357
  return (node);
358
}
359

  
360

  
361
/*
362
 * 'mxmlNewElement()' - Create a new element node.
363
 *
364
 * The new element node is added to the end of the specified parent's child
365
 * list. The constant MXML_NO_PARENT can be used to specify that the new
366
 * element node has no parent.
367
 */
368

  
369
mxml_node_t *				/* O - New node */
370
mxmlNewElement(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
371
               const char  *name)	/* I - Name of element */
372
{
373
  mxml_node_t	*node;			/* New node */
374

  
375

  
376
#ifdef DEBUG
377
  fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
378
          name ? name : "(null)");
379
#endif /* DEBUG */
380

  
381
 /*
382
  * Range check input...
383
  */
384

  
385
  if (!name)
386
    return (NULL);
387

  
388
 /*
389
  * Create the node and set the element name...
390
  */
391

  
392
  if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
393
    node->value.element.name = strdup(name);
394

  
395
  return (node);
396
}
397

  
398

  
399
/*
400
 * 'mxmlNewInteger()' - Create a new integer node.
401
 *
402
 * The new integer node is added to the end of the specified parent's child
403
 * list. The constant MXML_NO_PARENT can be used to specify that the new
404
 * integer node has no parent.
405
 */
406

  
407
mxml_node_t *				/* O - New node */
408
mxmlNewInteger(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
409
               int         integer)	/* I - Integer value */
410
{
411
  mxml_node_t	*node;			/* New node */
412

  
413

  
414
#ifdef DEBUG
415
  fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
416
#endif /* DEBUG */
417

  
418
 /*
419
  * Create the node and set the element name...
420
  */
421

  
422
  if ((node = mxml_new(parent, MXML_INTEGER)) != NULL)
423
    node->value.integer = integer;
424

  
425
  return (node);
426
}
427

  
428

  
429
/*
430
 * 'mxmlNewOpaque()' - Create a new opaque string.
431
 *
432
 * The new opaque node is added to the end of the specified parent's child
433
 * list. The constant MXML_NO_PARENT can be used to specify that the new
434
 * opaque node has no parent. The opaque string must be nul-terminated and
435
 * is copied into the new node.
436
 */
437

  
438
mxml_node_t *				/* O - New node */
439
mxmlNewOpaque(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
440
              const char  *opaque)	/* I - Opaque string */
441
{
442
  mxml_node_t	*node;			/* New node */
443

  
444

  
445
#ifdef DEBUG
446
  fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
447
          opaque ? opaque : "(null)");
448
#endif /* DEBUG */
449

  
450
 /*
451
  * Range check input...
452
  */
453

  
454
  if (!opaque)
455
    return (NULL);
456

  
457
 /*
458
  * Create the node and set the element name...
459
  */
460

  
461
  if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL)
462
    node->value.opaque = strdup(opaque);
463

  
464
  return (node);
465
}
466

  
467

  
468
/*
469
 * 'mxmlNewReal()' - Create a new real number node.
470
 *
471
 * The new real number node is added to the end of the specified parent's
472
 * child list. The constant MXML_NO_PARENT can be used to specify that
473
 * the new real number node has no parent.
474
 */
475

  
476
mxml_node_t *				/* O - New node */
477
mxmlNewReal(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
478
            double      real)		/* I - Real number value */
479
{
480
  mxml_node_t	*node;			/* New node */
481

  
482

  
483
#ifdef DEBUG
484
  fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
485
#endif /* DEBUG */
486

  
487
 /*
488
  * Create the node and set the element name...
489
  */
490

  
491
  if ((node = mxml_new(parent, MXML_REAL)) != NULL)
492
    node->value.real = real;
493

  
494
  return (node);
495
}
496

  
497

  
498
/*
499
 * 'mxmlNewText()' - Create a new text fragment node.
500
 *
501
 * The new text node is added to the end of the specified parent's child
502
 * list. The constant MXML_NO_PARENT can be used to specify that the new
503
 * text node has no parent. The whitespace parameter is used to specify
504
 * whether leading whitespace is present before the node. The text
505
 * string must be nul-terminated and is copied into the new node.  
506
 */
507

  
508
mxml_node_t *				/* O - New node */
509
mxmlNewText(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
510
            int         whitespace,	/* I - 1 = leading whitespace, 0 = no whitespace */
511
	    const char  *string)	/* I - String */
512
{
513
  mxml_node_t	*node;			/* New node */
514

  
515

  
516
#ifdef DEBUG
517
  fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
518
          parent, whitespace, string ? string : "(null)");
519
#endif /* DEBUG */
520

  
521
 /*
522
  * Range check input...
523
  */
524

  
525
  if (!string)
526
    return (NULL);
527

  
528
 /*
529
  * Create the node and set the text value...
530
  */
531

  
532
  if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
533
  {
534
    node->value.text.whitespace = whitespace;
535
    node->value.text.string     = strdup(string);
536
  }
537

  
538
  return (node);
539
}
540

  
541

  
542
/*
543
 * 'mxmlNewTextf()' - Create a new formatted text fragment node.
544
 *
545
 * The new text node is added to the end of the specified parent's child
546
 * list. The constant MXML_NO_PARENT can be used to specify that the new
547
 * text node has no parent. The whitespace parameter is used to specify
548
 * whether leading whitespace is present before the node. The format
549
 * string must be nul-terminated and is formatted into the new node.  
550
 */
551

  
552
mxml_node_t *				/* O - New node */
553
mxmlNewTextf(mxml_node_t *parent,	/* I - Parent node or MXML_NO_PARENT */
554
             int         whitespace,	/* I - 1 = leading whitespace, 0 = no whitespace */
555
	     const char  *format,	/* I - Printf-style frmat string */
556
	     ...)			/* I - Additional args as needed */
557
{
558
  mxml_node_t	*node;			/* New node */
559
  va_list	ap;			/* Pointer to arguments */
560

  
561

  
562
#ifdef DEBUG
563
  fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n",
564
          parent, whitespace, format ? format : "(null)");
565
#endif /* DEBUG */
566

  
567
 /*
568
  * Range check input...
569
  */
570

  
571
  if (!format)
572
    return (NULL);
573

  
574
 /*
575
  * Create the node and set the text value...
576
  */
577

  
578
  if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
579
  {
580
    va_start(ap, format);
581

  
582
    node->value.text.whitespace = whitespace;
583
    node->value.text.string     = _mxml_vstrdupf(format, ap);
584

  
585
    va_end(ap);
586
  }
587

  
588
  return (node);
589
}
590

  
591

  
592
/*
593
 * 'mxmlRemove()' - Remove a node from its parent.
594
 *
595
 * Does not free memory used by the node - use mxmlDelete() for that.
596
 * This function does nothing if the node has no parent.
597
 */
598

  
599
void
600
mxmlRemove(mxml_node_t *node)		/* I - Node to remove */
601
{
602
#ifdef DEBUG
603
  fprintf(stderr, "mxmlRemove(node=%p)\n", node);
604
#endif /* DEBUG */
605

  
606
 /*
607
  * Range check input...
608
  */
609

  
610
  if (!node || !node->parent)
611
    return;
612

  
613
 /*
614
  * Remove from parent...
615
  */
616

  
617
#if DEBUG > 1
618
  fprintf(stderr, "    BEFORE: node->parent=%p\n", node->parent);
619
  if (node->parent)
620
  {
621
    fprintf(stderr, "    BEFORE: node->parent->child=%p\n", node->parent->child);
622
    fprintf(stderr, "    BEFORE: node->parent->last_child=%p\n", node->parent->last_child);
623
  }
624
  fprintf(stderr, "    BEFORE: node->child=%p\n", node->child);
625
  fprintf(stderr, "    BEFORE: node->last_child=%p\n", node->last_child);
626
  fprintf(stderr, "    BEFORE: node->prev=%p\n", node->prev);
627
  fprintf(stderr, "    BEFORE: node->next=%p\n", node->next);
628
#endif /* DEBUG > 1 */
629

  
630
  if (node->prev)
631
    node->prev->next = node->next;
632
  else
633
    node->parent->child = node->next;
634

  
635
  if (node->next)
636
    node->next->prev = node->prev;
637
  else
638
    node->parent->last_child = node->prev;
639

  
640
  node->parent = NULL;
641
  node->prev   = NULL;
642
  node->next   = NULL;
643

  
644
#if DEBUG > 1
645
  fprintf(stderr, "    AFTER: node->parent=%p\n", node->parent);
646
  if (node->parent)
647
  {
648
    fprintf(stderr, "    AFTER: node->parent->child=%p\n", node->parent->child);
649
    fprintf(stderr, "    AFTER: node->parent->last_child=%p\n", node->parent->last_child);
650
  }
651
  fprintf(stderr, "    AFTER: node->child=%p\n", node->child);
652
  fprintf(stderr, "    AFTER: node->last_child=%p\n", node->last_child);
653
  fprintf(stderr, "    AFTER: node->prev=%p\n", node->prev);
654
  fprintf(stderr, "    AFTER: node->next=%p\n", node->next);
655
#endif /* DEBUG > 1 */
656
}
657

  
658

  
659
/*
660
 * 'mxmlNewXML()' - Create a new XML document tree.
661
 *
662
 * The "version" argument specifies the version number to put in the
663
 * ?xml element node. If NULL, version 1.0 is assumed.
664
 *
665
 * @since Mini-XML 2.3@
666
 */
667

  
668
mxml_node_t *				/* O - New ?xml node */
669
mxmlNewXML(const char *version)		/* I - Version number to use */
670
{
671
  char	element[1024];			/* Element text */
672

  
673

  
674
  snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?",
675
           version ? version : "1.0");
676

  
677
  return (mxmlNewElement(NULL, element));
678
}
679

  
680

  
681
/*
682
 * 'mxmlRelease()' - Release a node.
683
 *
684
 * When the reference count reaches zero, the node (and any children)
685
 * is deleted via mxmlDelete().
686
 *
687
 * @since Mini-XML 2.3@
688
 */
689

  
690
int					/* O - New reference count */
691
mxmlRelease(mxml_node_t *node)		/* I - Node */
692
{
693
  if (node)
694
  {
695
    if ((-- node->ref_count) <= 0)
696
    {
697
      mxmlDelete(node);
698
      return (0);
699
    }
700
    else
701
      return (node->ref_count);
702
  }
703
  else
704
    return (-1);
705
}
706

  
707

  
708
/*
709
 * 'mxmlRetain()' - Retain a node.
710
 *
711
 * @since Mini-XML 2.3@
712
 */
713

  
714
int					/* O - New reference count */
715
mxmlRetain(mxml_node_t *node)		/* I - Node */
716
{
717
  if (node)
718
    return (++ node->ref_count);
719
  else
720
    return (-1);
721
}
722

  
723

  
724
/*
725
 * 'mxml_new()' - Create a new node.
726
 */
727

  
728
static mxml_node_t *			/* O - New node */
729
mxml_new(mxml_node_t *parent,		/* I - Parent node */
730
         mxml_type_t type)		/* I - Node type */
731
{
732
  mxml_node_t	*node;			/* New node */
733

  
734

  
735
#if DEBUG > 1
736
  fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
737
#endif /* DEBUG > 1 */
738

  
739
 /*
740
  * Allocate memory for the node...
741
  */
742

  
743
  if ((node = calloc(1, sizeof(mxml_node_t))) == NULL)
744
  {
745
#if DEBUG > 1
746
    fputs("    returning NULL\n", stderr);
747
#endif /* DEBUG > 1 */
748

  
749
    return (NULL);
750
  }
751

  
752
#if DEBUG > 1
753
  fprintf(stderr, "    returning %p\n", node);
754
#endif /* DEBUG > 1 */
755

  
756
 /*
757
  * Set the node type...
758
  */
759

  
760
  node->type      = type;
761
  node->ref_count = 1;
762

  
763
 /*
764
  * Add to the parent if present...
765
  */
766

  
767
  if (parent)
768
    mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
769

  
770
 /*
771
  * Return the new node...
772
  */
773

  
774
  return (node);
775
}
776

  
777

  
778
/*
779
 * End of "$Id: mxml-node.c 363 2008-10-26 18:28:05Z mike $".
780
 */
logic/trunk/src/mxml/mxml-search.c
1
/*
2
 * "$Id: mxml-search.c 297 2007-09-09 07:16:52Z mike $"
3
 *
4
 * Search/navigation functions for Mini-XML, a small XML-like file
5
 * parsing library.
6
 *
7
 * Copyright 2003-2007 by Michael Sweet.
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Library General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * Contents:
20
 *
21
 *   mxmlFindElement() - Find the named element.
22
 *   mxmlWalkNext()    - Walk to the next logical node in the tree.
23
 *   mxmlWalkPrev()    - Walk to the previous logical node in the tree.
24
 */
25

  
26
/*
27
 * Include necessary headers...
28
 */
29

  
30
#include "config.h"
31
#include "mxml.h"
32

  
33

  
34
/*
35
 * 'mxmlFindElement()' - Find the named element.
36
 *
37
 * The search is constrained by the name, attribute name, and value; any
38
 * NULL names or values are treated as wildcards, so different kinds of
39
 * searches can be implemented by looking for all elements of a given name
40
 * or all elements with a specific attribute. The descend argument determines
41
 * whether the search descends into child nodes; normally you will use
42
 * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
43
 * additional direct descendents of the node. The top node argument
44
 * constrains the search to a particular node's children.
45
 */
46

  
47
mxml_node_t *				/* O - Element node or NULL */
48
mxmlFindElement(mxml_node_t *node,	/* I - Current node */
49
                mxml_node_t *top,	/* I - Top node */
50
                const char  *name,	/* I - Element name or NULL for any */
51
		const char  *attr,	/* I - Attribute name, or NULL for none */
52
		const char  *value,	/* I - Attribute value, or NULL for any */
53
		int         descend)	/* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
54
{
55
  const char	*temp;			/* Current attribute value */
56

  
57

  
58
 /*
59
  * Range check input...
60
  */
61

  
62
  if (!node || !top || (!attr && value))
63
    return (NULL);
64

  
65
 /*
66
  * Start with the next node...
67
  */
68

  
69
  node = mxmlWalkNext(node, top, descend);
70

  
71
 /*
72
  * Loop until we find a matching element...
73
  */
74

  
75
  while (node != NULL)
76
  {
77
   /*
78
    * See if this node matches...
79
    */
80

  
81
    if (node->type == MXML_ELEMENT &&
82
        node->value.element.name &&
83
	(!name || !strcmp(node->value.element.name, name)))
84
    {
85
     /*
86
      * See if we need to check for an attribute...
87
      */
88

  
89
      if (!attr)
90
        return (node);			/* No attribute search, return it... */
91

  
92
     /*
93
      * Check for the attribute...
94
      */
95

  
96
      if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
97
      {
98
       /*
99
        * OK, we have the attribute, does it match?
100
	*/
101

  
102
	if (!value || !strcmp(value, temp))
103
	  return (node);		/* Yes, return it... */
104
      }
105
    }
106

  
107
   /*
108
    * No match, move on to the next node...
109
    */
110

  
111
    if (descend == MXML_DESCEND)
112
      node = mxmlWalkNext(node, top, MXML_DESCEND);
113
    else
114
      node = node->next;
115
  }
116

  
117
  return (NULL);
118
}
119

  
120

  
121
/*
122
 * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
123
 *
124
 * The descend argument controls whether the first child is considered
125
 * to be the next node. The top node argument constrains the walk to
126
 * the node's children.
127
 */
128

  
129
mxml_node_t *				/* O - Next node or NULL */
130
mxmlWalkNext(mxml_node_t *node,		/* I - Current node */
131
             mxml_node_t *top,		/* I - Top node */
132
             int         descend)	/* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
133
{
134
  if (!node)
135
    return (NULL);
136
  else if (node->child && descend)
137
    return (node->child);
138
  else if (node == top)
139
    return (NULL);
140
  else if (node->next)
141
    return (node->next);
142
  else if (node->parent && node->parent != top)
143
  {
144
    node = node->parent;
145

  
146
    while (!node->next)
147
      if (node->parent == top || !node->parent)
148
        return (NULL);
149
      else
150
        node = node->parent;
151

  
152
    return (node->next);
153
  }
154
  else
155
    return (NULL);
156
}
157

  
158

  
159
/*
160
 * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
161
 *
162
 * The descend argument controls whether the previous node's last child
163
 * is considered to be the previous node. The top node argument constrains
164
 * the walk to the node's children.
165
 */
166

  
167
mxml_node_t *				/* O - Previous node or NULL */
168
mxmlWalkPrev(mxml_node_t *node,		/* I - Current node */
169
             mxml_node_t *top,		/* I - Top node */
170
             int         descend)	/* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
171
{
172
  if (!node || node == top)
173
    return (NULL);
174
  else if (node->prev)
175
  {
176
    if (node->prev->last_child && descend)
177
    {
178
     /*
179
      * Find the last child under the previous node...
180
      */
181

  
182
      node = node->prev->last_child;
183

  
184
      while (node->last_child)
185
        node = node->last_child;
186

  
187
      return (node);
188
    }
189
    else
190
      return (node->prev);
191
  }
192
  else if (node->parent != top)
193
    return (node->parent);
194
  else
195
    return (NULL);
196
}
197

  
198

  
199
/*
200
 * End of "$Id: mxml-search.c 297 2007-09-09 07:16:52Z mike $".
201
 */
logic/trunk/src/mxml/mxml-string.c
1
/*
2
 * "$Id: mxml-string.c 387 2009-04-18 17:05:52Z mike $"
3
 *
4
 * String functions for Mini-XML, a small XML-like file parsing library.
5
 *
6
 * Copyright 2003-2009 by Michael Sweet.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Library General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * Contents:
19
 *
20
 *   _mxml_snprintf()  - Format a string.
21
 *   _mxml_strdup()    - Duplicate a string.
22
 *   _mxml_strdupf()   - Format and duplicate a string.
23
 *   _mxml_vsnprintf() - Format a string into a fixed size buffer.
24
 *   _mxml_vstrdupf()  - Format and duplicate a string.
25
 */
26

  
27
/*
28
 * Include necessary headers...
29
 */
30

  
31
#include "config.h"
32

  
33

  
34
#ifndef HAVE_SNPRINTF
35
/*
36
 * '_mxml_snprintf()' - Format a string.
37
 */
38

  
39
int					/* O - Number of bytes formatted */
40
_mxml_snprintf(char       *buffer,	/* I - Output buffer */
41
               size_t     bufsize,	/* I - Size of output buffer */
42
	       const char *format,	/* I - Printf-style format string */
43
	       ...)			/* I - Additional arguments as needed */
44
{
45
  va_list	ap;			/* Argument list */
46
  int		bytes;			/* Number of bytes formatted */
47

  
48

  
49
  va_start(ap, format);
50
  bytes = vsnprintf(buffer, bufsize, format, ap);
51
  va_end(ap);
52

  
53
  return (bytes);
54
}
55
#endif /* !HAVE_SNPRINTF */
56

  
57

  
58
/*
59
 * '_mxml_strdup()' - Duplicate a string.
60
 */
61

  
62
#ifndef HAVE_STRDUP
63
char 	*				/* O - New string pointer */
64
_mxml_strdup(const char *s)		/* I - String to duplicate */
65
{
66
  char	*t;				/* New string pointer */
67

  
68

  
69
  if (s == NULL)
70
    return (NULL);
71

  
72
  if ((t = malloc(strlen(s) + 1)) == NULL)
73
    return (NULL);
74

  
75
  return (strcpy(t, s));
76
}
77
#endif /* !HAVE_STRDUP */
78

  
79

  
80
/*
81
 * '_mxml_strdupf()' - Format and duplicate a string.
82
 */
83

  
84
char *					/* O - New string pointer */
85
_mxml_strdupf(const char *format,	/* I - Printf-style format string */
86
              ...)			/* I - Additional arguments as needed */
87
{
88
  va_list	ap;			/* Pointer to additional arguments */
89
  char		*s;			/* Pointer to formatted string */
90

  
91

  
92
 /*
93
  * Get a pointer to the additional arguments, format the string,
94
  * and return it...
95
  */
96

  
97
  va_start(ap, format);
98
  s = _mxml_vstrdupf(format, ap);
99
  va_end(ap);
100

  
101
  return (s);
102
}
103

  
104

  
105
#ifndef HAVE_VSNPRINTF
106
/*
107
 * '_mxml_vsnprintf()' - Format a string into a fixed size buffer.
108
 */
109

  
110
int					/* O - Number of bytes formatted */
111
_mxml_vsnprintf(char       *buffer,	/* O - Output buffer */
112
                size_t     bufsize,	/* O - Size of output buffer */
113
		const char *format,	/* I - Printf-style format string */
114
 		va_list    ap)		/* I - Pointer to additional arguments */
115
{
116
  char		*bufptr,		/* Pointer to position in buffer */
117
		*bufend,		/* Pointer to end of buffer */
118
		sign,			/* Sign of format width */
119
		size,			/* Size character (h, l, L) */
120
		type;			/* Format type character */
121
  int		width,			/* Width of field */
122
		prec;			/* Number of characters of precision */
123
  char		tformat[100],		/* Temporary format string for sprintf() */
124
		*tptr,			/* Pointer into temporary format */
125
		temp[1024];		/* Buffer for formatted numbers */
126
  char		*s;			/* Pointer to string */
127
  int		slen;			/* Length of string */
128
  int		bytes;			/* Total number of bytes needed */
129

  
130

  
131
 /*
132
  * Loop through the format string, formatting as needed...
133
  */
134

  
135
  bufptr = buffer;
136
  bufend = buffer + bufsize - 1;
137
  bytes  = 0;
138

  
139
  while (*format)
140
  {
141
    if (*format == '%')
142
    {
143
      tptr = tformat;
144
      *tptr++ = *format++;
145

  
146
      if (*format == '%')
147
      {
148
        if (bufptr && bufptr < bufend) *bufptr++ = *format;
149
        bytes ++;
150
        format ++;
151
	continue;
152
      }
153
      else if (strchr(" -+#\'", *format))
154
      {
155
        *tptr++ = *format;
156
        sign = *format++;
157
      }
158
      else
159
        sign = 0;
160

  
161
      if (*format == '*')
162
      {
163
       /*
164
        * Get width from argument...
165
	*/
166

  
167
	format ++;
168
	width = va_arg(ap, int);
169

  
170
	snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
171
	tptr += strlen(tptr);
172
      }
173
      else
174
      {
175
	width = 0;
176

  
177
	while (isdigit(*format & 255))
178
	{
179
	  if (tptr < (tformat + sizeof(tformat) - 1))
180
	    *tptr++ = *format;
181

  
182
	  width = width * 10 + *format++ - '0';
183
	}
184
      }
185

  
186
      if (*format == '.')
187
      {
188
	if (tptr < (tformat + sizeof(tformat) - 1))
189
	  *tptr++ = *format;
190

  
191
        format ++;
192

  
193
        if (*format == '*')
194
	{
195
         /*
196
	  * Get precision from argument...
197
	  */
198

  
199
	  format ++;
200
	  prec = va_arg(ap, int);
201

  
202
	  snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
203
	  tptr += strlen(tptr);
204
	}
205
	else
206
	{
207
	  prec = 0;
208

  
209
	  while (isdigit(*format & 255))
210
	  {
211
	    if (tptr < (tformat + sizeof(tformat) - 1))
212
	      *tptr++ = *format;
213

  
214
	    prec = prec * 10 + *format++ - '0';
215
	  }
216
	}
217
      }
218
      else
219
        prec = -1;
220

  
221
      if (*format == 'l' && format[1] == 'l')
222
      {
223
        size = 'L';
224

  
225
	if (tptr < (tformat + sizeof(tformat) - 2))
226
	{
227
	  *tptr++ = 'l';
228
	  *tptr++ = 'l';
229
	}
230

  
231
	format += 2;
232
      }
233
      else if (*format == 'h' || *format == 'l' || *format == 'L')
234
      {
235
	if (tptr < (tformat + sizeof(tformat) - 1))
236
	  *tptr++ = *format;
237

  
238
        size = *format++;
239
      }
240

  
241
      if (!*format)
242
        break;
243

  
244
      if (tptr < (tformat + sizeof(tformat) - 1))
245
        *tptr++ = *format;
246

  
247
      type  = *format++;
248
      *tptr = '\0';
249

  
250
      switch (type)
251
      {
252
	case 'E' : /* Floating point formats */
253
	case 'G' :
254
	case 'e' :
255
	case 'f' :
256
	case 'g' :
257
	    if ((width + 2) > sizeof(temp))
258
	      break;
259

  
260
	    sprintf(temp, tformat, va_arg(ap, double));
261

  
262
            bytes += strlen(temp);
263

  
264
            if (bufptr)
265
	    {
266
	      if ((bufptr + strlen(temp)) > bufend)
267
	      {
268
		strncpy(bufptr, temp, (size_t)(bufend - bufptr));
269
		bufptr = bufend;
270
	      }
271
	      else
272
	      {
273
		strcpy(bufptr, temp);
274
		bufptr += strlen(temp);
275
	      }
276
	    }
277
	    break;
278

  
279
        case 'B' : /* Integer formats */
280
	case 'X' :
281
	case 'b' :
282
        case 'd' :
283
	case 'i' :
284
	case 'o' :
285
	case 'u' :
286
	case 'x' :
287
	    if ((width + 2) > sizeof(temp))
288
	      break;
289

  
290
#ifdef HAVE_LONG_LONG
291
	    if (size == 'L')
292
	      sprintf(temp, tformat, va_arg(ap, long long));
293
	    else
294
#endif /* HAVE_LONG_LONG */
295
	    sprintf(temp, tformat, va_arg(ap, int));
296

  
297
            bytes += strlen(temp);
298

  
299
	    if (bufptr)
300
	    {
301
	      if ((bufptr + strlen(temp)) > bufend)
302
	      {
303
		strncpy(bufptr, temp, (size_t)(bufend - bufptr));
304
		bufptr = bufend;
305
	      }
306
	      else
307
	      {
308
		strcpy(bufptr, temp);
309
		bufptr += strlen(temp);
310
	      }
311
	    }
312
	    break;
313

  
314
	case 'p' : /* Pointer value */
315
	    if ((width + 2) > sizeof(temp))
316
	      break;
317

  
318
	    sprintf(temp, tformat, va_arg(ap, void *));
319

  
320
            bytes += strlen(temp);
321

  
322
	    if (bufptr)
323
	    {
324
	      if ((bufptr + strlen(temp)) > bufend)
325
	      {
326
		strncpy(bufptr, temp, (size_t)(bufend - bufptr));
327
		bufptr = bufend;
328
	      }
329
	      else
330
	      {
331
		strcpy(bufptr, temp);
332
		bufptr += strlen(temp);
333
	      }
334
	    }
335
	    break;
336

  
337
        case 'c' : /* Character or character array */
338
	    bytes += width;
339

  
340
	    if (bufptr)
341
	    {
342
	      if (width <= 1)
343
	        *bufptr++ = va_arg(ap, int);
344
	      else
345
	      {
346
		if ((bufptr + width) > bufend)
347
		  width = bufend - bufptr;
348

  
349
		memcpy(bufptr, va_arg(ap, char *), (size_t)width);
350
		bufptr += width;
351
	      }
352
	    }
353
	    break;
354

  
355
	case 's' : /* String */
356
	    if ((s = va_arg(ap, char *)) == NULL)
357
	      s = "(null)";
358

  
359
	    slen = strlen(s);
360
	    if (slen > width && prec != width)
361
	      width = slen;
362

  
363
            bytes += width;
364

  
365
	    if (bufptr)
366
	    {
367
	      if ((bufptr + width) > bufend)
368
	        width = bufend - bufptr;
369

  
370
              if (slen > width)
371
	        slen = width;
372

  
373
	      if (sign == '-')
374
	      {
375
		strncpy(bufptr, s, (size_t)slen);
376
		memset(bufptr + slen, ' ', (size_t)(width - slen));
377
	      }
378
	      else
379
	      {
380
		memset(bufptr, ' ', (size_t)(width - slen));
381
		strncpy(bufptr + width - slen, s, (size_t)slen);
382
	      }
383

  
384
	      bufptr += width;
385
	    }
386
	    break;
387

  
388
	case 'n' : /* Output number of chars so far */
389
	    *(va_arg(ap, int *)) = bytes;
390
	    break;
391
      }
392
    }
393
    else
394
    {
395
      bytes ++;
396

  
397
      if (bufptr && bufptr < bufend)
398
        *bufptr++ = *format;
399

  
400
      format ++;
401
    }
402
  }
403

  
404
 /*
405
  * Nul-terminate the string and return the number of characters needed.
406
  */
407

  
408
  *bufptr = '\0';
409

  
410
  return (bytes);
411
}
412
#endif /* !HAVE_VSNPRINTF */
413

  
414

  
415
/*
416
 * '_mxml_vstrdupf()' - Format and duplicate a string.
417
 */
418

  
419
char *					/* O - New string pointer */
420
_mxml_vstrdupf(const char *format,	/* I - Printf-style format string */
421
               va_list    ap)		/* I - Pointer to additional arguments */
422
{
423
  int	bytes;				/* Number of bytes required */
424
  char	*buffer,			/* String buffer */
425
	temp[256];			/* Small buffer for first vsnprintf */
426

  
427

  
428
 /*
429
  * First format with a tiny buffer; this will tell us how many bytes are
430
  * needed...
431
  */
432

  
433
  bytes = vsnprintf(temp, sizeof(temp), format, ap);
434

  
435
  if (bytes < sizeof(temp))
436
  {
437
   /*
438
    * Hey, the formatted string fits in the tiny buffer, so just dup that...
439
    */
440

  
441
    return (strdup(temp));
442
  }
443

  
444
 /*
445
  * Allocate memory for the whole thing and reformat to the new, larger
446
  * buffer...
447
  */
448

  
449
  if ((buffer = calloc(1, bytes + 1)) != NULL)
450
    vsnprintf(buffer, bytes + 1, format, ap);
451

  
452
 /*
453
  * Return the new string...
454
  */
455

  
456
  return (buffer);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff