1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * GThumb
5 *
6 * Copyright (C) 2003, 2010 Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (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 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <stdio.h>
23 #include "albumtheme-private.h"
24
25 #define MAX_EXPR_SIZE 100
26 #define MEM_SIZE 1000
27
28
29 GList *yy_parsed_doc = NULL;
30
31
32 GthMem *
gth_mem_new(int size)33 gth_mem_new (int size)
34 {
35 GthMem *mem;
36
37 mem = g_new0 (GthMem, 1);
38
39 mem->data = g_new (int, size);
40 gth_mem_set_empty (mem);
41
42 return mem;
43 }
44
45
46 void
gth_mem_free(GthMem * mem)47 gth_mem_free (GthMem *mem)
48 {
49 g_free (mem->data);
50 g_free (mem);
51 }
52
53
54 void
gth_mem_set_empty(GthMem * mem)55 gth_mem_set_empty (GthMem *mem)
56 {
57 mem->top = 0;
58 }
59
60
61 gboolean
gth_mem_is_empty(GthMem * mem)62 gth_mem_is_empty (GthMem *mem)
63 {
64 return (mem->top == 0);
65 }
66
67
68 void
gth_mem_push(GthMem * mem,int val)69 gth_mem_push (GthMem *mem,
70 int val)
71 {
72 mem->data[mem->top++] = val;
73 }
74
75
76 int
gth_mem_pop(GthMem * mem)77 gth_mem_pop (GthMem *mem)
78 {
79 if (! gth_mem_is_empty (mem)) {
80 mem->top--;
81 return mem->data[mem->top];
82 }
83
84 return 0;
85 }
86
87
88 int
gth_mem_get_pos(GthMem * mem,int pos)89 gth_mem_get_pos (GthMem *mem,
90 int pos)
91 {
92 if ((pos <= 0) || (pos > mem->top))
93 return 0;
94 return mem->data[pos - 1];
95 }
96
97
98 int
gth_mem_get(GthMem * mem)99 gth_mem_get (GthMem *mem)
100 {
101 return gth_mem_get_pos (mem, mem->top);
102 }
103
104
105 int
gth_mem_get_top(GthMem * mem)106 gth_mem_get_top (GthMem *mem)
107 {
108 return mem->top;
109 }
110
111
112 /* GthCell */
113
114
115 GthCell *
gth_cell_new(void)116 gth_cell_new (void)
117 {
118 GthCell *cell;
119
120 cell = g_new0 (GthCell, 1);
121 cell->ref = 1;
122
123 return cell;
124 }
125
126
127 GthCell *
gth_cell_ref(GthCell * cell)128 gth_cell_ref (GthCell *cell)
129 {
130 cell->ref++;
131 return cell;
132 }
133
134
135 void
gth_cell_unref(GthCell * cell)136 gth_cell_unref (GthCell *cell)
137 {
138 if (cell == NULL)
139 return;
140
141 cell->ref--;
142 if (cell->ref > 0)
143 return;
144
145 if (cell->type == GTH_CELL_TYPE_VAR)
146 g_free (cell->value.var);
147 else if (cell->type == GTH_CELL_TYPE_STRING)
148 g_string_free (cell->value.string, TRUE);
149 g_free (cell);
150 }
151
152
153 /* GthExpr */
154
155
156 static int
default_get_var_value_func(GthExpr * expr,int * index,const char * var_name,gpointer data)157 default_get_var_value_func (GthExpr *expr,
158 int *index,
159 const char *var_name,
160 gpointer data)
161 {
162 return 0;
163 }
164
165
166 GthExpr *
gth_expr_new(void)167 gth_expr_new (void)
168 {
169 GthExpr *e;
170
171 e = g_new0 (GthExpr, 1);
172 e->ref = 1;
173 e->data = g_new0 (GthCell*, MAX_EXPR_SIZE);
174 gth_expr_set_get_var_value_func (e, default_get_var_value_func, NULL);
175
176 return e;
177 }
178
179
180 GthExpr *
gth_expr_ref(GthExpr * e)181 gth_expr_ref (GthExpr *e)
182 {
183 e->ref++;
184 return e;
185 }
186
187
188 void
gth_expr_unref(GthExpr * e)189 gth_expr_unref (GthExpr *e)
190 {
191 if (e == NULL)
192 return;
193
194 e->ref--;
195
196 if (e->ref == 0) {
197 int i;
198
199 for (i = 0; i < MAX_EXPR_SIZE; i++)
200 gth_cell_unref (e->data[i]);
201 g_free (e->data);
202 g_free (e);
203 }
204 }
205
206
207 void
gth_expr_set_empty(GthExpr * e)208 gth_expr_set_empty (GthExpr *e)
209 {
210 e->top = 0;
211 }
212
213
214 gboolean
gth_expr_is_empty(GthExpr * e)215 gth_expr_is_empty (GthExpr *e)
216 {
217 return (e->top == 0);
218 }
219
220
221 void
gth_expr_push_expr(GthExpr * e,GthExpr * e2)222 gth_expr_push_expr (GthExpr *e,
223 GthExpr *e2)
224 {
225 int i;
226
227 for (i = 0; i < e2->top; i++) {
228 gth_cell_unref (e->data[e->top]);
229 e->data[e->top] = gth_cell_ref (e2->data[i]);
230 e->top++;
231 }
232 }
233
234
235 void
gth_expr_push_op(GthExpr * e,GthOp op)236 gth_expr_push_op (GthExpr *e,
237 GthOp op)
238 {
239 GthCell *cell;
240
241 gth_cell_unref (e->data[e->top]);
242
243 cell = gth_cell_new ();
244 cell->type = GTH_CELL_TYPE_OP;
245 cell->value.op = op;
246 e->data[e->top] = cell;
247
248 e->top++;
249 }
250
251
252 void
gth_expr_push_var(GthExpr * e,const char * name)253 gth_expr_push_var (GthExpr *e,
254 const char *name)
255 {
256 GthCell *cell;
257
258 gth_cell_unref (e->data[e->top]);
259
260 cell = gth_cell_new ();
261 cell->type = GTH_CELL_TYPE_VAR;
262 cell->value.var = g_strdup (name);
263 e->data[e->top] = cell;
264
265 e->top++;
266 }
267
268
269 void
gth_expr_push_string(GthExpr * e,const char * value)270 gth_expr_push_string (GthExpr *e,
271 const char *value)
272 {
273 GthCell *cell;
274
275 gth_cell_unref (e->data[e->top]);
276
277 cell = gth_cell_new ();
278 cell->type = GTH_CELL_TYPE_STRING;
279 cell->value.string = g_string_new (value);
280 e->data[e->top] = cell;
281
282 e->top++;
283 }
284
285
286 void
gth_expr_push_integer(GthExpr * e,int value)287 gth_expr_push_integer (GthExpr *e,
288 int value)
289 {
290 GthCell *cell;
291
292 gth_cell_unref (e->data[e->top]);
293
294 cell = gth_cell_new ();
295 cell->type = GTH_CELL_TYPE_INTEGER;
296 cell->value.integer = value;
297 e->data[e->top] = cell;
298
299 e->top++;
300 }
301
302
303 void
gth_expr_pop(GthExpr * e)304 gth_expr_pop (GthExpr *e)
305 {
306 if (! gth_expr_is_empty (e))
307 e->top--;
308 }
309
310
311 GthCell *
gth_expr_get_pos(GthExpr * e,int pos)312 gth_expr_get_pos (GthExpr *e, int pos)
313 {
314 if ((pos <= 0) || (pos > e->top))
315 return NULL;
316 return e->data[pos - 1];
317 }
318
319
320 GthCell *
gth_expr_get(GthExpr * e)321 gth_expr_get (GthExpr *e)
322 {
323 return gth_expr_get_pos (e, e->top);
324 }
325
326
327 int
gth_expr_get_top(GthExpr * e)328 gth_expr_get_top (GthExpr *e)
329 {
330 return e->top;
331 }
332
333
334 void
gth_expr_set_get_var_value_func(GthExpr * e,GthGetVarValueFunc f,gpointer data)335 gth_expr_set_get_var_value_func (GthExpr *e,
336 GthGetVarValueFunc f,
337 gpointer data)
338 {
339 e->get_var_value_func = f;
340 e->get_var_value_data = data;
341 }
342
343
344 static char *op_name[] = {
345 "ADD",
346 "SUB",
347 "MUL",
348 "DIV",
349 "NEG",
350 "NOT",
351 "AND",
352 "OR",
353 "CMP_EQ",
354 "CMP_NE",
355 "CMP_LT",
356 "CMP_GT",
357 "CMP_LE",
358 "CMP_GE"
359 };
360
361
362 void
gth_expr_print(GthExpr * e)363 gth_expr_print (GthExpr *e)
364 {
365 int i;
366
367 for (i = 1; i <= gth_expr_get_top (e); i++) {
368 GthCell *cell = gth_expr_get_pos (e, i);
369
370 switch (cell->type) {
371 case GTH_CELL_TYPE_VAR:
372 /*g_print ("VAR: %s (%d)\n",
373 cell->value.var,
374 e->get_var_value_func (e,
375 &i,
376 cell->value.var,
377 e->get_var_value_data));*/
378 g_print ("(%d) VAR: %s\n", i, cell->value.var);
379 break;
380
381 case GTH_CELL_TYPE_STRING:
382 g_print ("(%d) STRING: %s\n", i, cell->value.string->str);
383 break;
384
385 case GTH_CELL_TYPE_INTEGER:
386 printf ("(%d) NUM: %d\n", i, cell->value.integer);
387 break;
388
389 case GTH_CELL_TYPE_OP:
390 printf ("(%d) OP: %s\n", i, op_name[cell->value.op]);
391 break;
392 }
393 }
394 }
395
396
397 int
gth_expr_eval(GthExpr * e)398 gth_expr_eval (GthExpr *e)
399 {
400 GthMem *mem;
401 int retval = 0;
402 int i;
403
404 mem = gth_mem_new (MEM_SIZE);
405
406 for (i = 1; i <= gth_expr_get_top (e); i++) {
407 GthCell *cell = gth_expr_get_pos (e, i);
408 int a, b, c;
409
410 switch (cell->type) {
411 case GTH_CELL_TYPE_VAR:
412 gth_mem_push (mem,
413 e->get_var_value_func (e,
414 &i,
415 cell->value.var,
416 e->get_var_value_data));
417 break;
418
419 case GTH_CELL_TYPE_STRING:
420 /* only used as argument for a function */
421 break;
422
423 case GTH_CELL_TYPE_INTEGER:
424 gth_mem_push (mem, cell->value.integer);
425 break;
426
427 case GTH_CELL_TYPE_OP:
428 switch (cell->value.op) {
429 case GTH_OP_NEG:
430 a = gth_mem_pop (mem);
431 gth_mem_push (mem, -a);
432 break;
433
434 case GTH_OP_NOT:
435 a = gth_mem_pop (mem);
436 gth_mem_push (mem, (a == 0) ? 1 : 0);
437 break;
438
439 case GTH_OP_ADD:
440 b = gth_mem_pop (mem);
441 a = gth_mem_pop (mem);
442 c = a + b;
443 gth_mem_push (mem, c);
444 break;
445
446 case GTH_OP_SUB:
447 b = gth_mem_pop (mem);
448 a = gth_mem_pop (mem);
449 c = a - b;
450 gth_mem_push (mem, c);
451 break;
452
453 case GTH_OP_MUL:
454 b = gth_mem_pop (mem);
455 a = gth_mem_pop (mem);
456 c = a * b;
457 gth_mem_push (mem, c);
458 break;
459
460 case GTH_OP_DIV:
461 b = gth_mem_pop (mem);
462 a = gth_mem_pop (mem);
463 c = a / b;
464 gth_mem_push (mem, c);
465 break;
466
467 case GTH_OP_AND:
468 b = gth_mem_pop (mem);
469 a = gth_mem_pop (mem);
470 c = (a != 0) && (b != 0);
471 gth_mem_push (mem, c);
472 break;
473
474 case GTH_OP_OR:
475 b = gth_mem_pop (mem);
476 a = gth_mem_pop (mem);
477 c = (a != 0) || (b != 0);
478 gth_mem_push (mem, c);
479 break;
480
481 case GTH_OP_CMP_EQ:
482 b = gth_mem_pop (mem);
483 a = gth_mem_pop (mem);
484 c = (a == b);
485 gth_mem_push (mem, c);
486 break;
487
488 case GTH_OP_CMP_NE:
489 b = gth_mem_pop (mem);
490 a = gth_mem_pop (mem);
491 c = (a != b);
492 gth_mem_push (mem, c);
493 break;
494
495 case GTH_OP_CMP_LT:
496 b = gth_mem_pop (mem);
497 a = gth_mem_pop (mem);
498 c = (a < b);
499 gth_mem_push (mem, c);
500 break;
501
502 case GTH_OP_CMP_GT:
503 b = gth_mem_pop (mem);
504 a = gth_mem_pop (mem);
505 c = (a > b);
506 gth_mem_push (mem, c);
507 break;
508
509 case GTH_OP_CMP_LE:
510 b = gth_mem_pop (mem);
511 a = gth_mem_pop (mem);
512 c = (a <= b);
513 gth_mem_push (mem, c);
514 break;
515
516 case GTH_OP_CMP_GE:
517 b = gth_mem_pop (mem);
518 a = gth_mem_pop (mem);
519 c = (a >= b);
520 gth_mem_push (mem, c);
521 break;
522 }
523 break;
524 }
525 }
526
527 retval = gth_mem_get (mem);
528
529 gth_mem_free (mem);
530
531 return retval;
532 }
533
534
535 void
gth_expr_list_unref(GList * list)536 gth_expr_list_unref (GList *list)
537 {
538 GList *scan;
539
540 for (scan = list; scan; scan = scan->next)
541 gth_expr_unref ((GthExpr *) scan->data);
542 g_list_free (list);
543 }
544
545
546 /* GthAttribute */
547
548
549 GthAttribute *
gth_attribute_new_expression(const char * name,GthExpr * expr)550 gth_attribute_new_expression (const char *name,
551 GthExpr *expr)
552 {
553 GthAttribute *attribute;
554
555 g_return_val_if_fail (name != NULL, NULL);
556
557 attribute = g_new0 (GthAttribute, 1);
558 attribute->type = GTH_ATTRIBUTE_EXPR;
559 attribute->name = g_strdup (name);
560 attribute->value.expr = gth_expr_ref (expr);
561
562 return attribute;
563 }
564
565
566 GthAttribute*
gth_attribute_new_string(const char * name,const char * string)567 gth_attribute_new_string (const char *name,
568 const char *string)
569 {
570 GthAttribute *attribute;
571
572 g_return_val_if_fail (name != NULL, NULL);
573
574 attribute = g_new0 (GthAttribute, 1);
575 attribute->type = GTH_ATTRIBUTE_STRING;
576 attribute->name = g_strdup (name);
577 if (string != NULL)
578 attribute->value.string = g_strdup (string);
579
580 return attribute;
581 }
582
583
584 void
gth_attribute_free(GthAttribute * attribute)585 gth_attribute_free (GthAttribute *attribute)
586 {
587 g_free (attribute->name);
588 switch (attribute->type) {
589 case GTH_ATTRIBUTE_EXPR:
590 gth_expr_unref (attribute->value.expr);
591 break;
592 case GTH_ATTRIBUTE_STRING:
593 g_free (attribute->value.string);
594 break;
595 }
596 g_free (attribute);
597 }
598
599
600 /* GthCondition */
601
602
603 GthCondition *
gth_condition_new(GthExpr * expr)604 gth_condition_new (GthExpr *expr)
605 {
606 GthCondition *cond;
607
608 cond = g_new0 (GthCondition, 1);
609 cond->expr = gth_expr_ref (expr);
610
611 return cond;
612 }
613
614
615 void
gth_condition_free(GthCondition * cond)616 gth_condition_free (GthCondition *cond)
617 {
618 if (cond == NULL)
619 return;
620 gth_expr_unref (cond->expr);
621 gth_parsed_doc_free (cond->document);
622 g_free (cond);
623 }
624
625
626 void
gth_condition_add_document(GthCondition * cond,GList * document)627 gth_condition_add_document (GthCondition *cond,
628 GList *document)
629 {
630 if (cond->document != NULL)
631 gth_parsed_doc_free (cond->document);
632 cond->document = document;
633 }
634
635
636 /* GthLoop */
637
638
639 GthLoop *
gth_loop_new(GthTagType loop_type)640 gth_loop_new (GthTagType loop_type)
641 {
642 GthLoop *loop;
643
644 loop = g_new0 (GthLoop, 1);
645 loop->type = loop_type;
646
647 return loop;
648 }
649
650
651 void
gth_loop_free(GthLoop * loop)652 gth_loop_free (GthLoop *loop)
653 {
654 if (loop == NULL)
655 return;
656 gth_parsed_doc_free (loop->document);
657 g_free (loop);
658 }
659
660
661 GthTagType
gth_loop_get_type(GthLoop * loop)662 gth_loop_get_type (GthLoop *loop)
663 {
664 return loop->type;
665 }
666
667
668 void
gth_loop_add_document(GthLoop * loop,GList * document)669 gth_loop_add_document (GthLoop *loop,
670 GList *document)
671 {
672 if (loop->document != NULL)
673 gth_parsed_doc_free (loop->document);
674 loop->document = document;
675 }
676
677
678 /* GthRangeLoop */
679
680
681 GthLoop *
gth_range_loop_new(void)682 gth_range_loop_new (void)
683 {
684 GthLoop *loop;
685
686 loop = (GthLoop *) g_new0 (GthRangeLoop, 1);
687 loop->type = GTH_TAG_FOR_EACH_IN_RANGE;
688
689 return loop;
690 }
691
692
693 void
gth_range_loop_free(GthRangeLoop * loop)694 gth_range_loop_free (GthRangeLoop *loop)
695 {
696 g_free (loop->iterator);
697 gth_expr_unref (loop->first_value);
698 gth_expr_unref (loop->last_value);
699 gth_loop_free (GTH_LOOP (loop));
700 }
701
702
703 void
gth_range_loop_set_range(GthRangeLoop * loop,const char * iterator,GthExpr * first_value,GthExpr * last_value)704 gth_range_loop_set_range (GthRangeLoop *loop,
705 const char *iterator,
706 GthExpr *first_value,
707 GthExpr *last_value)
708 {
709 loop->iterator = g_strdup (iterator);
710 loop->first_value = gth_expr_ref (first_value);
711 loop->last_value = gth_expr_ref (last_value);
712 }
713
714
715 /* GthTag */
716
717
718 GthTag *
gth_tag_new(GthTagType type,GList * attributes)719 gth_tag_new (GthTagType type,
720 GList *attributes)
721 {
722 GthTag *tag;
723
724 tag = g_new0 (GthTag, 1);
725 tag->type = type;
726 tag->value.attributes = attributes;
727
728 return tag;
729 }
730
731
732 GthTag *
gth_tag_new_html(const char * html)733 gth_tag_new_html (const char *html)
734 {
735 GthTag *tag;
736
737 tag = g_new0 (GthTag, 1);
738 tag->type = GTH_TAG_HTML;
739 tag->value.html = g_strdup (html);
740
741 return tag;
742 }
743
744
745 GthTag *
gth_tag_new_condition(GList * cond_list)746 gth_tag_new_condition (GList *cond_list)
747 {
748 GthTag *tag;
749
750 tag = g_new0 (GthTag, 1);
751 tag->type = GTH_TAG_IF;
752 tag->value.cond_list = cond_list;
753
754 return tag;
755 }
756
757
758 GthTag *
gth_tag_new_loop(GthLoop * loop)759 gth_tag_new_loop (GthLoop *loop)
760 {
761 GthTag *tag;
762
763 tag = g_new0 (GthTag, 1);
764 tag->type = loop->type;
765 if (loop->type == GTH_TAG_FOR_EACH_IN_RANGE)
766 tag->value.range_loop = (GthRangeLoop *) loop;
767 else
768 tag->value.loop = loop;
769
770 return tag;
771 }
772
773
774 void
gth_tag_add_document(GthTag * tag,GList * document)775 gth_tag_add_document (GthTag *tag,
776 GList *document)
777 {
778 if (tag->document != NULL)
779 gth_parsed_doc_free (tag->document);
780 tag->document = document;
781 }
782
783
784 void
gth_tag_free(GthTag * tag)785 gth_tag_free (GthTag *tag)
786 {
787 if (tag->type == GTH_TAG_HTML) {
788 g_free (tag->value.html);
789 }
790 else if (tag->type == GTH_TAG_IF) {
791 g_list_foreach (tag->value.cond_list,
792 (GFunc) gth_condition_free,
793 NULL);
794 g_list_free (tag->value.cond_list);
795 }
796 else if ((tag->type == GTH_TAG_FOR_EACH_THUMBNAIL_CAPTION)
797 || (tag->type == GTH_TAG_FOR_EACH_IMAGE_CAPTION))
798 {
799 gth_loop_free (tag->value.loop);
800 }
801 else if (tag->type == GTH_TAG_FOR_EACH_IN_RANGE) {
802 gth_range_loop_free (GTH_RANGE_LOOP (tag->value.range_loop));
803 }
804 else {
805 g_list_foreach (tag->value.attributes,
806 (GFunc) gth_attribute_free,
807 NULL);
808 g_list_free (tag->value.attributes);
809 }
810
811 if (tag->document != NULL)
812 gth_parsed_doc_free (tag->document);
813
814 g_free (tag);
815 }
816
817
818 GthTagType
gth_tag_get_type_from_name(const char * tag_name)819 gth_tag_get_type_from_name (const char *tag_name)
820 {
821 if (tag_name == NULL)
822 return GTH_TAG_INVALID;
823
824 if (g_str_equal (tag_name, "header"))
825 return GTH_TAG_HEADER;
826 else if (g_str_equal (tag_name, "footer"))
827 return GTH_TAG_FOOTER;
828 else if (g_str_equal (tag_name, "language"))
829 return GTH_TAG_LANGUAGE;
830 else if (g_str_equal (tag_name, "theme_link"))
831 return GTH_TAG_THEME_LINK;
832 else if (g_str_equal (tag_name, "image"))
833 return GTH_TAG_IMAGE;
834 else if (g_str_equal (tag_name, "image_link"))
835 return GTH_TAG_IMAGE_LINK;
836 else if (g_str_equal (tag_name, "image_idx"))
837 return GTH_TAG_IMAGE_IDX;
838 else if (g_str_equal (tag_name, "image_dim"))
839 return GTH_TAG_IMAGE_DIM;
840 else if (g_str_equal (tag_name, "image_attribute"))
841 return GTH_TAG_IMAGE_ATTRIBUTE;
842 else if (g_str_equal (tag_name, "images"))
843 return GTH_TAG_IMAGES;
844 else if (g_str_equal (tag_name, "file_name"))
845 return GTH_TAG_FILE_NAME;
846 else if (g_str_equal (tag_name, "file_path"))
847 return GTH_TAG_FILE_PATH;
848 else if (g_str_equal (tag_name, "file_size"))
849 return GTH_TAG_FILE_SIZE;
850 else if (g_str_equal (tag_name, "page_link"))
851 return GTH_TAG_PAGE_LINK;
852 else if (g_str_equal (tag_name, "page_idx"))
853 return GTH_TAG_PAGE_IDX;
854 else if (g_str_equal (tag_name, "page_link"))
855 return GTH_TAG_PAGE_LINK;
856 else if (g_str_equal (tag_name, "page_rows"))
857 return GTH_TAG_PAGE_ROWS;
858 else if (g_str_equal (tag_name, "page_cols"))
859 return GTH_TAG_PAGE_COLS;
860 else if (g_str_equal (tag_name, "pages"))
861 return GTH_TAG_PAGES;
862 else if (g_str_equal (tag_name, "thumbnails"))
863 return GTH_TAG_THUMBNAILS;
864 else if (g_str_equal (tag_name, "timestamp"))
865 return GTH_TAG_TIMESTAMP;
866 else if (g_str_equal (tag_name, "translate"))
867 return GTH_TAG_TRANSLATE;
868 else if (g_str_equal (tag_name, "html"))
869 return GTH_TAG_HTML;
870 else if (g_str_equal (tag_name, "set_var"))
871 return GTH_TAG_SET_VAR;
872 else if (g_str_equal (tag_name, "eval"))
873 return GTH_TAG_EVAL;
874 else if (g_str_equal (tag_name, "if"))
875 return GTH_TAG_IF;
876 else if (g_str_equal (tag_name, "for_each_thumbnail_caption"))
877 return GTH_TAG_FOR_EACH_THUMBNAIL_CAPTION;
878 else if (g_str_equal (tag_name, "for_each_image_caption"))
879 return GTH_TAG_FOR_EACH_IMAGE_CAPTION;
880 else if (g_str_equal (tag_name, "for_each_in_range"))
881 return GTH_TAG_FOR_EACH_IN_RANGE;
882 else if (g_str_equal (tag_name, "item_attribute"))
883 return GTH_TAG_ITEM_ATTRIBUTE;
884
885 return GTH_TAG_INVALID;
886 }
887
888
889 const char *
gth_tag_get_name_from_type(GthTagType tag_type)890 gth_tag_get_name_from_type (GthTagType tag_type)
891 {
892 static char *tag_name[] = {
893 "header",
894 "footer",
895 "language",
896 "theme_link",
897 "image",
898 "image_link",
899 "image_idx",
900 "image_dim",
901 "images",
902 "filename",
903 "filepath",
904 "filesize",
905 "page_link",
906 "page_idx",
907 "page_rows",
908 "page_cols",
909 "pages",
910 "thumbnails",
911 "timestamp",
912 "text",
913 "html",
914 "set_var",
915 "eval",
916 "if",
917 "for_each_thumbnail_caption",
918 "for_each_image_caption",
919 "for_each_in_range",
920 "item_attribute"
921 };
922
923 return tag_name[tag_type];
924 }
925
926
927 void
gth_parsed_doc_print_tree(GList * document)928 gth_parsed_doc_print_tree (GList *document)
929 {
930 GList *scan;
931
932 for (scan = document; scan; scan = scan->next) {
933 GthTag *tag = scan->data;
934
935 g_print ("<%s>\n", gth_tag_get_name_from_type (tag->type));
936
937 if ((tag->type != GTH_TAG_HTML) && (tag->type != GTH_TAG_IF)) {
938 GList *scan_arg;
939
940 for (scan_arg = tag->value.attributes; scan_arg; scan_arg = scan_arg->next) {
941 GthAttribute *attribute = scan_arg->data;
942
943 g_print (" %s = ", attribute->name);
944 if (attribute->type == GTH_ATTRIBUTE_STRING)
945 g_print ("%s\n", attribute->value.string);
946 else
947 gth_expr_print (attribute->value.expr);
948 }
949 }
950 }
951 g_print (".\n\n");
952 }
953
954
955 void
gth_parsed_doc_free(GList * document)956 gth_parsed_doc_free (GList *document)
957 {
958 if (document != NULL) {
959 g_list_foreach (document, (GFunc) gth_tag_free, NULL);
960 g_list_free (document);
961 }
962 }
963