document-manager: Fixes on find in files
[anjuta.git] / libanjuta / anjuta-token.c
blobba7cb6922d7c14cfc9f6e2ccd84a3054fb8d6b71
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>
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.
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.
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/>.
20 #include "anjuta-token.h"
22 #include "anjuta-debug.h"
24 #include <glib-object.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
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
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...
42 * The token can own the string or has only a pointer on some data allocated
43 * somewhere else with a length.
45 * A token is linked with other tokens using three double linked lists.
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.
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.
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.
71 * A token with its pointer can be put in one of the following case:
73 * * Simple token:
74 * children = NULL && last = NULL
75 * This is the case of a simple token without any children.
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.
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.
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.
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.
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.
109 typedef struct _AnjutaTokenData AnjutaTokenData;
111 struct _AnjutaTokenData
113 AnjutaTokenType type;
114 gint flags;
115 gchar *pos;
116 gsize length;
119 struct _AnjutaToken
121 AnjutaToken *next;
122 AnjutaToken *prev;
123 AnjutaToken *parent;
124 AnjutaToken *last;
125 AnjutaToken *group;
126 AnjutaToken *children;
127 AnjutaTokenData data;
130 /* Helpers functions
131 *---------------------------------------------------------------------------*/
133 /* Private functions
134 *---------------------------------------------------------------------------*/
136 static AnjutaToken *
137 anjuta_token_next_child (AnjutaToken *child, AnjutaToken **last)
139 if (child == NULL) return child;
141 if (child->children != NULL)
143 child = child->children;
145 else
147 for (;;)
149 if ((*last == NULL) || (child == *last))
151 if (child->last == NULL)
153 child = NULL;
154 break;
156 *last = child->last;
158 if (child->next != NULL)
160 child = child->next;
161 break;
163 child = child->parent;
167 return child;
170 AnjutaToken *
171 anjuta_token_next_after_children (AnjutaToken *token)
173 while (token->next == NULL)
175 token = token->parent;
176 if (token == NULL) return NULL;
179 return token->next;
182 static AnjutaToken *
183 anjuta_token_copy (AnjutaToken *token)
185 AnjutaToken *copy = NULL;
187 if (token != NULL)
189 copy = g_slice_new0 (AnjutaToken);
190 copy->data.type = token->data.type;
191 copy->data.flags = token->data.flags;
192 if ((copy->data.flags & ANJUTA_TOKEN_STATIC) || (token->data.pos == NULL))
194 copy->data.pos = token->data.pos;
196 else
198 copy->data.pos = g_strdup (token->data.pos);
200 copy->data.length = token->data.length;
203 return copy;
207 * anjuta_token_unlink_token:
208 * @token: a #AnjutaToken object.
210 * Unlink a single token, not the complete item, from the token tree.
212 * Return value: the removed token tree
214 static AnjutaToken *
215 anjuta_token_unlink_token (AnjutaToken *token)
218 if (token->prev != NULL)
220 token->prev->next = token->next;
222 else if ((token->parent != NULL) && (token->parent->children == token))
224 token->parent->children = token->next;
226 token->parent = NULL;
228 if ((token->group != NULL) && (token->group->last == token))
230 AnjutaToken *prev;
232 for (prev = token->prev; prev != NULL; prev = prev->prev)
234 if (prev->group == token->group)
236 /* Find previous token in the same group */
237 token->group->last = prev;
238 break;
240 else if (prev == token->group)
242 /* No more token in group */
243 token->group->last = NULL;
244 break;
249 if (token->next != NULL)
251 token->next->prev = token->prev;
252 token->next = NULL;
254 token->prev = NULL;
256 return token;
260 * anjuta_token_insert_token_before:
261 * @sibling: a #AnjutaToken object.
262 * @token: a #AnjutaToken object.
264 * Insert token before sibling.
266 * Return value: inserted token
268 static AnjutaToken *
269 anjuta_token_insert_token_before (AnjutaToken *sibling, AnjutaToken *token)
271 token->prev = sibling->prev;
272 token->next = sibling;
274 if (token->prev != NULL)
276 token->prev->next = token;
278 sibling->prev = token;
280 if ((sibling->parent != NULL) && (sibling->parent->children == sibling))
282 sibling->parent->children = token;
284 token->parent = sibling->parent;
286 return token;
289 static void
290 anjuta_token_evaluate_token (AnjutaToken *token, GString *value, gboolean raw)
292 if ((token != NULL) && (token->data.length != 0))
294 if (!raw)
296 switch (anjuta_token_get_type (token))
298 case ANJUTA_TOKEN_COMMENT:
299 case ANJUTA_TOKEN_OPEN_QUOTE:
300 case ANJUTA_TOKEN_CLOSE_QUOTE:
301 case ANJUTA_TOKEN_ESCAPE:
302 case ANJUTA_TOKEN_MACRO:
303 case ANJUTA_TOKEN_EOV:
304 return;
305 default:
306 break;
309 g_string_append_len (value, anjuta_token_get_string (token), anjuta_token_get_length (token));
313 static void
314 anjuta_token_show (AnjutaToken *token, gint indent, gchar parent)
316 static gchar type[] = "\0";
317 const gchar *string;
318 gsize length;
320 type[0] = parent;
321 fprintf (stderr, "%*s%s %p", indent, "", type, token);
322 fprintf (stderr, ": %d ",
323 anjuta_token_get_type (token));
324 string = anjuta_token_get_string (token);
325 length = anjuta_token_get_length (token);
326 if (string == NULL)
328 /* Value doesn't contain a newline */
329 fprintf (stderr, "(%lu)", length);
331 else
333 const gchar *newline;
335 newline = g_strrstr_len (string, length, "\n");
336 if (newline == NULL)
338 /* Value doesn't contain a newline */
339 fprintf (stderr, "\"%.*s\"",
340 length,
341 string);
343 else
345 /* Value contains a newline, take care of indentation */
346 newline++;
347 fprintf (stderr, "\"%.*s",
348 newline - string,
349 string);
350 for (;;)
352 length -= newline - string;
353 string = newline;
355 newline = g_strrstr_len (string, length, "\n");
356 if (newline == NULL) break;
358 newline++;
359 fprintf (stderr, "%*s %.*s",
360 indent, "",
361 newline - string,
362 string);
364 fprintf (stderr, "%*s %.*s\"",
365 indent, "",
366 length,
367 string);
370 fprintf (stderr, " %p/%p (%p/%p) %s\n",
371 token->last, token->children,
372 token->group, token->parent,
373 anjuta_token_get_flags (token) & ANJUTA_TOKEN_REMOVED ? " (removed)" : "");
376 static AnjutaToken*
377 anjuta_token_dump_child (AnjutaToken *token, gint indent, gchar type)
379 AnjutaToken *last;
380 AnjutaToken *child;
382 anjuta_token_show (token, indent, type);
383 indent += 4;
385 last = token;
386 if (token->last != NULL)
390 child = last->next;
391 if (child == NULL) break;
392 last = anjuta_token_dump_child (child, indent, '+');
394 while (child != token->last);
397 if (token->children != NULL)
399 for (child = token->children; child != NULL; child = child->next)
401 child = anjuta_token_dump_child (child, indent, '*');
405 return last;
408 static gboolean
409 anjuta_token_check_child (AnjutaToken *token, AnjutaToken *parent)
411 if (token->parent != parent)
413 anjuta_token_show (token, 0, 0);
414 fprintf(stderr, "Error: Children has %p as parent instead of %p\n", token->parent, parent);
415 return FALSE;
418 return anjuta_token_check (token);
421 /* Get and set functions
422 *---------------------------------------------------------------------------*/
424 void
425 anjuta_token_set_type (AnjutaToken *token, gint type)
427 token->data.type = type;
430 gint
431 anjuta_token_get_type (AnjutaToken *token)
433 return token->data.type;
436 void
437 anjuta_token_set_flags (AnjutaToken *token, gint flags)
439 AnjutaToken *child;
440 AnjutaToken *last = token->last;
442 for (child = token; child != NULL; child = anjuta_token_next_child (child, &last))
444 child->data.flags |= flags;
448 void
449 anjuta_token_clear_flags (AnjutaToken *token, gint flags)
451 token->data.flags &= ~flags;
454 gint
455 anjuta_token_get_flags (AnjutaToken *token)
457 return token->data.flags;
460 void
461 anjuta_token_set_string (AnjutaToken *token, const gchar *data, gsize length)
463 if (!(token->data.flags & ANJUTA_TOKEN_STATIC))
465 g_free (token->data.pos);
466 token->data.flags |= ANJUTA_TOKEN_STATIC;
468 token->data.pos = (gchar *)data;
469 token->data.length = length;
472 const gchar *
473 anjuta_token_get_string (AnjutaToken *token)
475 return token->data.pos;
478 void
479 anjuta_token_set_length (AnjutaToken *token, gsize length)
481 token->data.length = length;
484 gsize
485 anjuta_token_get_length (AnjutaToken *token)
487 return token->data.length;
490 /* Basic move functions
491 *---------------------------------------------------------------------------*/
493 AnjutaToken *
494 anjuta_token_next (AnjutaToken *token)
496 if (token->children != NULL)
498 return token->children;
500 else if (token->next != NULL)
502 return token->next;
504 else if (token->parent != NULL)
506 return anjuta_token_next_after_children (token->parent);
508 else
510 return NULL;
514 AnjutaToken *
515 anjuta_token_previous (AnjutaToken *token)
517 if (token->prev != NULL)
519 return token->prev;
521 else
523 return token->parent;
527 AnjutaToken *
528 anjuta_token_last (AnjutaToken *token)
530 AnjutaToken *last;
532 for (last = token; last->last != NULL; last = last->last);
533 if (last->children != NULL)
535 for (last = last->children; last->next != NULL; last = last->next);
538 return last;
541 AnjutaToken *
542 anjuta_token_parent (AnjutaToken *token)
544 return token->parent;
547 AnjutaToken *
548 anjuta_token_list (AnjutaToken *token)
550 return token->group;
553 /* Item move functions
554 *---------------------------------------------------------------------------*/
556 AnjutaToken *
557 anjuta_token_last_item (AnjutaToken *list)
559 return list->last;
562 AnjutaToken *
563 anjuta_token_first_item (AnjutaToken *list)
565 AnjutaToken *first = NULL;
567 if (list != NULL)
569 if (list->children != NULL)
571 first = list->children;
573 else if (list->last != NULL)
575 first = list->next;
579 return first;
582 AnjutaToken *
583 anjuta_token_next_item (AnjutaToken *item)
585 AnjutaToken *next;
587 if (item != NULL)
591 next = NULL;
592 if ((item->group == NULL) || (item->group->last != item))
594 AnjutaToken *last;
595 for (last = item; last->last != NULL; last = last->last);
596 next = anjuta_token_next (last);
597 if ((next != NULL) && (next->group != item->group)) next = NULL;
599 item = next;
601 /* Loop if the current item has been deleted */
602 while ((next != NULL) && (anjuta_token_get_flags (next) & ANJUTA_TOKEN_REMOVED));
605 return next;
608 AnjutaToken *
609 anjuta_token_previous_item (AnjutaToken *item)
611 AnjutaToken *prev = NULL;
614 if (item != NULL)
618 for (prev = item->prev; (prev != NULL) && (prev->group != item->group); prev = prev->group);
619 item = prev;
621 /* Loop if the current item has been deleted */
622 while ((prev != NULL) && (anjuta_token_get_flags (prev) & ANJUTA_TOKEN_REMOVED));
625 return prev;
628 /* Add/Insert/Remove tokens
629 *---------------------------------------------------------------------------*/
632 * anjuta_token_append_child:
633 * @parent: a #AnjutaToken object used as parent.
634 * @children: a #AnjutaToken object.
636 * Insert all tokens in children as the last children of the given parent.
638 * Return value: The first token append.
640 AnjutaToken *
641 anjuta_token_append_child (AnjutaToken *parent, AnjutaToken *children)
643 AnjutaToken *token;
644 AnjutaToken *last;
645 AnjutaToken *old_group;
646 AnjutaToken *old_parent;
648 g_return_val_if_fail (parent != NULL, NULL);
649 g_return_val_if_fail (children != NULL, NULL);
651 old_group = children->group;
652 old_parent = children->parent;
654 if (parent->children == NULL)
656 parent->children = children;
658 children->prev = NULL;
660 else
662 /* Find last children */
663 for (last = parent->children; last->next != NULL;)
665 if ((last->last != NULL) && (last->last->parent == last->parent))
667 last = last->last;
669 else
671 last = last->next;
675 last->next = children;
676 children->prev = last;
679 /* Update each token */
680 for (token = children;;)
682 if (token->parent == old_parent) token->parent = parent;
683 if (token->group == old_group) token->group = parent->group;
685 if (token->children != NULL)
687 token = token->children;
689 else if (token->next != NULL)
691 token = token->next;
693 else
695 while (token->parent != parent)
697 token = token->parent;
698 if (token->next != NULL) break;
700 if (token->next == NULL) break;
701 token = token->next;
705 return children;
709 * anjuta_token_prepend_child:
710 * @parent: a #AnjutaToken object used as parent.
711 * @children: a #AnjutaToken object.
713 * Insert all tokens in children as the first children of the given parent.
715 * Return value: The first token append.
717 AnjutaToken *
718 anjuta_token_prepend_child (AnjutaToken *parent, AnjutaToken *children)
720 AnjutaToken *child;
721 AnjutaToken *last = NULL;
723 g_return_val_if_fail (parent != NULL, NULL);
724 g_return_val_if_fail (children != NULL, NULL);
726 /* Update each token */
727 for (child = children;;)
729 AnjutaToken *next;
731 if (child->parent == children->parent) child->parent = parent;
732 if (child->group == children->group) child->group = parent->group;
734 next = anjuta_token_next_child (child, &last);
735 if (next == NULL) break;
736 child = next;
739 child->next = parent->children;
740 if (child->next) child->next->prev = child;
741 parent->children = children;
743 return children;
747 * anjuta_token_prepend_items:
748 * @list: a #AnjutaToken object used as list.
749 * @item: a #AnjutaToken object.
751 * Insert all tokens in item as item of the given list.
753 * Return value: The first token append.
755 AnjutaToken *
756 anjuta_token_prepend_items (AnjutaToken *list, AnjutaToken *item)
758 AnjutaToken *token;
759 AnjutaToken *old_group;
760 AnjutaToken *old_parent;
762 g_return_val_if_fail (list != NULL, NULL);
763 g_return_val_if_fail (item != NULL, NULL);
765 old_group = item->group;
766 old_parent = item->parent;
768 /* Update each token */
769 for (token = item;;)
771 if (token->parent == old_parent) token->parent = list->parent;
772 if (token->group == old_group) token->group = list;
774 if (token->children != NULL)
776 token = token->children;
778 else if (token->next != NULL)
780 token = token->next;
782 else
784 while (token->parent != list->parent)
786 token = token->parent;
787 if (token->next != NULL) break;
789 if (token->next == NULL) break;
790 token = token->next;
794 token->next = list->next;
795 if (token->next) token->next->prev = token;
797 list->next = item;
798 item->prev = list;
800 if (list->last == NULL)
802 while (token->group != list) token = token->group;
803 list->last = token;
806 return item;
810 * anjuta_token_insert_after:
811 * @sibling: a #AnjutaToken object.
812 * @item: a #AnjutaToken object.
814 * Insert all tokens after sibling.
816 * Return value: The first token inserted.
818 AnjutaToken *
819 anjuta_token_insert_after (AnjutaToken *sibling, AnjutaToken *list)
821 AnjutaToken *last;
822 AnjutaToken *token;
823 AnjutaToken *old_group;
824 AnjutaToken *old_parent;
826 g_return_val_if_fail (sibling != NULL, NULL);
827 g_return_val_if_fail (list != NULL, NULL);
829 old_group = list->group;
830 old_parent = list->parent;
832 /* Update each token */
833 for (token = list;;)
835 if (token->parent == old_parent) token->parent = sibling->parent;
836 if (token->group == old_group) token->group = sibling->group;
838 if (token->children != NULL)
840 token = token->children;
842 else if (token->next != NULL)
844 token = token->next;
846 else
848 while (token->parent != sibling->parent)
850 token = token->parent;
851 if (token->next != NULL) break;
853 if (token->next == NULL) break;
854 token = token->next;
858 for (last = sibling; last->last != NULL; last = last->last);
860 token->next = last->next;
861 if (token->next) token->next->prev = token;
863 last->next = list;
864 list->prev = last;
866 if ((sibling->group != NULL) && (sibling->group->last == sibling))
868 while (token->group != sibling->group) token = token->group;
869 sibling->group->last = token;
872 return list;
876 * anjuta_token_insert_before:
877 * @sibling: a #AnjutaToken object.
878 * @item: a #AnjutaToken object.
880 * Insert all tokens before sibling.
882 * Return value: The first token inserted.
884 AnjutaToken *
885 anjuta_token_insert_before (AnjutaToken *sibling, AnjutaToken *list)
887 AnjutaToken *last;
888 AnjutaToken *token;
889 AnjutaToken *old_group;
890 AnjutaToken *old_parent;
892 g_return_val_if_fail (sibling != NULL, NULL);
893 g_return_val_if_fail (list != NULL, NULL);
895 old_group = list->group;
896 old_parent = list->parent;
898 /* Update each token */
899 for (token = list;;)
901 if (token->parent == old_parent) token->parent = sibling->parent;
902 if (token->group == old_group) token->group = sibling->group;
904 if (token->children != NULL)
906 token = token->children;
908 else if (token->next != NULL)
910 token = token->next;
912 else
914 while (token->parent != sibling->parent)
916 token = token->parent;
917 if (token->next != NULL) break;
919 if (token->next == NULL) break;
920 token = token->next;
924 for (last = sibling; last->last != NULL; last = last->last);
926 token->next = sibling;
927 list->prev = sibling->prev;
928 sibling->prev = token;
930 if (list->prev) list->prev->next = list;
932 if ((list->parent != NULL) && (list->parent->children == sibling)) list->parent->children = list;
934 return list;
938 * anjuta_token_delete_parent:
939 * @parent: a #AnjutaToken object used as parent.
941 * Delete only the parent token.
943 * Return value: the first children
945 AnjutaToken *
946 anjuta_token_delete_parent (AnjutaToken *parent)
948 AnjutaToken *token;
950 g_return_val_if_fail (parent != NULL, NULL);
952 if (parent->children == NULL) return NULL;
954 /* Update each token */
955 for (token = parent->children;;)
957 if (token->parent == parent) token->parent = parent->parent;
959 if (token->children != NULL)
961 token = token->children;
963 else if (token->next != NULL)
965 token = token->next;
967 else
969 while (token->parent != parent->parent)
971 token = token->parent;
972 if (token->next != NULL) break;
974 if (token->next == NULL) break;
975 token = token->next;
979 token->next = parent->next;
980 if (token->next) token->next->prev = token;
982 parent->next = parent->children;
983 parent->children->prev = parent;
984 parent->children = NULL;
986 return anjuta_token_free (parent);
989 /* Merge function
990 *---------------------------------------------------------------------------*/
992 /* anjuta_token_merge can be used with first or end being a floating token and
993 * on already grouped tokens to change the group organisation */
994 AnjutaToken *
995 anjuta_token_merge (AnjutaToken *first, AnjutaToken *end)
997 AnjutaToken *next;
999 if ((first == end) || (end == NULL)) return first;
1001 /* Insert first or end in the same sequence if it is not already the case */
1002 for (next = first; next != end; next = anjuta_token_next (next))
1004 if (next == NULL)
1006 if (first->parent == NULL)
1008 anjuta_token_insert_before (end, first);
1010 else
1012 anjuta_token_insert_after (first, end);
1014 break;
1017 first->last = end;
1018 if ((end->group != NULL) && (end->group != first) && (end->group->last == end)) end->group->last = first;
1019 end->group = first;
1021 return first;
1024 AnjutaToken *
1025 anjuta_token_merge_own_children (AnjutaToken *group)
1027 AnjutaToken *token;
1028 AnjutaToken *next = NULL;
1030 if (group->last != NULL) return group;
1032 if (group->last->last != NULL) group->last = group->last->last;
1034 for (token = anjuta_token_next (group); (token != NULL) && (token != group->last); token = anjuta_token_next (token))
1036 if (next == NULL)
1038 if (token->last != NULL)
1040 next = token->last;
1041 //token->last = NULL;
1043 token->group = group;
1045 else if (next == token)
1047 next = NULL;
1051 return group;
1054 AnjutaToken *
1055 anjuta_token_merge_children (AnjutaToken *first, AnjutaToken *end)
1057 if (first == NULL)
1059 return end;
1061 if ((first == end) || (end == NULL))
1063 return first;
1066 if (first->parent == NULL)
1068 first->parent = end->parent;
1070 if (first->next == NULL)
1072 anjuta_token_insert_before (end, first);
1074 anjuta_token_unlink_token (end);
1075 if (end->last != NULL)
1077 AnjutaToken *child;
1079 first->last = end->last;
1080 for (child = anjuta_token_next (first); child != first->last; child = anjuta_token_next (child))
1082 if (child->group == end) child->group = first;
1084 first->last->group = first;
1086 end->group = first;
1087 anjuta_token_free (end);
1089 return first;
1093 * anjuta_token_merge_previous:
1094 * @list: a #AnjutaToken object representing a list
1095 * @first: a #AnjutaToken object for the new beginning of the list
1097 * If the list token is not already linked with first, it is inserted
1098 * just before first.
1099 * If the list token is already linked, it must be in the same list after
1100 * first token. It it possible to have several tokens beweent list and
1101 * first.
1103 * Return value: the new list
1105 AnjutaToken *
1106 anjuta_token_merge_previous (AnjutaToken *list, AnjutaToken *first)
1108 AnjutaToken *token;
1110 if ((first == NULL) || (list == first)) return list;
1112 /* Change group of all tokens from end to first
1113 * if the list is already linked */
1114 if ((list->prev != NULL) || (list->parent != NULL))
1116 for (token = first; token != NULL; token = anjuta_token_next_item (token))
1118 token->group = list;
1122 token = anjuta_token_next (list);
1123 anjuta_token_unlink_token (list);
1124 anjuta_token_insert_token_before (first, list);
1126 return list;
1129 AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
1131 if (token->data.length > size)
1133 AnjutaToken *copy;
1135 copy = anjuta_token_copy (token);
1136 anjuta_token_insert_before (token, copy);
1138 copy->data.length = size;
1139 if (token->data.flags & ANJUTA_TOKEN_STATIC)
1141 token->data.pos += size;
1142 token->data.length -= size;
1144 else
1146 memcpy(token->data.pos, token->data.pos + size, token->data.length - size);
1149 return copy;
1151 else
1153 return token;
1157 AnjutaToken *
1158 anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
1160 AnjutaToken *copy;
1162 copy = anjuta_token_copy (token);
1164 if (pos >= token->data.length)
1166 if (!(copy->data.flags & ANJUTA_TOKEN_STATIC))
1168 g_free (copy->data.pos);
1170 copy->data.pos = NULL;
1171 copy->data.length = 0;
1173 if ((pos + size) > token->data.length)
1175 size = token->data.length - pos;
1178 if (copy->data.flags & ANJUTA_TOKEN_STATIC)
1180 copy->data.pos += pos;
1182 else
1184 memcpy(copy->data.pos, copy->data.pos + pos, size);
1186 copy->data.length = size;
1188 return copy;
1191 static void
1192 concat_token (AnjutaToken *token, gpointer user_data)
1194 AnjutaToken *first = (AnjutaToken *)user_data;
1196 if (anjuta_token_get_length (token) > 0)
1198 if (anjuta_token_get_string (first) == NULL)
1200 anjuta_token_set_string (first, anjuta_token_get_string (token), anjuta_token_get_length (token));
1202 else if ((first != NULL) && ((anjuta_token_get_string(first) + anjuta_token_get_length (first)) == anjuta_token_get_string (token)))
1204 anjuta_token_set_string (first, anjuta_token_get_string (first), anjuta_token_get_length (first) + anjuta_token_get_length (token));
1206 else
1208 AnjutaToken *new;
1210 new = anjuta_token_new_static_len (ANJUTA_TOKEN_CONTENT, anjuta_token_get_string (token), anjuta_token_get_length (token));
1211 anjuta_token_insert_after (first, new);
1212 anjuta_token_merge (first, new);
1218 AnjutaToken *
1219 anjuta_token_concat(AnjutaToken *token)
1221 AnjutaToken *new;
1223 new = anjuta_token_new_static (ANJUTA_TOKEN_CONTENT, NULL);
1224 anjuta_token_foreach_token (token, concat_token, new);
1226 anjuta_token_insert_token_before (token, new);
1227 anjuta_token_free (token);
1229 return new;
1232 /* Token foreach
1233 *---------------------------------------------------------------------------*/
1235 void
1236 anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1238 if (token != NULL)
1240 AnjutaToken *last_token;
1241 gint child = 0;
1243 last_token = token->last == NULL ? token : token->last;
1244 while (token != NULL)
1246 if (child == 0) func (token, user_data);
1248 /* Check if we have found the last token */
1249 if (token == last_token)
1251 /* Find last token */
1252 if (token->last == NULL)
1254 break;
1256 /* Last token still include additional tokens */
1257 last_token = token->last;
1260 if (token->children != NULL)
1262 /* Check children, only for last token */
1263 child++;
1264 token = token->children;
1266 else if (token->next != NULL)
1268 /* Get next sibling */
1269 token = token->next;
1271 else
1273 /* Get parent */
1274 for (;;)
1276 child--;
1277 token = token->parent;
1278 if (token == NULL) break;
1279 if (token->next != NULL)
1281 token = token->next;
1282 break;
1289 return;
1292 void
1293 anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1295 if (token != NULL)
1297 AnjutaToken *last_parent; /* If not NULL, token belong to a parent and
1298 * are not taken into account */
1299 AnjutaToken *last_token;
1300 gboolean expand = TRUE;
1302 last_parent = NULL;
1303 last_token = token->last == NULL ? token : token->last;
1304 for (;;)
1306 if (expand && (token->children != NULL))
1308 /* Children of the last token does not belong to the group */
1309 if (token == last_token)
1311 /* Find last token */
1312 if (token->last == NULL)
1314 break;
1316 /* Last token still include additional tokens */
1317 last_token = token->last;
1320 /* Enumerate children */
1321 token = token->children;
1323 else
1325 if (token->children == NULL)
1327 /* Take into account only the content of token having no children */
1328 if (last_parent == NULL)
1330 /* Take into account only the content of group having no children */
1331 func (token, user_data);
1335 /* Check if we have found the last token */
1336 if (token == last_token)
1338 /* Find last token */
1339 if (token->last == NULL)
1341 break;
1343 /* Last token still include additional tokens */
1344 last_token = token->last;
1347 if (token == last_parent)
1349 /* Find last parent */
1350 if (token->last == NULL)
1352 /* Found complete group having children */
1353 last_parent = NULL;
1355 else
1357 /* Parent group has additional token */
1358 last_parent = token->last;
1362 if (token->next != NULL)
1364 /* Get next sibling */
1365 token = token->next;
1366 expand = TRUE;
1368 else
1370 /* Get parent */
1371 token = token->parent;
1372 if (token != NULL) last_parent = token->last;
1373 expand = FALSE;
1379 return;
1382 void
1383 anjuta_token_foreach_container (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1385 if (token != NULL)
1387 AnjutaToken *parent; /* If not NULL, token belong to a parent and
1388 * are not taken into account */
1389 AnjutaToken *last_token;
1390 gboolean expand = TRUE;
1392 parent = NULL;
1393 last_token = token->last == NULL ? token : token->last;
1394 for (;;)
1396 if (expand && (token->children != NULL))
1398 if (parent == NULL) parent = token;
1399 /* Enumerate children */
1400 token = token->children;
1402 else
1404 /* Take into account only the content of parent token */
1405 if (parent == NULL)
1407 /* Take into account only the content of group having no children */
1408 func (token, user_data);
1411 /* Check if we have found the last token */
1412 if (token == last_token)
1414 /* Find last token */
1415 if (token->last == NULL)
1417 break;
1419 /* Last token still include additional tokens */
1420 last_token = token->last;
1423 if (token->next != NULL)
1425 /* Get next sibling */
1426 token = token->next;
1427 expand = TRUE;
1429 else
1431 /* Get parent */
1432 token = token->parent;
1433 if (token == parent) parent = NULL;
1434 expand = FALSE;
1440 return;
1443 AnjutaToken *
1444 anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1446 if (token != NULL)
1448 AnjutaToken *last_parent; /* If not NULL, token belong to a parent */
1449 AnjutaToken *last_token;
1450 AnjutaToken buffer; /* Temporary token allowing func to destroy
1451 * the current token */
1452 gboolean expand = TRUE;
1454 last_parent = NULL;
1455 last_token = token->last == NULL ? token : token->last;
1456 while (token != NULL)
1458 if (expand && (token->children != NULL))
1460 /* Check if we have found the last token */
1461 if (token == last_token)
1463 /* Find last token */
1464 if (token->last == NULL)
1466 break;
1468 /* Last token still include additional tokens */
1469 last_token = token->last;
1472 /* Enumerate children */
1473 token = token->children;
1475 else
1477 /* Save token data in case it is destroyed */
1478 memcpy (&buffer, token, sizeof (buffer));
1479 /* Take into account all token */
1480 func (token, user_data);
1482 /* Check if we have found the last token */
1483 if (token == last_token)
1485 /* Find last token */
1486 if (buffer.last == NULL)
1488 token = &buffer;
1489 break;
1491 /* Last token still include additional tokens */
1492 last_token = buffer.last;
1495 if (token == last_parent)
1497 /* Find last parent */
1498 if (buffer.last == NULL)
1500 /* Found complete group having children */
1501 last_parent = NULL;
1503 else
1505 /* Parent group has additional token */
1506 last_parent = buffer.last;
1510 if (buffer.next != NULL)
1512 /* Get next sibling */
1513 token = buffer.next;
1514 expand = TRUE;
1516 else
1518 /* Get parent */
1519 token = buffer.parent;
1520 if (token != NULL) last_parent = token->last;
1521 expand = FALSE;
1526 while ((token != NULL) && (token->next == NULL))
1528 token = token->parent;
1531 if (token != NULL) token = token->next;
1534 return token;
1537 /* Token evaluation
1538 *---------------------------------------------------------------------------*/
1540 static void
1541 evaluate_raw_token (AnjutaToken *token, gpointer user_data)
1543 GString *value = (GString *)user_data;
1545 anjuta_token_evaluate_token (token, value, TRUE);
1548 static void
1549 evaluate_token (AnjutaToken *token, gpointer user_data)
1551 GString *value = (GString *)user_data;
1553 anjuta_token_evaluate_token (token, value, FALSE);
1557 gchar *
1558 anjuta_token_evaluate (AnjutaToken *token)
1560 GString *value = g_string_new (NULL);
1562 anjuta_token_foreach_content (token, evaluate_token, value);
1564 /* Return NULL and free data for an empty string */
1565 return g_string_free (value, *(value->str) == '\0');
1568 /* Does not evaluate content if token is a variable */
1569 gchar *
1570 anjuta_token_evaluate_name (AnjutaToken *token)
1572 GString *value = g_string_new (NULL);
1574 anjuta_token_foreach_container (token, evaluate_token, value);
1576 /* Return NULL and free data for an empty string */
1577 return g_string_free (value, *(value->str) == '\0');
1580 gboolean
1581 anjuta_token_is_empty (AnjutaToken *token)
1583 return (token == NULL) || ((token->data.length == 0) && (token->last == NULL) && (token->children == NULL));
1587 /* Other functions
1588 *---------------------------------------------------------------------------*/
1590 gboolean
1591 anjuta_token_compare (AnjutaToken *toka, AnjutaToken *tokb)
1593 if (tokb->data.type)
1595 if (tokb->data.type != toka->data.type) return FALSE;
1598 if (tokb->data.type != ANJUTA_TOKEN_NONE)
1600 if (tokb->data.length != 0)
1602 if (toka->data.length != tokb->data.length) return FALSE;
1604 if ((toka->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE) && (tokb->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE))
1606 if (g_ascii_strncasecmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1608 else
1610 if (strncmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1615 if (tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS)
1617 if ((toka->data.flags & tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS) == 0)
1618 return FALSE;
1621 return TRUE;
1624 void
1625 anjuta_token_dump (AnjutaToken *token)
1627 if (token == NULL) return;
1629 anjuta_token_dump_child (token, 0, 0);
1632 void
1633 anjuta_token_dump_link (AnjutaToken *token)
1635 AnjutaToken *last = token;
1637 while (last->last != NULL) last = last->last;
1639 for (; token != last; token = anjuta_token_next (token))
1641 anjuta_token_show (token, 0, 0);
1645 gboolean
1646 anjuta_token_check (AnjutaToken *token)
1648 if ((token->children != NULL) && (token->last != NULL))
1650 anjuta_token_show (token, 0, 0);
1651 fprintf(stderr, "Error: Previous token has both non NULL children and last\n");
1653 return FALSE;
1656 if (token->children != NULL)
1658 AnjutaToken *child;
1660 for (child = token->children; child != NULL; child = child->next)
1662 if (!anjuta_token_check_child (child, token)) return FALSE;
1666 if (token->last != NULL)
1668 AnjutaToken *child;
1670 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (child))
1672 if (!anjuta_token_check (child)) return FALSE;
1673 if (child == token->last) break;
1677 return TRUE;
1680 /* Constructor & Destructor
1681 *---------------------------------------------------------------------------*/
1683 AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const gchar *value)
1685 AnjutaToken *token;
1687 if (value == NULL)
1689 token = anjuta_token_new_static (type, NULL);
1691 else
1693 token = g_slice_new0 (AnjutaToken);
1694 token->data.type = type & ANJUTA_TOKEN_TYPE;
1695 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1696 token->data.pos = g_strdup (value);
1697 token->data.length = strlen (value);
1700 return token;
1703 AnjutaToken*
1704 anjuta_token_new_string_len (AnjutaTokenType type, gchar *value, gsize length)
1706 AnjutaToken *token;
1708 if (value == NULL)
1710 token = anjuta_token_new_static (type, NULL);
1712 else
1714 token = g_slice_new0 (AnjutaToken);
1715 token->data.type = type & ANJUTA_TOKEN_TYPE;
1716 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1717 token->data.pos = value;
1718 token->data.length = length;
1721 return token;
1724 AnjutaToken *
1725 anjuta_token_new_static_len (gint type, const gchar *pos, gsize length)
1727 AnjutaToken *token;
1729 token = g_slice_new0 (AnjutaToken);
1730 token->data.type = type & ANJUTA_TOKEN_TYPE;
1731 token->data.flags = (type & ANJUTA_TOKEN_FLAGS) | ANJUTA_TOKEN_STATIC;
1732 token->data.pos = (gchar *)pos;
1733 token->data.length = length;
1735 return token;
1738 AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const char *value)
1740 return anjuta_token_new_static_len (type, value, value == NULL ? 0 : strlen (value));
1743 AnjutaToken*
1744 anjuta_token_free_children (AnjutaToken *token)
1746 AnjutaToken *child;
1747 AnjutaToken *last;
1749 if (token == NULL) return NULL;
1751 for (child = token->children; child != NULL; child = token->children)
1753 anjuta_token_free (child);
1755 token->children = NULL;
1757 if (token->last != NULL)
1759 last = token->last;
1760 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (token))
1762 anjuta_token_free (child);
1763 if (child == last) break;
1766 token->last = NULL;
1768 return token;
1771 static void
1772 free_token (AnjutaToken *token, gpointer user_data)
1774 anjuta_token_unlink_token (token);
1775 if ((token->data.pos != NULL) && !(token->data.flags & ANJUTA_TOKEN_STATIC))
1777 g_free (token->data.pos);
1779 g_slice_free (AnjutaToken, token);
1783 AnjutaToken*
1784 anjuta_token_free (AnjutaToken *token)
1786 AnjutaToken *next;
1788 if (token == NULL) return NULL;
1790 next = anjuta_token_foreach_post_order (token, free_token, NULL);
1792 return next;