language-support-js: Fixed bgo#665082 - Crash in javascript autocompletion
[anjuta.git] / libanjuta / anjuta-token.c
blob457c0b0fb3982b5844713066127cc1aa55a0df77
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 == end) || (end == NULL))
1059 return first;
1062 if (first->parent == NULL)
1064 first->parent = end->parent;
1066 if (first->next == NULL)
1068 anjuta_token_insert_before (end, first);
1070 anjuta_token_unlink_token (end);
1071 if (end->last != NULL)
1073 AnjutaToken *child;
1075 first->last = end->last;
1076 for (child = anjuta_token_next (first); child != first->last; child = anjuta_token_next (child))
1078 if (child->group == end) child->group = first;
1080 first->last->group = first;
1082 end->group = first;
1083 anjuta_token_free (end);
1085 return first;
1089 * anjuta_token_merge_previous:
1090 * @list: a #AnjutaToken object representing a list
1091 * @first: a #AnjutaToken object for the new beginning of the list
1093 * If the list token is not already linked with first, it is inserted
1094 * just before first.
1095 * If the list token is already linked, it must be in the same list after
1096 * first token. It it possible to have several tokens beweent list and
1097 * first.
1099 * Return value: the new list
1101 AnjutaToken *
1102 anjuta_token_merge_previous (AnjutaToken *list, AnjutaToken *first)
1104 AnjutaToken *token;
1106 if ((first == NULL) || (list == first)) return list;
1108 /* Change group of all tokens from end to first
1109 * if the list is already linked */
1110 if ((list->prev != NULL) || (list->parent != NULL))
1112 for (token = first; token != NULL; token = anjuta_token_next_item (token))
1114 token->group = list;
1118 token = anjuta_token_next (list);
1119 anjuta_token_unlink_token (list);
1120 anjuta_token_insert_token_before (first, list);
1122 return list;
1125 AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
1127 if (token->data.length > size)
1129 AnjutaToken *copy;
1131 copy = anjuta_token_copy (token);
1132 anjuta_token_insert_before (token, copy);
1134 copy->data.length = size;
1135 if (token->data.flags & ANJUTA_TOKEN_STATIC)
1137 token->data.pos += size;
1138 token->data.length -= size;
1140 else
1142 memcpy(token->data.pos, token->data.pos + size, token->data.length - size);
1145 return copy;
1147 else
1149 return token;
1153 AnjutaToken *
1154 anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
1156 AnjutaToken *copy;
1158 copy = anjuta_token_copy (token);
1160 if (pos >= token->data.length)
1162 if (!(copy->data.flags & ANJUTA_TOKEN_STATIC))
1164 g_free (copy->data.pos);
1166 copy->data.pos = NULL;
1167 copy->data.length = 0;
1169 if ((pos + size) > token->data.length)
1171 size = token->data.length - pos;
1174 if (copy->data.flags & ANJUTA_TOKEN_STATIC)
1176 copy->data.pos += pos;
1178 else
1180 memcpy(copy->data.pos, copy->data.pos + pos, size);
1182 copy->data.length = size;
1184 return copy;
1187 static void
1188 concat_token (AnjutaToken *token, gpointer user_data)
1190 AnjutaToken *first = (AnjutaToken *)user_data;
1192 if (anjuta_token_get_length (token) > 0)
1194 if (anjuta_token_get_string (first) == NULL)
1196 anjuta_token_set_string (first, anjuta_token_get_string (token), anjuta_token_get_length (token));
1198 else if ((first != NULL) && ((anjuta_token_get_string(first) + anjuta_token_get_length (first)) == anjuta_token_get_string (token)))
1200 anjuta_token_set_string (first, anjuta_token_get_string (first), anjuta_token_get_length (first) + anjuta_token_get_length (token));
1202 else
1204 AnjutaToken *new;
1206 new = anjuta_token_new_static_len (ANJUTA_TOKEN_CONTENT, anjuta_token_get_string (token), anjuta_token_get_length (token));
1207 anjuta_token_insert_after (first, new);
1208 anjuta_token_merge (first, new);
1214 AnjutaToken *
1215 anjuta_token_concat(AnjutaToken *token)
1217 AnjutaToken *new;
1219 new = anjuta_token_new_static (ANJUTA_TOKEN_CONTENT, NULL);
1220 anjuta_token_foreach_token (token, concat_token, new);
1222 anjuta_token_insert_token_before (token, new);
1223 anjuta_token_free (token);
1225 return new;
1228 /* Token foreach
1229 *---------------------------------------------------------------------------*/
1231 void
1232 anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1234 if (token != NULL)
1236 AnjutaToken *last_token;
1237 gint child = 0;
1239 last_token = token->last == NULL ? token : token->last;
1240 while (token != NULL)
1242 if (child == 0) func (token, user_data);
1244 /* Check if we have found the last token */
1245 if (token == last_token)
1247 /* Find last token */
1248 if (token->last == NULL)
1250 break;
1252 /* Last token still include additional tokens */
1253 last_token = token->last;
1256 if (token->children != NULL)
1258 /* Check children, only for last token */
1259 child++;
1260 token = token->children;
1262 else if (token->next != NULL)
1264 /* Get next sibling */
1265 token = token->next;
1267 else
1269 /* Get parent */
1270 for (;;)
1272 child--;
1273 token = token->parent;
1274 if (token == NULL) break;
1275 if (token->next != NULL)
1277 token = token->next;
1278 break;
1285 return;
1288 void
1289 anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1291 if (token != NULL)
1293 AnjutaToken *last_parent; /* If not NULL, token belong to a parent and
1294 * are not taken into account */
1295 AnjutaToken *last_token;
1296 gboolean expand = TRUE;
1298 last_parent = NULL;
1299 last_token = token->last == NULL ? token : token->last;
1300 for (;;)
1302 if (expand && (token->children != NULL))
1304 /* Children of the last token does not belong to the group */
1305 if (token == last_token)
1307 /* Find last token */
1308 if (token->last == NULL)
1310 break;
1312 /* Last token still include additional tokens */
1313 last_token = token->last;
1316 /* Enumerate children */
1317 token = token->children;
1319 else
1321 if (token->children == NULL)
1323 /* Take into account only the content of token having no children */
1324 if (last_parent == NULL)
1326 /* Take into account only the content of group having no children */
1327 func (token, user_data);
1331 /* Check if we have found the last token */
1332 if (token == last_token)
1334 /* Find last token */
1335 if (token->last == NULL)
1337 break;
1339 /* Last token still include additional tokens */
1340 last_token = token->last;
1343 if (token == last_parent)
1345 /* Find last parent */
1346 if (token->last == NULL)
1348 /* Found complete group having children */
1349 last_parent = NULL;
1351 else
1353 /* Parent group has additional token */
1354 last_parent = token->last;
1358 if (token->next != NULL)
1360 /* Get next sibling */
1361 token = token->next;
1362 expand = TRUE;
1364 else
1366 /* Get parent */
1367 token = token->parent;
1368 if (token != NULL) last_parent = token->last;
1369 expand = FALSE;
1375 return;
1378 void
1379 anjuta_token_foreach_container (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1381 if (token != NULL)
1383 AnjutaToken *parent; /* If not NULL, token belong to a parent and
1384 * are not taken into account */
1385 AnjutaToken *last_token;
1386 gboolean expand = TRUE;
1388 parent = NULL;
1389 last_token = token->last == NULL ? token : token->last;
1390 for (;;)
1392 if (expand && (token->children != NULL))
1394 if (parent == NULL) parent = token;
1395 /* Enumerate children */
1396 token = token->children;
1398 else
1400 /* Take into account only the content of parent token */
1401 if (parent == NULL)
1403 /* Take into account only the content of group having no children */
1404 func (token, user_data);
1407 /* Check if we have found the last token */
1408 if (token == last_token)
1410 /* Find last token */
1411 if (token->last == NULL)
1413 break;
1415 /* Last token still include additional tokens */
1416 last_token = token->last;
1419 if (token->next != NULL)
1421 /* Get next sibling */
1422 token = token->next;
1423 expand = TRUE;
1425 else
1427 /* Get parent */
1428 token = token->parent;
1429 if (token == parent) parent = NULL;
1430 expand = FALSE;
1436 return;
1439 AnjutaToken *
1440 anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1442 if (token != NULL)
1444 AnjutaToken *last_parent; /* If not NULL, token belong to a parent */
1445 AnjutaToken *last_token;
1446 AnjutaToken buffer; /* Temporary token allowing func to destroy
1447 * the current token */
1448 gboolean expand = TRUE;
1450 last_parent = NULL;
1451 last_token = token->last == NULL ? token : token->last;
1452 while (token != NULL)
1454 if (expand && (token->children != NULL))
1456 /* Check if we have found the last token */
1457 if (token == last_token)
1459 /* Find last token */
1460 if (token->last == NULL)
1462 break;
1464 /* Last token still include additional tokens */
1465 last_token = token->last;
1468 /* Enumerate children */
1469 token = token->children;
1471 else
1473 /* Save token data in case it is destroyed */
1474 memcpy (&buffer, token, sizeof (buffer));
1475 /* Take into account all token */
1476 func (token, user_data);
1478 /* Check if we have found the last token */
1479 if (token == last_token)
1481 /* Find last token */
1482 if (buffer.last == NULL)
1484 token = &buffer;
1485 break;
1487 /* Last token still include additional tokens */
1488 last_token = buffer.last;
1491 if (token == last_parent)
1493 /* Find last parent */
1494 if (buffer.last == NULL)
1496 /* Found complete group having children */
1497 last_parent = NULL;
1499 else
1501 /* Parent group has additional token */
1502 last_parent = buffer.last;
1506 if (buffer.next != NULL)
1508 /* Get next sibling */
1509 token = buffer.next;
1510 expand = TRUE;
1512 else
1514 /* Get parent */
1515 token = buffer.parent;
1516 if (token != NULL) last_parent = token->last;
1517 expand = FALSE;
1522 while ((token != NULL) && (token->next == NULL))
1524 token = token->parent;
1527 if (token != NULL) token = token->next;
1530 return token;
1533 /* Token evaluation
1534 *---------------------------------------------------------------------------*/
1536 static void
1537 evaluate_raw_token (AnjutaToken *token, gpointer user_data)
1539 GString *value = (GString *)user_data;
1541 anjuta_token_evaluate_token (token, value, TRUE);
1544 static void
1545 evaluate_token (AnjutaToken *token, gpointer user_data)
1547 GString *value = (GString *)user_data;
1549 anjuta_token_evaluate_token (token, value, FALSE);
1553 gchar *
1554 anjuta_token_evaluate (AnjutaToken *token)
1556 GString *value = g_string_new (NULL);
1558 anjuta_token_foreach_content (token, evaluate_token, value);
1560 /* Return NULL and free data for an empty string */
1561 return g_string_free (value, *(value->str) == '\0');
1564 /* Does not evaluate content if token is a variable */
1565 gchar *
1566 anjuta_token_evaluate_name (AnjutaToken *token)
1568 GString *value = g_string_new (NULL);
1570 anjuta_token_foreach_container (token, evaluate_token, value);
1572 /* Return NULL and free data for an empty string */
1573 return g_string_free (value, *(value->str) == '\0');
1576 gboolean
1577 anjuta_token_is_empty (AnjutaToken *token)
1579 return (token == NULL) || ((token->data.length == 0) && (token->last == NULL) && (token->children == NULL));
1583 /* Other functions
1584 *---------------------------------------------------------------------------*/
1586 gboolean
1587 anjuta_token_compare (AnjutaToken *toka, AnjutaToken *tokb)
1589 if (tokb->data.type)
1591 if (tokb->data.type != toka->data.type) return FALSE;
1594 if (tokb->data.type != ANJUTA_TOKEN_NONE)
1596 if (tokb->data.length != 0)
1598 if (toka->data.length != tokb->data.length) return FALSE;
1600 if ((toka->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE) && (tokb->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE))
1602 if (g_ascii_strncasecmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1604 else
1606 if (strncmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1611 if (tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS)
1613 if ((toka->data.flags & tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS) == 0)
1614 return FALSE;
1617 return TRUE;
1620 void
1621 anjuta_token_dump (AnjutaToken *token)
1623 if (token == NULL) return;
1625 anjuta_token_dump_child (token, 0, 0);
1628 void
1629 anjuta_token_dump_link (AnjutaToken *token)
1631 AnjutaToken *last = token;
1633 while (last->last != NULL) last = last->last;
1635 for (; token != last; token = anjuta_token_next (token))
1637 anjuta_token_show (token, 0, 0);
1641 gboolean
1642 anjuta_token_check (AnjutaToken *token)
1644 if ((token->children != NULL) && (token->last != NULL))
1646 anjuta_token_show (token, 0, 0);
1647 fprintf(stderr, "Error: Previous token has both non NULL children and last\n");
1649 return FALSE;
1652 if (token->children != NULL)
1654 AnjutaToken *child;
1656 for (child = token->children; child != NULL; child = child->next)
1658 if (!anjuta_token_check_child (child, token)) return FALSE;
1662 if (token->last != NULL)
1664 AnjutaToken *child;
1666 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (child))
1668 if (!anjuta_token_check (child)) return FALSE;
1669 if (child == token->last) break;
1673 return TRUE;
1676 /* Constructor & Destructor
1677 *---------------------------------------------------------------------------*/
1679 AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const gchar *value)
1681 AnjutaToken *token;
1683 if (value == NULL)
1685 token = anjuta_token_new_static (type, NULL);
1687 else
1689 token = g_slice_new0 (AnjutaToken);
1690 token->data.type = type & ANJUTA_TOKEN_TYPE;
1691 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1692 token->data.pos = g_strdup (value);
1693 token->data.length = strlen (value);
1696 return token;
1699 AnjutaToken*
1700 anjuta_token_new_string_len (AnjutaTokenType type, gchar *value, gsize length)
1702 AnjutaToken *token;
1704 if (value == NULL)
1706 token = anjuta_token_new_static (type, NULL);
1708 else
1710 token = g_slice_new0 (AnjutaToken);
1711 token->data.type = type & ANJUTA_TOKEN_TYPE;
1712 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1713 token->data.pos = value;
1714 token->data.length = length;
1717 return token;
1720 AnjutaToken *
1721 anjuta_token_new_static_len (gint type, const gchar *pos, gsize length)
1723 AnjutaToken *token;
1725 token = g_slice_new0 (AnjutaToken);
1726 token->data.type = type & ANJUTA_TOKEN_TYPE;
1727 token->data.flags = (type & ANJUTA_TOKEN_FLAGS) | ANJUTA_TOKEN_STATIC;
1728 token->data.pos = (gchar *)pos;
1729 token->data.length = length;
1731 return token;
1734 AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const char *value)
1736 return anjuta_token_new_static_len (type, value, value == NULL ? 0 : strlen (value));
1739 AnjutaToken*
1740 anjuta_token_free_children (AnjutaToken *token)
1742 AnjutaToken *child;
1743 AnjutaToken *last;
1745 if (token == NULL) return NULL;
1747 for (child = token->children; child != NULL; child = token->children)
1749 anjuta_token_free (child);
1751 token->children = NULL;
1753 if (token->last != NULL)
1755 last = token->last;
1756 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (token))
1758 anjuta_token_free (child);
1759 if (child == last) break;
1762 token->last = NULL;
1764 return token;
1767 static void
1768 free_token (AnjutaToken *token, gpointer user_data)
1770 anjuta_token_unlink_token (token);
1771 if ((token->data.pos != NULL) && !(token->data.flags & ANJUTA_TOKEN_STATIC))
1773 g_free (token->data.pos);
1775 g_slice_free (AnjutaToken, token);
1779 AnjutaToken*
1780 anjuta_token_free (AnjutaToken *token)
1782 AnjutaToken *next;
1784 if (token == NULL) return NULL;
1786 next = anjuta_token_foreach_post_order (token, free_token, NULL);
1788 return next;