debug-manager: Remove weak pointer when needed
[anjuta.git] / libanjuta / anjuta-token.c
blob291b7cf1920d842ce601d19c045ee2819124b789
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;
164 if (child == NULL) break;
168 return child;
171 AnjutaToken *
172 anjuta_token_next_after_children (AnjutaToken *token)
174 while (token->last != NULL) token = token->last;
175 while (token->next == NULL)
177 token = token->parent;
178 if (token == NULL) return NULL;
179 while (token->last != NULL) token = token->last;
182 return token->next;
185 static AnjutaToken *
186 anjuta_token_copy (AnjutaToken *token)
188 AnjutaToken *copy = NULL;
190 if (token != NULL)
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))
197 copy->data.pos = token->data.pos;
199 else
201 copy->data.pos = g_strdup (token->data.pos);
203 copy->data.length = token->data.length;
206 return copy;
210 * anjuta_token_unlink_token:
211 * @token: a #AnjutaToken object.
213 * Unlink a single token, not the complete item, from the token tree.
215 * Return value: the removed token tree
217 static AnjutaToken *
218 anjuta_token_unlink_token (AnjutaToken *token)
221 if (token->prev != NULL)
223 token->prev->next = token->next;
225 else if ((token->parent != NULL) && (token->parent->children == token))
227 token->parent->children = token->next;
229 token->parent = NULL;
231 if ((token->group != NULL) && (token->group->last == token))
233 AnjutaToken *prev;
235 for (prev = token->prev; prev != NULL; prev = prev->prev)
237 if (prev->group == token->group)
239 /* Find previous token in the same group */
240 token->group->last = prev;
241 break;
243 else if (prev == token->group)
245 /* No more token in group */
246 token->group->last = NULL;
247 break;
252 if (token->next != NULL)
254 token->next->prev = token->prev;
255 token->next = NULL;
257 token->prev = NULL;
259 return token;
263 * anjuta_token_insert_token_before:
264 * @sibling: a #AnjutaToken object.
265 * @token: a #AnjutaToken object.
267 * Insert token before sibling.
269 * Return value: inserted token
271 static AnjutaToken *
272 anjuta_token_insert_token_before (AnjutaToken *sibling, AnjutaToken *token)
274 token->prev = sibling->prev;
275 token->next = sibling;
277 if (token->prev != NULL)
279 token->prev->next = token;
281 sibling->prev = token;
283 if ((sibling->parent != NULL) && (sibling->parent->children == sibling))
285 sibling->parent->children = token;
287 token->parent = sibling->parent;
289 return token;
292 static void
293 anjuta_token_evaluate_token (AnjutaToken *token, GString *value, gboolean raw)
295 if ((token != NULL) && (token->data.length != 0))
297 if (!raw)
299 switch (anjuta_token_get_type (token))
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;
312 g_string_append_len (value, anjuta_token_get_string (token), anjuta_token_get_length (token));
316 static void
317 anjuta_token_show (AnjutaToken *token, gint indent, gchar parent)
319 static gchar type[] = "\0";
320 const gchar *string;
321 gsize length;
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)
331 /* Value doesn't contain a newline */
332 fprintf (stderr, "(%" G_GSIZE_FORMAT ")", length);
334 else
336 const gchar *newline;
338 newline = g_strrstr_len (string, length, "\n");
339 if (newline == NULL)
341 /* Value doesn't contain a newline */
342 fprintf (stderr, "\"%.*s\"",
343 (int)length,
344 string);
346 else
348 /* Value contains a newline, take care of indentation */
349 newline++;
350 fprintf (stderr, "\"%.*s",
351 (int)(newline - string),
352 string);
353 for (;;)
355 length -= newline - string;
356 string = newline;
358 newline = g_strrstr_len (string, length, "\n");
359 if (newline == NULL) break;
361 newline++;
362 fprintf (stderr, "%*s %.*s",
363 indent, "",
364 (int)(newline - string),
365 string);
367 fprintf (stderr, "%*s %.*s\"",
368 indent, "",
369 (int)length,
370 string);
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)" : "");
379 static AnjutaToken*
380 anjuta_token_dump_child (AnjutaToken *token, gint indent, gchar type)
382 AnjutaToken *last;
383 AnjutaToken *child;
385 anjuta_token_show (token, indent, type);
386 indent += 4;
388 last = token;
389 if (token->last != NULL)
393 child = last->next;
394 if (child == NULL) break;
395 last = anjuta_token_dump_child (child, indent, '+');
397 while (child != token->last);
400 if (token->children != NULL)
402 for (child = token->children; child != NULL; child = child->next)
404 child = anjuta_token_dump_child (child, indent, '*');
408 return last;
411 static gboolean
412 anjuta_token_check_child (AnjutaToken *token, AnjutaToken *parent)
414 if (token->parent != parent)
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;
421 return anjuta_token_check (token);
424 /* Get and set functions
425 *---------------------------------------------------------------------------*/
427 void
428 anjuta_token_set_type (AnjutaToken *token, gint type)
430 token->data.type = type;
433 gint
434 anjuta_token_get_type (AnjutaToken *token)
436 return token->data.type;
439 void
440 anjuta_token_set_flags (AnjutaToken *token, gint flags)
442 AnjutaToken *child;
443 AnjutaToken *last = token->last;
445 for (child = token; child != NULL; child = anjuta_token_next_child (child, &last))
447 child->data.flags |= flags;
451 void
452 anjuta_token_clear_flags (AnjutaToken *token, gint flags)
454 token->data.flags &= ~flags;
457 gint
458 anjuta_token_get_flags (AnjutaToken *token)
460 return token->data.flags;
463 void
464 anjuta_token_set_string (AnjutaToken *token, const gchar *data, gsize length)
466 if (!(token->data.flags & ANJUTA_TOKEN_STATIC))
468 g_free (token->data.pos);
469 token->data.flags |= ANJUTA_TOKEN_STATIC;
471 token->data.pos = (gchar *)data;
472 token->data.length = length;
475 const gchar *
476 anjuta_token_get_string (AnjutaToken *token)
478 return token->data.pos;
481 void
482 anjuta_token_set_length (AnjutaToken *token, gsize length)
484 token->data.length = length;
487 gsize
488 anjuta_token_get_length (AnjutaToken *token)
490 return token->data.length;
493 /* Basic move functions
494 *---------------------------------------------------------------------------*/
496 AnjutaToken *
497 anjuta_token_next (AnjutaToken *token)
499 if (token->children != NULL)
501 return token->children;
503 else if (token->next != NULL)
505 return token->next;
507 else if (token->parent != NULL)
509 return anjuta_token_next_after_children (token->parent);
511 else
513 return NULL;
517 AnjutaToken *
518 anjuta_token_previous (AnjutaToken *token)
520 if (token->prev != NULL)
522 return token->prev;
524 else
526 return token->parent;
530 AnjutaToken *
531 anjuta_token_last (AnjutaToken *token)
533 AnjutaToken *last;
535 for (last = token; last->last != NULL; last = last->last);
536 if (last->children != NULL)
538 for (last = last->children; last->next != NULL; last = last->next);
541 return last;
544 AnjutaToken *
545 anjuta_token_parent (AnjutaToken *token)
547 return token->parent;
550 AnjutaToken *
551 anjuta_token_list (AnjutaToken *token)
553 return token->group;
556 /* Item move functions
557 *---------------------------------------------------------------------------*/
559 AnjutaToken *
560 anjuta_token_last_item (AnjutaToken *list)
562 return list->last;
565 AnjutaToken *
566 anjuta_token_first_item (AnjutaToken *list)
568 AnjutaToken *first = NULL;
570 if (list != NULL)
572 if (list->children != NULL)
574 first = list->children;
576 else if (list->last != NULL)
578 first = list->next;
582 return first;
585 AnjutaToken *
586 anjuta_token_next_item (AnjutaToken *item)
588 AnjutaToken *next;
590 if (item != NULL)
594 next = NULL;
595 if ((item->group == NULL) || (item->group->last != item))
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;
602 item = next;
604 /* Loop if the current item has been deleted */
605 while ((next != NULL) && (anjuta_token_get_flags (next) & ANJUTA_TOKEN_REMOVED));
608 return next;
611 AnjutaToken *
612 anjuta_token_previous_item (AnjutaToken *item)
614 AnjutaToken *prev = NULL;
617 if (item != NULL)
621 for (prev = item->prev; (prev != NULL) && (prev->group != item->group); prev = prev->group);
622 item = prev;
624 /* Loop if the current item has been deleted */
625 while ((prev != NULL) && (anjuta_token_get_flags (prev) & ANJUTA_TOKEN_REMOVED));
628 return prev;
631 /* Add/Insert/Remove tokens
632 *---------------------------------------------------------------------------*/
635 * anjuta_token_append_child:
636 * @parent: a #AnjutaToken object used as parent.
637 * @children: a #AnjutaToken object.
639 * Insert all tokens in children as the last children of the given parent.
641 * Return value: The first token append.
643 AnjutaToken *
644 anjuta_token_append_child (AnjutaToken *parent, AnjutaToken *children)
646 AnjutaToken *token;
647 AnjutaToken *last;
648 AnjutaToken *old_group;
649 AnjutaToken *old_parent;
651 g_return_val_if_fail (parent != NULL, NULL);
652 g_return_val_if_fail (children != NULL, NULL);
654 old_group = children->group;
655 old_parent = children->parent;
657 if (parent->children == NULL)
659 parent->children = children;
661 children->prev = NULL;
663 else
665 /* Find last children */
666 for (last = parent->children; last->next != NULL;)
668 if ((last->last != NULL) && (last->last->parent == last->parent))
670 last = last->last;
672 else
674 last = last->next;
678 last->next = children;
679 children->prev = last;
682 /* Update each token */
683 for (token = children;;)
685 if (token->parent == old_parent) token->parent = parent;
686 if (token->group == old_group) token->group = parent->group;
688 if (token->children != NULL)
690 token = token->children;
692 else if (token->next != NULL)
694 token = token->next;
696 else
698 while (token->parent != parent)
700 token = token->parent;
701 if (token->next != NULL) break;
703 if (token->next == NULL) break;
704 token = token->next;
708 return children;
712 * anjuta_token_prepend_child:
713 * @parent: a #AnjutaToken object used as parent.
714 * @children: a #AnjutaToken object.
716 * Insert all tokens in children as the first children of the given parent.
718 * Return value: The first token append.
720 AnjutaToken *
721 anjuta_token_prepend_child (AnjutaToken *parent, AnjutaToken *children)
723 AnjutaToken *child;
724 AnjutaToken *last = NULL;
726 g_return_val_if_fail (parent != NULL, NULL);
727 g_return_val_if_fail (children != NULL, NULL);
729 /* Update each token */
730 for (child = children;;)
732 AnjutaToken *next;
734 if (child->parent == children->parent) child->parent = parent;
735 if (child->group == children->group) child->group = parent->group;
737 next = anjuta_token_next_child (child, &last);
738 if (next == NULL) break;
739 child = next;
742 child->next = parent->children;
743 if (child->next) child->next->prev = child;
744 parent->children = children;
746 return children;
750 * anjuta_token_prepend_items:
751 * @list: a #AnjutaToken object used as list.
752 * @item: a #AnjutaToken object.
754 * Insert all tokens in item as item of the given list.
756 * Return value: The first token append.
758 AnjutaToken *
759 anjuta_token_prepend_items (AnjutaToken *list, AnjutaToken *item)
761 AnjutaToken *token;
762 AnjutaToken *old_group;
763 AnjutaToken *old_parent;
765 g_return_val_if_fail (list != NULL, NULL);
766 g_return_val_if_fail (item != NULL, NULL);
768 old_group = item->group;
769 old_parent = item->parent;
771 /* Update each token */
772 for (token = item;;)
774 if (token->parent == old_parent) token->parent = list->parent;
775 if (token->group == old_group) token->group = list;
777 if (token->children != NULL)
779 token = token->children;
781 else if (token->next != NULL)
783 token = token->next;
785 else
787 while (token->parent != list->parent)
789 token = token->parent;
790 if (token->next != NULL) break;
792 if (token->next == NULL) break;
793 token = token->next;
797 token->next = list->next;
798 if (token->next) token->next->prev = token;
800 list->next = item;
801 item->prev = list;
803 if (list->last == NULL)
805 while (token->group != list) token = token->group;
806 list->last = token;
809 return item;
813 * anjuta_token_insert_after:
814 * @sibling: a #AnjutaToken object.
815 * @list: a #AnjutaToken object.
817 * Insert all tokens after sibling.
819 * Return value: The first token inserted.
821 AnjutaToken *
822 anjuta_token_insert_after (AnjutaToken *sibling, AnjutaToken *list)
824 AnjutaToken *last;
825 AnjutaToken *token;
826 AnjutaToken *old_group;
827 AnjutaToken *old_parent;
829 g_return_val_if_fail (sibling != NULL, NULL);
830 g_return_val_if_fail (list != NULL, NULL);
832 old_group = list->group;
833 old_parent = list->parent;
835 /* Update each token */
836 for (token = list;;)
838 if (token->parent == old_parent) token->parent = sibling->parent;
839 if (token->group == old_group) token->group = sibling->group;
841 if (token->children != NULL)
843 token = token->children;
845 else if (token->next != NULL)
847 token = token->next;
849 else
851 while (token->parent != sibling->parent)
853 token = token->parent;
854 if (token->next != NULL) break;
856 if (token->next == NULL) break;
857 token = token->next;
861 for (last = sibling; last->last != NULL; last = last->last);
863 token->next = last->next;
864 if (token->next) token->next->prev = token;
866 last->next = list;
867 list->prev = last;
869 if ((sibling->group != NULL) && (sibling->group->last == sibling))
871 while (token->group != sibling->group) token = token->group;
872 sibling->group->last = token;
875 return list;
879 * anjuta_token_insert_before:
880 * @sibling: a #AnjutaToken object.
881 * @list: a #AnjutaToken object.
883 * Insert all tokens before sibling.
885 * Return value: The first token inserted.
887 AnjutaToken *
888 anjuta_token_insert_before (AnjutaToken *sibling, AnjutaToken *list)
890 AnjutaToken *last;
891 AnjutaToken *token;
892 AnjutaToken *old_group;
893 AnjutaToken *old_parent;
895 g_return_val_if_fail (sibling != NULL, NULL);
896 g_return_val_if_fail (list != NULL, NULL);
898 old_group = list->group;
899 old_parent = list->parent;
901 /* Update each token */
902 for (token = list;;)
904 if (token->parent == old_parent) token->parent = sibling->parent;
905 if (token->group == old_group) token->group = sibling->group;
907 if (token->children != NULL)
909 token = token->children;
911 else if (token->next != NULL)
913 token = token->next;
915 else
917 while (token->parent != sibling->parent)
919 token = token->parent;
920 if (token->next != NULL) break;
922 if (token->next == NULL) break;
923 token = token->next;
927 for (last = sibling; last->last != NULL; last = last->last);
929 token->next = sibling;
930 list->prev = sibling->prev;
931 sibling->prev = token;
933 if (list->prev) list->prev->next = list;
935 if ((list->parent != NULL) && (list->parent->children == sibling)) list->parent->children = list;
937 return list;
941 * anjuta_token_delete_parent:
942 * @parent: a #AnjutaToken object used as parent.
944 * Delete only the parent token.
946 * Return value: the first children
948 AnjutaToken *
949 anjuta_token_delete_parent (AnjutaToken *parent)
951 AnjutaToken *token;
953 g_return_val_if_fail (parent != NULL, NULL);
955 if (parent->children == NULL) return NULL;
957 /* Update each token */
958 for (token = parent->children;;)
960 if (token->parent == parent) token->parent = parent->parent;
962 if (token->children != NULL)
964 token = token->children;
966 else if (token->next != NULL)
968 token = token->next;
970 else
972 while (token->parent != parent->parent)
974 token = token->parent;
975 if (token->next != NULL) break;
977 if (token->next == NULL) break;
978 token = token->next;
982 token->next = parent->next;
983 if (token->next) token->next->prev = token;
985 parent->next = parent->children;
986 parent->children->prev = parent;
987 parent->children = NULL;
989 return anjuta_token_free (parent);
992 /* Merge function
993 *---------------------------------------------------------------------------*/
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 *
998 anjuta_token_merge (AnjutaToken *first, AnjutaToken *end)
1000 AnjutaToken *next;
1002 if ((first == end) || (end == NULL)) return first;
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))
1007 if (next == NULL)
1009 if (first->parent == NULL)
1011 anjuta_token_insert_before (end, first);
1013 else
1015 anjuta_token_insert_after (first, end);
1017 break;
1020 first->last = end;
1021 if ((end->group != NULL) && (end->group != first) && (end->group->last == end)) end->group->last = first;
1022 end->group = first;
1024 return first;
1027 AnjutaToken *
1028 anjuta_token_merge_own_children (AnjutaToken *group)
1030 AnjutaToken *token;
1031 AnjutaToken *next = NULL;
1033 if (group->last != NULL) return group;
1035 if (group->last->last != NULL) group->last = group->last->last;
1037 for (token = anjuta_token_next (group); (token != NULL) && (token != group->last); token = anjuta_token_next (token))
1039 if (next == NULL)
1041 if (token->last != NULL)
1043 next = token->last;
1044 //token->last = NULL;
1046 token->group = group;
1048 else if (next == token)
1050 next = NULL;
1054 return group;
1057 AnjutaToken *
1058 anjuta_token_merge_children (AnjutaToken *first, AnjutaToken *end)
1060 if (first == NULL)
1062 return end;
1064 if ((first == end) || (end == NULL))
1066 return first;
1069 if (first->parent == NULL)
1071 first->parent = end->parent;
1073 if (first->next == NULL)
1075 anjuta_token_insert_before (end, first);
1077 anjuta_token_unlink_token (end);
1078 if (end->last != NULL)
1080 AnjutaToken *child;
1082 first->last = end->last;
1083 for (child = anjuta_token_next (first); child != first->last; child = anjuta_token_next (child))
1085 if (child->group == end) child->group = first;
1087 first->last->group = first;
1089 end->group = first;
1090 anjuta_token_free (end);
1092 return first;
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
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.
1106 * Return value: the new list
1108 AnjutaToken *
1109 anjuta_token_merge_previous (AnjutaToken *list, AnjutaToken *first)
1111 AnjutaToken *token;
1113 if ((first == NULL) || (list == first)) return list;
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))
1119 for (token = first; token != NULL; token = anjuta_token_next_item (token))
1121 token->group = list;
1125 token = anjuta_token_next (list);
1126 anjuta_token_unlink_token (list);
1127 anjuta_token_insert_token_before (first, list);
1129 return list;
1132 AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
1134 if (token->data.length > size)
1136 AnjutaToken *copy;
1138 copy = anjuta_token_copy (token);
1139 anjuta_token_insert_before (token, copy);
1141 copy->data.length = size;
1142 if (token->data.flags & ANJUTA_TOKEN_STATIC)
1144 token->data.pos += size;
1145 token->data.length -= size;
1147 else
1149 memcpy(token->data.pos, token->data.pos + size, token->data.length - size);
1152 return copy;
1154 else
1156 return token;
1160 AnjutaToken *
1161 anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
1163 AnjutaToken *copy;
1165 copy = anjuta_token_copy (token);
1167 if (pos >= token->data.length)
1169 if (!(copy->data.flags & ANJUTA_TOKEN_STATIC))
1171 g_free (copy->data.pos);
1173 copy->data.pos = NULL;
1174 copy->data.length = 0;
1176 if ((pos + size) > token->data.length)
1178 size = token->data.length - pos;
1181 if (copy->data.flags & ANJUTA_TOKEN_STATIC)
1183 copy->data.pos += pos;
1185 else
1187 memmove(copy->data.pos, copy->data.pos + pos, size);
1189 copy->data.length = size;
1191 return copy;
1194 static void
1195 concat_token (AnjutaToken *token, gpointer user_data)
1197 AnjutaToken *first = (AnjutaToken *)user_data;
1199 if (anjuta_token_get_length (token) > 0)
1201 if (anjuta_token_get_string (first) == NULL)
1203 anjuta_token_set_string (first, anjuta_token_get_string (token), anjuta_token_get_length (token));
1205 else if ((first != NULL) && ((anjuta_token_get_string(first) + anjuta_token_get_length (first)) == anjuta_token_get_string (token)))
1207 anjuta_token_set_string (first, anjuta_token_get_string (first), anjuta_token_get_length (first) + anjuta_token_get_length (token));
1209 else
1211 AnjutaToken *new;
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);
1221 AnjutaToken *
1222 anjuta_token_concat(AnjutaToken *token)
1224 AnjutaToken *new;
1226 new = anjuta_token_new_static (ANJUTA_TOKEN_CONTENT, NULL);
1227 anjuta_token_foreach_token (token, concat_token, new);
1229 anjuta_token_insert_token_before (token, new);
1230 anjuta_token_free (token);
1232 return new;
1235 /* Token foreach
1236 *---------------------------------------------------------------------------*/
1238 void
1239 anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1241 if (token != NULL)
1243 AnjutaToken *last_token;
1244 gint child = 0;
1246 last_token = token->last == NULL ? token : token->last;
1247 while (token != NULL)
1249 if (child == 0) func (token, user_data);
1251 /* Check if we have found the last token */
1252 if (token == last_token)
1254 /* Find last token */
1255 if (token->last == NULL)
1257 break;
1259 /* Last token still include additional tokens */
1260 last_token = token->last;
1263 if (token->children != NULL)
1265 /* Check children, only for last token */
1266 child++;
1267 token = token->children;
1269 else if (token->next != NULL)
1271 /* Get next sibling */
1272 token = token->next;
1274 else
1276 /* Get parent */
1277 for (;;)
1279 child--;
1280 token = token->parent;
1281 if (token == NULL) break;
1282 if (token->next != NULL)
1284 token = token->next;
1285 break;
1292 return;
1295 void
1296 anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1298 if (token != NULL)
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;
1305 last_parent = NULL;
1306 last_token = token->last == NULL ? token : token->last;
1307 for (;;)
1309 if (expand && (token->children != NULL))
1311 /* Children of the last token does not belong to the group */
1312 if (token == last_token)
1314 /* Find last token */
1315 if (token->last == NULL)
1317 break;
1319 /* Last token still include additional tokens */
1320 last_token = token->last;
1323 /* Enumerate children */
1324 token = token->children;
1326 else
1328 if (token->children == NULL)
1330 /* Take into account only the content of token having no children */
1331 if (last_parent == NULL)
1333 /* Take into account only the content of group having no children */
1334 func (token, user_data);
1338 /* Check if we have found the last token */
1339 if (token == last_token)
1341 /* Find last token */
1342 if (token->last == NULL)
1344 break;
1346 /* Last token still include additional tokens */
1347 last_token = token->last;
1350 if (token == last_parent)
1352 /* Find last parent */
1353 if (token->last == NULL)
1355 /* Found complete group having children */
1356 last_parent = NULL;
1358 else
1360 /* Parent group has additional token */
1361 last_parent = token->last;
1365 if (token->next != NULL)
1367 /* Get next sibling */
1368 token = token->next;
1369 expand = TRUE;
1371 else
1373 /* Get parent */
1374 token = token->parent;
1375 expand = FALSE;
1376 if (token == NULL) break;
1377 last_parent = token->last;
1383 return;
1386 static void
1387 anjuta_token_foreach_container (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1389 if (token != NULL)
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;
1396 parent = NULL;
1397 last_token = token->last == NULL ? token : token->last;
1398 for (;;)
1400 /* Take into account only the content of parent token */
1401 if (expand && (parent == NULL))
1403 func (token, user_data);
1405 if (expand && (token->children != NULL))
1407 if (parent == NULL) parent = token;
1408 /* Enumerate children */
1409 token = token->children;
1411 else
1413 /* Check if we have found the last token */
1414 if (token == last_token)
1416 /* Find last token */
1417 if (token->last == NULL)
1419 break;
1421 /* Last token still include additional tokens */
1422 last_token = token->last;
1425 if (token->next != NULL)
1427 /* Get next sibling */
1428 token = token->next;
1429 expand = TRUE;
1431 else
1433 /* Get parent */
1434 token = token->parent;
1435 if (token == parent) parent = NULL;
1436 expand = FALSE;
1442 return;
1445 AnjutaToken *
1446 anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1448 if (token != NULL)
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;
1456 last_parent = NULL;
1457 last_token = token->last == NULL ? token : token->last;
1458 while (token != NULL)
1460 if (expand && (token->children != NULL))
1462 /* Check if we have found the last token */
1463 if (token == last_token)
1465 /* Find last token */
1466 if (token->last == NULL)
1468 break;
1470 /* Last token still include additional tokens */
1471 last_token = token->last;
1474 /* Enumerate children */
1475 token = token->children;
1477 else
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);
1484 /* Check if we have found the last token */
1485 if (token == last_token)
1487 /* Find last token */
1488 if (buffer.last == NULL)
1490 token = &buffer;
1491 break;
1493 /* Last token still include additional tokens */
1494 last_token = buffer.last;
1497 if (token == last_parent)
1499 /* Find last parent */
1500 if (buffer.last == NULL)
1502 /* Found complete group having children */
1503 last_parent = NULL;
1505 else
1507 /* Parent group has additional token */
1508 last_parent = buffer.last;
1512 if (buffer.next != NULL)
1514 /* Get next sibling */
1515 token = buffer.next;
1516 expand = TRUE;
1518 else
1520 /* Get parent */
1521 token = buffer.parent;
1522 if (token != NULL) last_parent = token->last;
1523 expand = FALSE;
1528 while ((token != NULL) && (token->next == NULL))
1530 token = token->parent;
1533 if (token != NULL) token = token->next;
1536 return token;
1539 /* Token evaluation
1540 *---------------------------------------------------------------------------*/
1542 static void
1543 evaluate_token (AnjutaToken *token, gpointer user_data)
1545 GString *value = (GString *)user_data;
1547 anjuta_token_evaluate_token (token, value, FALSE);
1551 gchar *
1552 anjuta_token_evaluate (AnjutaToken *token)
1554 GString *value = g_string_new (NULL);
1556 anjuta_token_foreach_content (token, evaluate_token, value);
1558 /* Return NULL and free data for an empty string */
1559 return g_string_free (value, *(value->str) == '\0');
1562 /* Does not evaluate content if token is a variable */
1563 gchar *
1564 anjuta_token_evaluate_name (AnjutaToken *token)
1566 GString *value = g_string_new (NULL);
1568 anjuta_token_foreach_container (token, evaluate_token, value);
1570 /* Return NULL and free data for an empty string */
1571 return g_string_free (value, *(value->str) == '\0');
1574 gboolean
1575 anjuta_token_is_empty (AnjutaToken *token)
1577 return (token == NULL) || ((token->data.length == 0) && (token->last == NULL) && (token->children == NULL));
1581 /* Other functions
1582 *---------------------------------------------------------------------------*/
1584 gboolean
1585 anjuta_token_compare (AnjutaToken *toka, AnjutaToken *tokb)
1587 if (tokb->data.type)
1589 if (tokb->data.type != toka->data.type) return FALSE;
1592 if (tokb->data.type != ANJUTA_TOKEN_NONE)
1594 if (tokb->data.length != 0)
1596 if (toka->data.length != tokb->data.length) return FALSE;
1598 if ((toka->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE) && (tokb->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE))
1600 if (g_ascii_strncasecmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1602 else
1604 if (strncmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1609 if (tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS)
1611 if ((toka->data.flags & tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS) == 0)
1612 return FALSE;
1615 return TRUE;
1618 void
1619 anjuta_token_dump (AnjutaToken *token)
1621 if (token == NULL) return;
1623 anjuta_token_dump_child (token, 0, 0);
1626 void
1627 anjuta_token_dump_link (AnjutaToken *token)
1629 AnjutaToken *last = token;
1631 while (last->last != NULL) last = last->last;
1633 for (; token != last; token = anjuta_token_next (token))
1635 anjuta_token_show (token, 0, 0);
1639 gboolean
1640 anjuta_token_check (AnjutaToken *token)
1642 if ((token->children != NULL) && (token->last != NULL))
1644 anjuta_token_show (token, 0, 0);
1645 fprintf(stderr, "Error: Previous token has both non NULL children and last\n");
1647 return FALSE;
1650 if (token->children != NULL)
1652 AnjutaToken *child;
1654 for (child = token->children; child != NULL; child = child->next)
1656 if (!anjuta_token_check_child (child, token)) return FALSE;
1660 if (token->last != NULL)
1662 AnjutaToken *child;
1664 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (child))
1666 if (!anjuta_token_check (child)) return FALSE;
1667 if (child == token->last) break;
1671 return TRUE;
1674 /* Constructor & Destructor
1675 *---------------------------------------------------------------------------*/
1677 AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const gchar *value)
1679 AnjutaToken *token;
1681 if (value == NULL)
1683 token = anjuta_token_new_static (type, NULL);
1685 else
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);
1694 return token;
1697 AnjutaToken*
1698 anjuta_token_new_string_len (AnjutaTokenType type, gchar *value, gsize length)
1700 AnjutaToken *token;
1702 if (value == NULL)
1704 token = anjuta_token_new_static (type, NULL);
1706 else
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;
1715 return token;
1718 AnjutaToken *
1719 anjuta_token_new_static_len (gint type, const gchar *pos, gsize length)
1721 AnjutaToken *token;
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;
1729 return token;
1732 AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const char *value)
1734 return anjuta_token_new_static_len (type, value, value == NULL ? 0 : strlen (value));
1737 AnjutaToken*
1738 anjuta_token_free_children (AnjutaToken *token)
1740 AnjutaToken *child;
1741 AnjutaToken *last;
1743 if (token == NULL) return NULL;
1745 for (child = token->children; child != NULL; child = token->children)
1747 anjuta_token_free (child);
1749 token->children = NULL;
1751 if (token->last != NULL)
1753 last = token->last;
1754 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (token))
1756 anjuta_token_free (child);
1757 if (child == last) break;
1760 token->last = NULL;
1762 return token;
1765 static void
1766 free_token (AnjutaToken *token, gpointer user_data)
1768 anjuta_token_unlink_token (token);
1769 if ((token->data.pos != NULL) && !(token->data.flags & ANJUTA_TOKEN_STATIC))
1771 g_free (token->data.pos);
1773 g_slice_free (AnjutaToken, token);
1777 AnjutaToken*
1778 anjuta_token_free (AnjutaToken *token)
1780 AnjutaToken *next;
1782 if (token == NULL) return NULL;
1784 next = anjuta_token_foreach_post_order (token, free_token, NULL);
1786 return next;