1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-token.c
4 * Copyright (C) Sébastien Granjoux 2009 <seb.sfo@free.fr>
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "anjuta-token.h"
21
22 #include "anjuta-debug.h"
23
24 #include <glib-object.h>
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 /**
31 * SECTION:anjuta-token
32 * @title: Anjuta token
33 * @short_description: Anjuta token
34 * @see_also:
35 * @stability: Unstable
36 * @include: libanjuta/anjuta-token.h
37 *
38 * A #AnjutaToken represents a token. It is a sequence of characters associated
39 * with a type representing its meaning. By example, a token can represent
40 * a keyword, a comment, a variable...
41 *
42 * The token can own the string or has only a pointer on some data allocated
43 * somewhere else with a length.
44 *
45 * A token is linked with other tokens using three double linked lists.
46 *
47 * The first list using next and prev fields is used to keep the token in the
48 * order where there are in the file. The first character of the first token is
49 * the first character in the file.
50 *
51 * A second list is used to represent included
52 * files. Such file is represented by a special token in the first list which
53 * has a pointer, named children to a token list. Each token in this secondary
54 * list has a pointer to its parent, it means the token representing the file
55 * where is the token. It looks like a tree. In fact, every file is represented
56 * by a special token, so the root node is normally a file token and has as
57 * children all the token representing the file content. This parent/child list
58 * is used for expanded variable too.
59 *
60 * A third list is used to group several tokens. A token can have a pointer to
61 * another last token. It means that this token is a group starting from this
62 * token to the one indicated by the last field. In addition each token in this
63 * group has a pointer on the first token of the group. This grouping is
64 * independent of the parent/child list. So a group can start in one file and
65 * end in another included file. The grouping can be nested too. Typically
66 * we can have a group representing a command, a sub group representing the
67 * arguments and then one sub group for each argument.
68 */
69
70 /*
71 * A token with its pointer can be put in one of the following case:
72 *
73 * * Simple token:
74 * children = NULL && last = NULL
75 * This is the case of a simple token without any children.
76 *
77 * * Composite token:
78 * children = NULL && last != NULL
79 * This is the case of a token grouping several other tokens, representing
80 * by example an item in a list.
81 *
82 * * Parent token:
83 * children != NULL && last == NULL
84 * This is the case of a token having children, by example a variable where
85 * the children represent the content. Most of the time the value of the
86 * parent token is ignored.
87 *
88 * * Composite parent token:
89 * children != NULL && last != NULL && (last in list)
90 * This case represents a variable which is split into several tokens. The
91 * children represents the content of the variable. The token up to last
92 * corresponds to the variable name. After getting the variable content, the
93 * next token is after the last token of the variable.
94 *
95 * * Composite parent token:
96 * children != NULL && last != NULL && (last in children)
97 * This case would represent a variable which is split into several token
98 * with one inside the children of the variable. This is not possible as
99 * the complete name of the variable is needed to get the children.
100 *
101 * * Composite parent token:
102 * children != NULL && last != NULL && (last in parent)
103 * This case represents a variable split into several token where the
104 * last element is a sibling of one parent of the token. I think this case
105 * is possible.
106 *
107 */
108
109 typedef struct _AnjutaTokenData AnjutaTokenData;
110
111 struct _AnjutaTokenData
112 {
113 AnjutaTokenType type;
114 gint flags;
115 gchar *pos;
116 gsize length;
117 };
118
119 struct _AnjutaToken
120 {
121 AnjutaToken *next;
122 AnjutaToken *prev;
123 AnjutaToken *parent;
124 AnjutaToken *last;
125 AnjutaToken *group;
126 AnjutaToken *children;
127 AnjutaTokenData data;
128 };
129
130 /* Helpers functions
131 *---------------------------------------------------------------------------*/
132
133 /* Private functions
134 *---------------------------------------------------------------------------*/
135
136 static AnjutaToken *
anjuta_token_next_child(AnjutaToken * child,AnjutaToken ** last)137 anjuta_token_next_child (AnjutaToken *child, AnjutaToken **last)
138 {
139 if (child == NULL) return child;
140
141 if (child->children != NULL)
142 {
143 child = child->children;
144 }
145 else
146 {
147 for (;;)
148 {
149 if ((*last == NULL) || (child == *last))
150 {
151 if (child->last == NULL)
152 {
153 child = NULL;
154 break;
155 }
156 *last = child->last;
157 }
158 if (child->next != NULL)
159 {
160 child = child->next;
161 break;
162 }
163 child = child->parent;
164 if (child == NULL) break;
165 }
166 }
167
168 return child;
169 }
170
171 AnjutaToken *
anjuta_token_next_after_children(AnjutaToken * token)172 anjuta_token_next_after_children (AnjutaToken *token)
173 {
174 while (token->last != NULL) token = token->last;
175 while (token->next == NULL)
176 {
177 token = token->parent;
178 if (token == NULL) return NULL;
179 while (token->last != NULL) token = token->last;
180 };
181
182 return token->next;
183 }
184
185 static AnjutaToken *
anjuta_token_copy(AnjutaToken * token)186 anjuta_token_copy (AnjutaToken *token)
187 {
188 AnjutaToken *copy = NULL;
189
190 if (token != NULL)
191 {
192 copy = g_slice_new0 (AnjutaToken);
193 copy->data.type = token->data.type;
194 copy->data.flags = token->data.flags;
195 if ((copy->data.flags & ANJUTA_TOKEN_STATIC) || (token->data.pos == NULL))
196 {
197 copy->data.pos = token->data.pos;
198 }
199 else
200 {
201 copy->data.pos = g_strdup (token->data.pos);
202 }
203 copy->data.length = token->data.length;
204 }
205
206 return copy;
207 }
208
209 /**
210 * anjuta_token_unlink_token:
211 * @token: a #AnjutaToken object.
212 *
213 * Unlink a single token, not the complete item, from the token tree.
214 *
215 * Return value: the removed token tree
216 */
217 static AnjutaToken *
anjuta_token_unlink_token(AnjutaToken * token)218 anjuta_token_unlink_token (AnjutaToken *token)
219 {
220
221 if (token->prev != NULL)
222 {
223 token->prev->next = token->next;
224 }
225 else if ((token->parent != NULL) && (token->parent->children == token))
226 {
227 token->parent->children = token->next;
228 }
229 token->parent = NULL;
230
231 if ((token->group != NULL) && (token->group->last == token))
232 {
233 AnjutaToken *prev;
234
235 for (prev = token->prev; prev != NULL; prev = prev->prev)
236 {
237 if (prev->group == token->group)
238 {
239 /* Find previous token in the same group */
240 token->group->last = prev;
241 break;
242 }
243 else if (prev == token->group)
244 {
245 /* No more token in group */
246 token->group->last = NULL;
247 break;
248 }
249 }
250 }
251
252 if (token->next != NULL)
253 {
254 token->next->prev = token->prev;
255 token->next = NULL;
256 }
257 token->prev = NULL;
258
259 return token;
260 }
261
262 /**
263 * anjuta_token_insert_token_before:
264 * @sibling: a #AnjutaToken object.
265 * @token: a #AnjutaToken object.
266 *
267 * Insert token before sibling.
268 *
269 * Return value: inserted token
270 */
271 static AnjutaToken *
anjuta_token_insert_token_before(AnjutaToken * sibling,AnjutaToken * token)272 anjuta_token_insert_token_before (AnjutaToken *sibling, AnjutaToken *token)
273 {
274 token->prev = sibling->prev;
275 token->next = sibling;
276
277 if (token->prev != NULL)
278 {
279 token->prev->next = token;
280 }
281 sibling->prev = token;
282
283 if ((sibling->parent != NULL) && (sibling->parent->children == sibling))
284 {
285 sibling->parent->children = token;
286 }
287 token->parent = sibling->parent;
288
289 return token;
290 }
291
292 static void
anjuta_token_evaluate_token(AnjutaToken * token,GString * value,gboolean raw)293 anjuta_token_evaluate_token (AnjutaToken *token, GString *value, gboolean raw)
294 {
295 if ((token != NULL) && (token->data.length != 0))
296 {
297 if (!raw)
298 {
299 switch (anjuta_token_get_type (token))
300 {
301 case ANJUTA_TOKEN_COMMENT:
302 case ANJUTA_TOKEN_OPEN_QUOTE:
303 case ANJUTA_TOKEN_CLOSE_QUOTE:
304 case ANJUTA_TOKEN_ESCAPE:
305 case ANJUTA_TOKEN_MACRO:
306 case ANJUTA_TOKEN_EOV:
307 return;
308 default:
309 break;
310 }
311 }
312 g_string_append_len (value, anjuta_token_get_string (token), anjuta_token_get_length (token));
313 }
314 }
315
316 static void
anjuta_token_show(AnjutaToken * token,gint indent,gchar parent)317 anjuta_token_show (AnjutaToken *token, gint indent, gchar parent)
318 {
319 static gchar type[] = "\0";
320 const gchar *string;
321 gsize length;
322
323 type[0] = parent;
324 fprintf (stderr, "%*s%s %p", indent, "", type, token);
325 fprintf (stderr, ": %d ",
326 anjuta_token_get_type (token));
327 string = anjuta_token_get_string (token);
328 length = anjuta_token_get_length (token);
329 if (string == NULL)
330 {
331 /* Value doesn't contain a newline */
332 fprintf (stderr, "(%" G_GSIZE_FORMAT ")", length);
333 }
334 else
335 {
336 const gchar *newline;
337
338 newline = g_strrstr_len (string, length, "\n");
339 if (newline == NULL)
340 {
341 /* Value doesn't contain a newline */
342 fprintf (stderr, "\"%.*s\"",
343 (int)length,
344 string);
345 }
346 else
347 {
348 /* Value contains a newline, take care of indentation */
349 newline++;
350 fprintf (stderr, "\"%.*s",
351 (int)(newline - string),
352 string);
353 for (;;)
354 {
355 length -= newline - string;
356 string = newline;
357
358 newline = g_strrstr_len (string, length, "\n");
359 if (newline == NULL) break;
360
361 newline++;
362 fprintf (stderr, "%*s %.*s",
363 indent, "",
364 (int)(newline - string),
365 string);
366 }
367 fprintf (stderr, "%*s %.*s\"",
368 indent, "",
369 (int)length,
370 string);
371 }
372 }
373 fprintf (stderr, " %p/%p (%p/%p) %s\n",
374 token->last, token->children,
375 token->group, token->parent,
376 anjuta_token_get_flags (token) & ANJUTA_TOKEN_REMOVED ? " (removed)" : "");
377 }
378
379 static AnjutaToken*
anjuta_token_dump_child(AnjutaToken * token,gint indent,gchar type)380 anjuta_token_dump_child (AnjutaToken *token, gint indent, gchar type)
381 {
382 AnjutaToken *last;
383 AnjutaToken *child;
384
385 anjuta_token_show (token, indent, type);
386 indent += 4;
387
388 last = token;
389 if (token->last != NULL)
390 {
391 do
392 {
393 child = last->next;
394 if (child == NULL) break;
395 last = anjuta_token_dump_child (child, indent, '+');
396 }
397 while (child != token->last);
398 }
399
400 if (token->children != NULL)
401 {
402 for (child = token->children; child != NULL; child = child->next)
403 {
404 child = anjuta_token_dump_child (child, indent, '*');
405 }
406 }
407
408 return last;
409 }
410
411 static gboolean
anjuta_token_check_child(AnjutaToken * token,AnjutaToken * parent)412 anjuta_token_check_child (AnjutaToken *token, AnjutaToken *parent)
413 {
414 if (token->parent != parent)
415 {
416 anjuta_token_show (token, 0, 0);
417 fprintf(stderr, "Error: Children has %p as parent instead of %p\n", token->parent, parent);
418 return FALSE;
419 }
420
421 return anjuta_token_check (token);
422 }
423
424 /* Get and set functions
425 *---------------------------------------------------------------------------*/
426
427 void
anjuta_token_set_type(AnjutaToken * token,gint type)428 anjuta_token_set_type (AnjutaToken *token, gint type)
429 {
430 token->data.type = type;
431 }
432
433 gint
anjuta_token_get_type(AnjutaToken * token)434 anjuta_token_get_type (AnjutaToken *token)
435 {
436 return token->data.type;
437 }
438
439 void
anjuta_token_set_flags(AnjutaToken * token,gint flags)440 anjuta_token_set_flags (AnjutaToken *token, gint flags)
441 {
442 AnjutaToken *child;
443 AnjutaToken *last = token->last;
444
445 for (child = token; child != NULL; child = anjuta_token_next_child (child, &last))
446 {
447 child->data.flags |= flags;
448 }
449 }
450
451 void
anjuta_token_clear_flags(AnjutaToken * token,gint flags)452 anjuta_token_clear_flags (AnjutaToken *token, gint flags)
453 {
454 token->data.flags &= ~flags;
455 }
456
457 gint
anjuta_token_get_flags(AnjutaToken * token)458 anjuta_token_get_flags (AnjutaToken *token)
459 {
460 return token->data.flags;
461 }
462
463 void
anjuta_token_set_string(AnjutaToken * token,const gchar * data,gsize length)464 anjuta_token_set_string (AnjutaToken *token, const gchar *data, gsize length)
465 {
466 if (!(token->data.flags & ANJUTA_TOKEN_STATIC))
467 {
468 g_free (token->data.pos);
469 token->data.flags |= ANJUTA_TOKEN_STATIC;
470 }
471 token->data.pos = (gchar *)data;
472 token->data.length = length;
473 }
474
475 const gchar *
anjuta_token_get_string(AnjutaToken * token)476 anjuta_token_get_string (AnjutaToken *token)
477 {
478 return token->data.pos;
479 }
480
481 void
anjuta_token_set_length(AnjutaToken * token,gsize length)482 anjuta_token_set_length (AnjutaToken *token, gsize length)
483 {
484 token->data.length = length;
485 }
486
487 gsize
anjuta_token_get_length(AnjutaToken * token)488 anjuta_token_get_length (AnjutaToken *token)
489 {
490 return token->data.length;
491 }
492
493 /* Basic move functions
494 *---------------------------------------------------------------------------*/
495
496 AnjutaToken *
anjuta_token_next(AnjutaToken * token)497 anjuta_token_next (AnjutaToken *token)
498 {
499 if (token->children != NULL)
500 {
501 return token->children;
502 }
503 else if (token->next != NULL)
504 {
505 return token->next;
506 }
507 else if (token->parent != NULL)
508 {
509 return anjuta_token_next_after_children (token->parent);
510 }
511 else
512 {
513 return NULL;
514 }
515 }
516
517 AnjutaToken *
anjuta_token_previous(AnjutaToken * token)518 anjuta_token_previous (AnjutaToken *token)
519 {
520 if (token->prev != NULL)
521 {
522 return token->prev;
523 }
524 else
525 {
526 return token->parent;
527 }
528 }
529
530 AnjutaToken *
anjuta_token_last(AnjutaToken * token)531 anjuta_token_last (AnjutaToken *token)
532 {
533 AnjutaToken *last;
534
535 for (last = token; last->last != NULL; last = last->last);
536 if (last->children != NULL)
537 {
538 for (last = last->children; last->next != NULL; last = last->next);
539 }
540
541 return last;
542 }
543
544 AnjutaToken *
anjuta_token_parent(AnjutaToken * token)545 anjuta_token_parent (AnjutaToken *token)
546 {
547 return token->parent;
548 }
549
550 AnjutaToken *
anjuta_token_list(AnjutaToken * token)551 anjuta_token_list (AnjutaToken *token)
552 {
553 return token->group;
554 }
555
556 /* Item move functions
557 *---------------------------------------------------------------------------*/
558
559 AnjutaToken *
anjuta_token_last_item(AnjutaToken * list)560 anjuta_token_last_item (AnjutaToken *list)
561 {
562 return list->last;
563 }
564
565 AnjutaToken *
anjuta_token_first_item(AnjutaToken * list)566 anjuta_token_first_item (AnjutaToken *list)
567 {
568 AnjutaToken *first = NULL;
569
570 if (list != NULL)
571 {
572 if (list->children != NULL)
573 {
574 first = list->children;
575 }
576 else if (list->last != NULL)
577 {
578 first = list->next;
579 }
580 }
581
582 return first;
583 }
584
585 AnjutaToken *
anjuta_token_next_item(AnjutaToken * item)586 anjuta_token_next_item (AnjutaToken *item)
587 {
588 AnjutaToken *next = NULL;
589
590 if (item != NULL)
591 {
592 do
593 {
594 next = NULL;
595 if ((item->group == NULL) || (item->group->last != item))
596 {
597 AnjutaToken *last;
598 for (last = item; last->last != NULL; last = last->last);
599 next = anjuta_token_next (last);
600 if ((next != NULL) && (next->group != item->group)) next = NULL;
601 }
602 item = next;
603 }
604 /* Loop if the current item has been deleted */
605 while ((next != NULL) && (anjuta_token_get_flags (next) & ANJUTA_TOKEN_REMOVED));
606 }
607
608 return next;
609 }
610
611 AnjutaToken *
anjuta_token_previous_item(AnjutaToken * item)612 anjuta_token_previous_item (AnjutaToken *item)
613 {
614 AnjutaToken *prev = NULL;
615
616
617 if (item != NULL)
618 {
619 do
620 {
621 for (prev = item->prev; (prev != NULL) && (prev->group != item->group); prev = prev->group);
622 item = prev;
623 }
624 /* Loop if the current item has been deleted */
625 while ((prev != NULL) && (anjuta_token_get_flags (prev) & ANJUTA_TOKEN_REMOVED));
626 }
627
628 return prev;
629 }
630
631 /* Add/Insert/Remove tokens
632 *---------------------------------------------------------------------------*/
633
634 /**
635 * anjuta_token_append_child:
636 * @parent: a #AnjutaToken object used as parent.
637 * @children: a #AnjutaToken object.
638 *
639 * Insert all tokens in children as the last children of the given parent.
640 *
641 * Return value: The first token append.
642 */
643 AnjutaToken *
anjuta_token_append_child(AnjutaToken * parent,AnjutaToken * children)644 anjuta_token_append_child (AnjutaToken *parent, AnjutaToken *children)
645 {
646 AnjutaToken *token;
647 AnjutaToken *last;
648 AnjutaToken *old_group;
649 AnjutaToken *old_parent;
650
651 g_return_val_if_fail (parent != NULL, NULL);
652 g_return_val_if_fail (children != NULL, NULL);
653
654 old_group = children->group;
655 old_parent = children->parent;
656
657 if (parent->children == NULL)
658 {
659 parent->children = children;
660
661 children->prev = NULL;
662 }
663 else
664 {
665 /* Find last children */
666 for (last = parent->children; last->next != NULL;)
667 {
668 if ((last->last != NULL) && (last->last->parent == last->parent))
669 {
670 last = last->last;
671 }
672 else
673 {
674 last = last->next;
675 }
676 }
677
678 last->next = children;
679 children->prev = last;
680 }
681
682 /* Update each token */
683 for (token = children;;)
684 {
685 if (token->parent == old_parent) token->parent = parent;
686 if (token->group == old_group) token->group = parent->group;
687
688 if (token->children != NULL)
689 {
690 token = token->children;
691 }
692 else if (token->next != NULL)
693 {
694 token = token->next;
695 }
696 else
697 {
698 while (token->parent != parent)
699 {
700 token = token->parent;
701 if (token->next != NULL) break;
702 }
703 if (token->next == NULL) break;
704 token = token->next;
705 }
706 }
707
708 return children;
709 }
710
711 /**
712 * anjuta_token_prepend_child:
713 * @parent: a #AnjutaToken object used as parent.
714 * @children: a #AnjutaToken object.
715 *
716 * Insert all tokens in children as the first children of the given parent.
717 *
718 * Return value: The first token append.
719 */
720 AnjutaToken *
anjuta_token_prepend_child(AnjutaToken * parent,AnjutaToken * children)721 anjuta_token_prepend_child (AnjutaToken *parent, AnjutaToken *children)
722 {
723 AnjutaToken *child;
724 AnjutaToken *last = NULL;
725
726 g_return_val_if_fail (parent != NULL, NULL);
727 g_return_val_if_fail (children != NULL, NULL);
728
729 /* Update each token */
730 for (child = children;;)
731 {
732 AnjutaToken *next;
733
734 if (child->parent == children->parent) child->parent = parent;
735 if (child->group == children->group) child->group = parent->group;
736
737 next = anjuta_token_next_child (child, &last);
738 if (next == NULL) break;
739 child = next;
740 }
741
742 child->next = parent->children;
743 if (child->next) child->next->prev = child;
744 parent->children = children;
745
746 return children;
747 }
748
749 /**
750 * anjuta_token_prepend_items:
751 * @list: a #AnjutaToken object used as list.
752 * @item: a #AnjutaToken object.
753 *
754 * Insert all tokens in item as item of the given list.
755 *
756 * Return value: The first token append.
757 */
758 AnjutaToken *
anjuta_token_prepend_items(AnjutaToken * list,AnjutaToken * item)759 anjuta_token_prepend_items (AnjutaToken *list, AnjutaToken *item)
760 {
761 AnjutaToken *token;
762 AnjutaToken *old_group;
763 AnjutaToken *old_parent;
764
765 g_return_val_if_fail (list != NULL, NULL);
766 g_return_val_if_fail (item != NULL, NULL);
767
768 old_group = item->group;
769 old_parent = item->parent;
770
771 /* Update each token */
772 for (token = item;;)
773 {
774 if (token->parent == old_parent) token->parent = list->parent;
775 if (token->group == old_group) token->group = list;
776
777 if (token->children != NULL)
778 {
779 token = token->children;
780 }
781 else if (token->next != NULL)
782 {
783 token = token->next;
784 }
785 else
786 {
787 while (token->parent != list->parent)
788 {
789 token = token->parent;
790 if (token->next != NULL) break;
791 }
792 if (token->next == NULL) break;
793 token = token->next;
794 }
795 }
796
797 token->next = list->next;
798 if (token->next) token->next->prev = token;
799
800 list->next = item;
801 item->prev = list;
802
803 if (list->last == NULL)
804 {
805 while (token->group != list) token = token->group;
806 list->last = token;
807 }
808
809 return item;
810 }
811
812 /**
813 * anjuta_token_insert_after:
814 * @sibling: a #AnjutaToken object.
815 * @list: a #AnjutaToken object.
816 *
817 * Insert all tokens after sibling.
818 *
819 * Return value: The first token inserted.
820 */
821 AnjutaToken *
anjuta_token_insert_after(AnjutaToken * sibling,AnjutaToken * list)822 anjuta_token_insert_after (AnjutaToken *sibling, AnjutaToken *list)
823 {
824 AnjutaToken *last;
825 AnjutaToken *token;
826 AnjutaToken *old_group;
827 AnjutaToken *old_parent;
828
829 g_return_val_if_fail (sibling != NULL, NULL);
830 g_return_val_if_fail (list != NULL, NULL);
831
832 old_group = list->group;
833 old_parent = list->parent;
834
835 /* Update each token */
836 for (token = list;;)
837 {
838 if (token->parent == old_parent) token->parent = sibling->parent;
839 if (token->group == old_group) token->group = sibling->group;
840
841 if (token->children != NULL)
842 {
843 token = token->children;
844 }
845 else if (token->next != NULL)
846 {
847 token = token->next;
848 }
849 else
850 {
851 while (token->parent != sibling->parent)
852 {
853 token = token->parent;
854 if (token->next != NULL) break;
855 }
856 if (token->next == NULL) break;
857 token = token->next;
858 }
859 }
860
861 for (last = sibling; last->last != NULL; last = last->last);
862
863 token->next = last->next;
864 if (token->next) token->next->prev = token;
865
866 last->next = list;
867 list->prev = last;
868
869 if ((sibling->group != NULL) && (sibling->group->last == sibling))
870 {
871 while (token->group != sibling->group) token = token->group;
872 sibling->group->last = token;
873 }
874
875 return list;
876 }
877
878 /**
879 * anjuta_token_insert_before:
880 * @sibling: a #AnjutaToken object.
881 * @list: a #AnjutaToken object.
882 *
883 * Insert all tokens before sibling.
884 *
885 * Return value: The first token inserted.
886 */
887 AnjutaToken *
anjuta_token_insert_before(AnjutaToken * sibling,AnjutaToken * list)888 anjuta_token_insert_before (AnjutaToken *sibling, AnjutaToken *list)
889 {
890 AnjutaToken *last;
891 AnjutaToken *token;
892 AnjutaToken *old_group;
893 AnjutaToken *old_parent;
894
895 g_return_val_if_fail (sibling != NULL, NULL);
896 g_return_val_if_fail (list != NULL, NULL);
897
898 old_group = list->group;
899 old_parent = list->parent;
900
901 /* Update each token */
902 for (token = list;;)
903 {
904 if (token->parent == old_parent) token->parent = sibling->parent;
905 if (token->group == old_group) token->group = sibling->group;
906
907 if (token->children != NULL)
908 {
909 token = token->children;
910 }
911 else if (token->next != NULL)
912 {
913 token = token->next;
914 }
915 else
916 {
917 while (token->parent != sibling->parent)
918 {
919 token = token->parent;
920 if (token->next != NULL) break;
921 }
922 if (token->next == NULL) break;
923 token = token->next;
924 }
925 }
926
927 for (last = sibling; last->last != NULL; last = last->last);
928
929 token->next = sibling;
930 list->prev = sibling->prev;
931 sibling->prev = token;
932
933 if (list->prev) list->prev->next = list;
934
935 if ((list->parent != NULL) && (list->parent->children == sibling)) list->parent->children = list;
936
937 return list;
938 }
939
940 /**
941 * anjuta_token_delete_parent:
942 * @parent: a #AnjutaToken object used as parent.
943 *
944 * Delete only the parent token.
945 *
946 * Return value: the first children
947 */
948 AnjutaToken *
anjuta_token_delete_parent(AnjutaToken * parent)949 anjuta_token_delete_parent (AnjutaToken *parent)
950 {
951 AnjutaToken *token;
952
953 g_return_val_if_fail (parent != NULL, NULL);
954
955 if (parent->children == NULL) return NULL;
956
957 /* Update each token */
958 for (token = parent->children;;)
959 {
960 if (token->parent == parent) token->parent = parent->parent;
961
962 if (token->children != NULL)
963 {
964 token = token->children;
965 }
966 else if (token->next != NULL)
967 {
968 token = token->next;
969 }
970 else
971 {
972 while (token->parent != parent->parent)
973 {
974 token = token->parent;
975 if (token->next != NULL) break;
976 }
977 if (token->next == NULL) break;
978 token = token->next;
979 }
980 }
981
982 token->next = parent->next;
983 if (token->next) token->next->prev = token;
984
985 parent->next = parent->children;
986 parent->children->prev = parent;
987 parent->children = NULL;
988
989 return anjuta_token_free (parent);
990 }
991
992 /* Merge function
993 *---------------------------------------------------------------------------*/
994
995 /* anjuta_token_merge can be used with first or end being a floating token and
996 * on already grouped tokens to change the group organisation */
997 AnjutaToken *
anjuta_token_merge(AnjutaToken * first,AnjutaToken * end)998 anjuta_token_merge (AnjutaToken *first, AnjutaToken *end)
999 {
1000 AnjutaToken *next;
1001
1002 if ((first == end) || (end == NULL)) return first;
1003
1004 /* Insert first or end in the same sequence if it is not already the case */
1005 for (next = first; next != end; next = anjuta_token_next (next))
1006 {
1007 if (next == NULL)
1008 {
1009 if (first->parent == NULL)
1010 {
1011 anjuta_token_insert_before (end, first);
1012 }
1013 else
1014 {
1015 anjuta_token_insert_after (first, end);
1016 }
1017 break;
1018 }
1019 }
1020 first->last = end;
1021 if ((end->group != NULL) && (end->group != first) && (end->group->last == end)) end->group->last = first;
1022 end->group = first;
1023
1024 return first;
1025 }
1026
1027 AnjutaToken *
anjuta_token_merge_own_children(AnjutaToken * group)1028 anjuta_token_merge_own_children (AnjutaToken *group)
1029 {
1030 AnjutaToken *token;
1031 AnjutaToken *next = NULL;
1032
1033 if (group->last != NULL) return group;
1034
1035 if (group->last->last != NULL) group->last = group->last->last;
1036
1037 for (token = anjuta_token_next (group); (token != NULL) && (token != group->last); token = anjuta_token_next (token))
1038 {
1039 if (next == NULL)
1040 {
1041 if (token->last != NULL)
1042 {
1043 next = token->last;
1044 //token->last = NULL;
1045 }
1046 token->group = group;
1047 }
1048 else if (next == token)
1049 {
1050 next = NULL;
1051 }
1052 }
1053
1054 return group;
1055 }
1056
1057 AnjutaToken *
anjuta_token_merge_children(AnjutaToken * first,AnjutaToken * end)1058 anjuta_token_merge_children (AnjutaToken *first, AnjutaToken *end)
1059 {
1060 if (first == NULL)
1061 {
1062 return end;
1063 }
1064 if ((first == end) || (end == NULL))
1065 {
1066 return first;
1067 }
1068
1069 if (first->parent == NULL)
1070 {
1071 first->parent = end->parent;
1072 }
1073 if (first->next == NULL)
1074 {
1075 anjuta_token_insert_before (end, first);
1076 }
1077 anjuta_token_unlink_token (end);
1078 if (end->last != NULL)
1079 {
1080 AnjutaToken *child;
1081
1082 first->last = end->last;
1083 for (child = anjuta_token_next (first); child != first->last; child = anjuta_token_next (child))
1084 {
1085 if (child->group == end) child->group = first;
1086 }
1087 first->last->group = first;
1088 }
1089 end->group = first;
1090 anjuta_token_free (end);
1091
1092 return first;
1093 }
1094
1095 /**
1096 * anjuta_token_merge_previous:
1097 * @list: a #AnjutaToken object representing a list
1098 * @first: a #AnjutaToken object for the new beginning of the list
1099 *
1100 * If the list token is not already linked with first, it is inserted
1101 * just before first.
1102 * If the list token is already linked, it must be in the same list after
1103 * first token. It it possible to have several tokens beweent list and
1104 * first.
1105 *
1106 * Return value: the new list
1107 */
1108 AnjutaToken *
anjuta_token_merge_previous(AnjutaToken * list,AnjutaToken * first)1109 anjuta_token_merge_previous (AnjutaToken *list, AnjutaToken *first)
1110 {
1111 AnjutaToken *token;
1112
1113 if ((first == NULL) || (list == first)) return list;
1114
1115 /* Change group of all tokens from end to first
1116 * if the list is already linked */
1117 if ((list->prev != NULL) || (list->parent != NULL))
1118 {
1119 for (token = first; token != NULL; token = anjuta_token_next_item (token))
1120 {
1121 token->group = list;
1122 }
1123 }
1124
1125 token = anjuta_token_next (list);
1126 anjuta_token_unlink_token (list);
1127 anjuta_token_insert_token_before (first, list);
1128
1129 return list;
1130 }
1131
anjuta_token_split(AnjutaToken * token,guint size)1132 AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
1133 {
1134 if (token->data.length > size)
1135 {
1136 AnjutaToken *copy;
1137
1138 copy = anjuta_token_copy (token);
1139 anjuta_token_insert_before (token, copy);
1140
1141 copy->data.length = size;
1142 if (token->data.flags & ANJUTA_TOKEN_STATIC)
1143 {
1144 token->data.pos += size;
1145 token->data.length -= size;
1146 }
1147 else
1148 {
1149 memcpy(token->data.pos, token->data.pos + size, token->data.length - size);
1150 }
1151
1152 return copy;
1153 }
1154 else
1155 {
1156 return token;
1157 }
1158 }
1159
1160 AnjutaToken *
anjuta_token_cut(AnjutaToken * token,guint pos,guint size)1161 anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
1162 {
1163 AnjutaToken *copy;
1164
1165 copy = anjuta_token_copy (token);
1166
1167 if (pos >= token->data.length)
1168 {
1169 if (!(copy->data.flags & ANJUTA_TOKEN_STATIC))
1170 {
1171 g_free (copy->data.pos);
1172 }
1173 copy->data.pos = NULL;
1174 copy->data.length = 0;
1175 }
1176 if ((pos + size) > token->data.length)
1177 {
1178 size = token->data.length - pos;
1179 }
1180
1181 if (copy->data.flags & ANJUTA_TOKEN_STATIC)
1182 {
1183 copy->data.pos += pos;
1184 }
1185 else
1186 {
1187 memmove(copy->data.pos, copy->data.pos + pos, size);
1188 }
1189 copy->data.length = size;
1190
1191 return copy;
1192 }
1193
1194 static void
concat_token(AnjutaToken * token,gpointer user_data)1195 concat_token (AnjutaToken *token, gpointer user_data)
1196 {
1197 AnjutaToken *first = (AnjutaToken *)user_data;
1198
1199 if (anjuta_token_get_length (token) > 0)
1200 {
1201 if (anjuta_token_get_string (first) == NULL)
1202 {
1203 anjuta_token_set_string (first, anjuta_token_get_string (token), anjuta_token_get_length (token));
1204 }
1205 else if ((first != NULL) && ((anjuta_token_get_string(first) + anjuta_token_get_length (first)) == anjuta_token_get_string (token)))
1206 {
1207 anjuta_token_set_string (first, anjuta_token_get_string (first), anjuta_token_get_length (first) + anjuta_token_get_length (token));
1208 }
1209 else
1210 {
1211 AnjutaToken *new;
1212
1213 new = anjuta_token_new_static_len (ANJUTA_TOKEN_CONTENT, anjuta_token_get_string (token), anjuta_token_get_length (token));
1214 anjuta_token_insert_after (first, new);
1215 anjuta_token_merge (first, new);
1216 }
1217 }
1218 }
1219
1220
1221 AnjutaToken *
anjuta_token_concat(AnjutaToken * token)1222 anjuta_token_concat(AnjutaToken *token)
1223 {
1224 AnjutaToken *new;
1225
1226 new = anjuta_token_new_static (ANJUTA_TOKEN_CONTENT, NULL);
1227 anjuta_token_foreach_token (token, concat_token, new);
1228
1229 anjuta_token_insert_token_before (token, new);
1230 anjuta_token_free (token);
1231
1232 return new;
1233 }
1234
1235 /* Token foreach
1236 *---------------------------------------------------------------------------*/
1237
1238 void
anjuta_token_foreach_token(AnjutaToken * token,AnjutaTokenForeachFunc func,gpointer user_data)1239 anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1240 {
1241 if (token != NULL)
1242 {
1243 AnjutaToken *last_token;
1244 gint child = 0;
1245
1246 last_token = token->last == NULL ? token : token->last;
1247 while (token != NULL)
1248 {
1249 if (child == 0) func (token, user_data);
1250
1251 /* Check if we have found the last token */
1252 if (token == last_token)
1253 {
1254 /* Find last token */
1255 if (token->last == NULL)
1256 {
1257 break;
1258 }
1259 /* Last token still include additional tokens */
1260 last_token = token->last;
1261 }
1262
1263 if (token->children != NULL)
1264 {
1265 /* Check children, only for last token */
1266 child++;
1267 token = token->children;
1268 }
1269 else if (token->next != NULL)
1270 {
1271 /* Get next sibling */
1272 token = token->next;
1273 }
1274 else
1275 {
1276 /* Get parent */
1277 for (;;)
1278 {
1279 child--;
1280 token = token->parent;
1281 if (token == NULL) break;
1282 if (token->next != NULL)
1283 {
1284 token = token->next;
1285 break;
1286 }
1287 }
1288 }
1289 }
1290 }
1291
1292 return;
1293 }
1294
1295 void
anjuta_token_foreach_content(AnjutaToken * token,AnjutaTokenForeachFunc func,gpointer user_data)1296 anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1297 {
1298 if (token != NULL)
1299 {
1300 AnjutaToken *last_parent; /* If not NULL, token belong to a parent and
1301 * are not taken into account */
1302 AnjutaToken *last_token;
1303 gboolean expand = TRUE;
1304
1305 last_parent = NULL;
1306 last_token = token->last == NULL ? token : token->last;
1307 for (;;)
1308 {
1309 if (expand && (token->children != NULL))
1310 {
1311 /* Children of the last token does not belong to the group */
1312 if (token == last_token)
1313 {
1314 /* Find last token */
1315 if (token->last == NULL)
1316 {
1317 break;
1318 }
1319 /* Last token still include additional tokens */
1320 last_token = token->last;
1321 }
1322
1323 /* Enumerate children */
1324 token = token->children;
1325 }
1326 else
1327 {
1328 if (token->children == NULL)
1329 {
1330 /* Take into account only the content of token having no children */
1331 if (last_parent == NULL)
1332 {
1333 /* Take into account only the content of group having no children */
1334 func (token, user_data);
1335 }
1336 }
1337
1338 /* Check if we have found the last token */
1339 if (token == last_token)
1340 {
1341 /* Find last token */
1342 if (token->last == NULL)
1343 {
1344 break;
1345 }
1346 /* Last token still include additional tokens */
1347 last_token = token->last;
1348 }
1349
1350 if (token == last_parent)
1351 {
1352 /* Find last parent */
1353 if (token->last == NULL)
1354 {
1355 /* Found complete group having children */
1356 last_parent = NULL;
1357 }
1358 else
1359 {
1360 /* Parent group has additional token */
1361 last_parent = token->last;
1362 }
1363 }
1364
1365 if (token->next != NULL)
1366 {
1367 /* Get next sibling */
1368 token = token->next;
1369 expand = TRUE;
1370 }
1371 else
1372 {
1373 /* Get parent */
1374 token = token->parent;
1375 expand = FALSE;
1376 if (token == NULL) break;
1377 last_parent = token->last;
1378 }
1379 }
1380 }
1381 }
1382
1383 return;
1384 }
1385
1386 static void
anjuta_token_foreach_container(AnjutaToken * token,AnjutaTokenForeachFunc func,gpointer user_data)1387 anjuta_token_foreach_container (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1388 {
1389 if (token != NULL)
1390 {
1391 AnjutaToken *parent; /* If not NULL, token belong to a parent and
1392 * are not taken into account */
1393 AnjutaToken *last_token;
1394 gboolean expand = TRUE;
1395
1396 parent = NULL;
1397 last_token = token->last == NULL ? token : token->last;
1398 for (;;)
1399 {
1400 /* Take into account only the content of parent token */
1401 if (expand && (parent == NULL))
1402 {
1403 func (token, user_data);
1404 }
1405 if (expand && (token->children != NULL))
1406 {
1407 if (parent == NULL) parent = token;
1408 /* Enumerate children */
1409 token = token->children;
1410 }
1411 else
1412 {
1413 /* Check if we have found the last token */
1414 if (token == last_token)
1415 {
1416 /* Find last token */
1417 if (token->last == NULL)
1418 {
1419 break;
1420 }
1421 /* Last token still include additional tokens */
1422 last_token = token->last;
1423 }
1424
1425 if (token->next != NULL)
1426 {
1427 /* Get next sibling */
1428 token = token->next;
1429 expand = TRUE;
1430 }
1431 else
1432 {
1433 /* Get parent */
1434 token = token->parent;
1435 if (token == parent) parent = NULL;
1436 expand = FALSE;
1437 }
1438 }
1439 }
1440 }
1441
1442 return;
1443 }
1444
1445 AnjutaToken *
anjuta_token_foreach_post_order(AnjutaToken * token,AnjutaTokenForeachFunc func,gpointer user_data)1446 anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1447 {
1448 if (token != NULL)
1449 {
1450 AnjutaToken *last_parent; /* If not NULL, token belong to a parent */
1451 AnjutaToken *last_token;
1452 AnjutaToken buffer; /* Temporary token allowing func to destroy
1453 * the current token */
1454 gboolean expand = TRUE;
1455
1456 last_parent = NULL;
1457 last_token = token->last == NULL ? token : token->last;
1458 while (token != NULL)
1459 {
1460 if (expand && (token->children != NULL))
1461 {
1462 /* Check if we have found the last token */
1463 if (token == last_token)
1464 {
1465 /* Find last token */
1466 if (token->last == NULL)
1467 {
1468 break;
1469 }
1470 /* Last token still include additional tokens */
1471 last_token = token->last;
1472 }
1473
1474 /* Enumerate children */
1475 token = token->children;
1476 }
1477 else
1478 {
1479 /* Save token data in case it is destroyed */
1480 memcpy (&buffer, token, sizeof (buffer));
1481 /* Take into account all token */
1482 func (token, user_data);
1483
1484 /* Check if we have found the last token */
1485 if (token == last_token)
1486 {
1487 /* Find last token */
1488 if (buffer.last == NULL)
1489 {
1490 token = &buffer;
1491 break;
1492 }
1493 /* Last token still include additional tokens */
1494 last_token = buffer.last;
1495 }
1496
1497 if (token == last_parent)
1498 {
1499 /* Find last parent */
1500 if (buffer.last == NULL)
1501 {
1502 /* Found complete group having children */
1503 last_parent = NULL;
1504 }
1505 else
1506 {
1507 /* Parent group has additional token */
1508 last_parent = buffer.last;
1509 }
1510 }
1511
1512 if (buffer.next != NULL)
1513 {
1514 /* Get next sibling */
1515 token = buffer.next;
1516 expand = TRUE;
1517 }
1518 else
1519 {
1520 /* Get parent */
1521 token = buffer.parent;
1522 if (token != NULL) last_parent = token->last;
1523 expand = FALSE;
1524 }
1525 }
1526 }
1527
1528 while ((token != NULL) && (token->next == NULL))
1529 {
1530 token = token->parent;
1531 };
1532
1533 if (token != NULL) token = token->next;
1534 }
1535
1536 return token;
1537 }
1538
1539 /* Token evaluation
1540 *---------------------------------------------------------------------------*/
1541
1542 static void
evaluate_token(AnjutaToken * token,gpointer user_data)1543 evaluate_token (AnjutaToken *token, gpointer user_data)
1544 {
1545 GString *value = (GString *)user_data;
1546
1547 anjuta_token_evaluate_token (token, value, FALSE);
1548 }
1549
1550
1551 gchar *
anjuta_token_evaluate(AnjutaToken * token)1552 anjuta_token_evaluate (AnjutaToken *token)
1553 {
1554 GString *value = g_string_new (NULL);
1555
1556 anjuta_token_foreach_content (token, evaluate_token, value);
1557
1558 /* Return NULL and free data for an empty string */
1559 return g_string_free (value, *(value->str) == '\0');
1560 }
1561
1562 /* Does not evaluate content if token is a variable */
1563 gchar *
anjuta_token_evaluate_name(AnjutaToken * token)1564 anjuta_token_evaluate_name (AnjutaToken *token)
1565 {
1566 GString *value = g_string_new (NULL);
1567
1568 anjuta_token_foreach_container (token, evaluate_token, value);
1569
1570 /* Return NULL and free data for an empty string */
1571 return g_string_free (value, *(value->str) == '\0');
1572 }
1573
1574 gboolean
anjuta_token_is_empty(AnjutaToken * token)1575 anjuta_token_is_empty (AnjutaToken *token)
1576 {
1577 return (token == NULL) || ((token->data.length == 0) && (token->last == NULL) && (token->children == NULL));
1578 }
1579
1580
1581 /* Other functions
1582 *---------------------------------------------------------------------------*/
1583
1584 gboolean
anjuta_token_compare(AnjutaToken * toka,AnjutaToken * tokb)1585 anjuta_token_compare (AnjutaToken *toka, AnjutaToken *tokb)
1586 {
1587 if (tokb->data.type)
1588 {
1589 if (tokb->data.type != toka->data.type) return FALSE;
1590 }
1591
1592 if (tokb->data.type != ANJUTA_TOKEN_NONE)
1593 {
1594 if (tokb->data.length != 0)
1595 {
1596 if (toka->data.length != tokb->data.length) return FALSE;
1597
1598 if ((toka->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE) && (tokb->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE))
1599 {
1600 if (g_ascii_strncasecmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1601 }
1602 else
1603 {
1604 if (strncmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1605 }
1606 }
1607 }
1608
1609 if (tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS)
1610 {
1611 if ((toka->data.flags & tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS) == 0)
1612 return FALSE;
1613 }
1614
1615 return TRUE;
1616 }
1617
1618 void
anjuta_token_dump(AnjutaToken * token)1619 anjuta_token_dump (AnjutaToken *token)
1620 {
1621 if (token == NULL) return;
1622
1623 anjuta_token_dump_child (token, 0, 0);
1624 }
1625
1626 void
anjuta_token_dump_link(AnjutaToken * token)1627 anjuta_token_dump_link (AnjutaToken *token)
1628 {
1629 AnjutaToken *last = token;
1630
1631 while (last->last != NULL) last = last->last;
1632
1633 for (; token != last; token = anjuta_token_next (token))
1634 {
1635 anjuta_token_show (token, 0, 0);
1636 }
1637 }
1638
1639 gboolean
anjuta_token_check(AnjutaToken * token)1640 anjuta_token_check (AnjutaToken *token)
1641 {
1642 if ((token->children != NULL) && (token->last != NULL))
1643 {
1644 anjuta_token_show (token, 0, 0);
1645 fprintf(stderr, "Error: Previous token has both non NULL children and last\n");
1646
1647 return FALSE;
1648 }
1649
1650 if (token->children != NULL)
1651 {
1652 AnjutaToken *child;
1653
1654 for (child = token->children; child != NULL; child = child->next)
1655 {
1656 if (!anjuta_token_check_child (child, token)) return FALSE;
1657 }
1658 }
1659
1660 if (token->last != NULL)
1661 {
1662 AnjutaToken *child;
1663
1664 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (child))
1665 {
1666 if (!anjuta_token_check (child)) return FALSE;
1667 if (child == token->last) break;
1668 }
1669 }
1670
1671 return TRUE;
1672 }
1673
1674 /* Constructor & Destructor
1675 *---------------------------------------------------------------------------*/
1676
anjuta_token_new_string(AnjutaTokenType type,const gchar * value)1677 AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const gchar *value)
1678 {
1679 AnjutaToken *token;
1680
1681 if (value == NULL)
1682 {
1683 token = anjuta_token_new_static (type, NULL);
1684 }
1685 else
1686 {
1687 token = g_slice_new0 (AnjutaToken);
1688 token->data.type = type & ANJUTA_TOKEN_TYPE;
1689 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1690 token->data.pos = g_strdup (value);
1691 token->data.length = strlen (value);
1692 }
1693
1694 return token;
1695 }
1696
1697 AnjutaToken*
anjuta_token_new_string_len(AnjutaTokenType type,gchar * value,gsize length)1698 anjuta_token_new_string_len (AnjutaTokenType type, gchar *value, gsize length)
1699 {
1700 AnjutaToken *token;
1701
1702 if (value == NULL)
1703 {
1704 token = anjuta_token_new_static (type, NULL);
1705 }
1706 else
1707 {
1708 token = g_slice_new0 (AnjutaToken);
1709 token->data.type = type & ANJUTA_TOKEN_TYPE;
1710 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1711 token->data.pos = value;
1712 token->data.length = length;
1713 }
1714
1715 return token;
1716 }
1717
1718 AnjutaToken *
anjuta_token_new_static_len(gint type,const gchar * pos,gsize length)1719 anjuta_token_new_static_len (gint type, const gchar *pos, gsize length)
1720 {
1721 AnjutaToken *token;
1722
1723 token = g_slice_new0 (AnjutaToken);
1724 token->data.type = type & ANJUTA_TOKEN_TYPE;
1725 token->data.flags = (type & ANJUTA_TOKEN_FLAGS) | ANJUTA_TOKEN_STATIC;
1726 token->data.pos = (gchar *)pos;
1727 token->data.length = length;
1728
1729 return token;
1730 };
1731
anjuta_token_new_static(AnjutaTokenType type,const char * value)1732 AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const char *value)
1733 {
1734 return anjuta_token_new_static_len (type, value, value == NULL ? 0 : strlen (value));
1735 }
1736
1737 AnjutaToken*
anjuta_token_free_children(AnjutaToken * token)1738 anjuta_token_free_children (AnjutaToken *token)
1739 {
1740 AnjutaToken *child;
1741 AnjutaToken *last;
1742
1743 if (token == NULL) return NULL;
1744
1745 for (child = token->children; child != NULL; child = token->children)
1746 {
1747 anjuta_token_free (child);
1748 }
1749 token->children = NULL;
1750
1751 if (token->last != NULL)
1752 {
1753 last = token->last;
1754 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (token))
1755 {
1756 anjuta_token_free (child);
1757 if (child == last) break;
1758 }
1759 }
1760 token->last = NULL;
1761
1762 return token;
1763 }
1764
1765 static void
free_token(AnjutaToken * token,gpointer user_data)1766 free_token (AnjutaToken *token, gpointer user_data)
1767 {
1768 anjuta_token_unlink_token (token);
1769 if ((token->data.pos != NULL) && !(token->data.flags & ANJUTA_TOKEN_STATIC))
1770 {
1771 g_free (token->data.pos);
1772 }
1773 g_slice_free (AnjutaToken, token);
1774 }
1775
1776
1777 AnjutaToken*
anjuta_token_free(AnjutaToken * token)1778 anjuta_token_free (AnjutaToken *token)
1779 {
1780 AnjutaToken *next;
1781
1782 if (token == NULL) return NULL;
1783
1784 next = anjuta_token_foreach_post_order (token, free_token, NULL);
1785
1786 return next;
1787 }
1788