1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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>
31 * SECTION:anjuta-token
32 * @title: Anjuta token
33 * @short_description: Anjuta token
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:
74 * children = NULL && last = NULL
75 * This is the case of a simple token without any children.
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.
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
109 typedef struct _AnjutaTokenData AnjutaTokenData
;
111 struct _AnjutaTokenData
113 AnjutaTokenType type
;
126 AnjutaToken
*children
;
127 AnjutaTokenData data
;
131 *---------------------------------------------------------------------------*/
134 *---------------------------------------------------------------------------*/
137 anjuta_token_next_child (AnjutaToken
*child
, AnjutaToken
**last
)
139 if (child
== NULL
) return child
;
141 if (child
->children
!= NULL
)
143 child
= child
->children
;
149 if ((*last
== NULL
) || (child
== *last
))
151 if (child
->last
== NULL
)
158 if (child
->next
!= NULL
)
163 child
= child
->parent
;
171 anjuta_token_next_after_children (AnjutaToken
*token
)
173 while (token
->next
== NULL
)
175 token
= token
->parent
;
176 if (token
== NULL
) return NULL
;
183 anjuta_token_copy (AnjutaToken
*token
)
185 AnjutaToken
*copy
= 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
;
198 copy
->data
.pos
= g_strdup (token
->data
.pos
);
200 copy
->data
.length
= token
->data
.length
;
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
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
))
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
;
240 else if (prev
== token
->group
)
242 /* No more token in group */
243 token
->group
->last
= NULL
;
249 if (token
->next
!= NULL
)
251 token
->next
->prev
= token
->prev
;
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
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
;
290 anjuta_token_evaluate_token (AnjutaToken
*token
, GString
*value
, gboolean raw
)
292 if ((token
!= NULL
) && (token
->data
.length
!= 0))
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
:
309 g_string_append_len (value
, anjuta_token_get_string (token
), anjuta_token_get_length (token
));
314 anjuta_token_show (AnjutaToken
*token
, gint indent
, gchar parent
)
316 static gchar type
[] = "\0";
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
);
328 /* Value doesn't contain a newline */
329 fprintf (stderr
, "(%lu)", length
);
333 const gchar
*newline
;
335 newline
= g_strrstr_len (string
, length
, "\n");
338 /* Value doesn't contain a newline */
339 fprintf (stderr
, "\"%.*s\"",
345 /* Value contains a newline, take care of indentation */
347 fprintf (stderr
, "\"%.*s",
352 length
-= newline
- string
;
355 newline
= g_strrstr_len (string
, length
, "\n");
356 if (newline
== NULL
) break;
359 fprintf (stderr
, "%*s %.*s",
364 fprintf (stderr
, "%*s %.*s\"",
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)" : "");
377 anjuta_token_dump_child (AnjutaToken
*token
, gint indent
, gchar type
)
382 anjuta_token_show (token
, indent
, type
);
386 if (token
->last
!= NULL
)
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
, '*');
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
);
418 return anjuta_token_check (token
);
421 /* Get and set functions
422 *---------------------------------------------------------------------------*/
425 anjuta_token_set_type (AnjutaToken
*token
, gint type
)
427 token
->data
.type
= type
;
431 anjuta_token_get_type (AnjutaToken
*token
)
433 return token
->data
.type
;
437 anjuta_token_set_flags (AnjutaToken
*token
, gint flags
)
440 AnjutaToken
*last
= token
->last
;
442 for (child
= token
; child
!= NULL
; child
= anjuta_token_next_child (child
, &last
))
444 child
->data
.flags
|= flags
;
449 anjuta_token_clear_flags (AnjutaToken
*token
, gint flags
)
451 token
->data
.flags
&= ~flags
;
455 anjuta_token_get_flags (AnjutaToken
*token
)
457 return token
->data
.flags
;
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
;
473 anjuta_token_get_string (AnjutaToken
*token
)
475 return token
->data
.pos
;
479 anjuta_token_set_length (AnjutaToken
*token
, gsize length
)
481 token
->data
.length
= length
;
485 anjuta_token_get_length (AnjutaToken
*token
)
487 return token
->data
.length
;
490 /* Basic move functions
491 *---------------------------------------------------------------------------*/
494 anjuta_token_next (AnjutaToken
*token
)
496 if (token
->children
!= NULL
)
498 return token
->children
;
500 else if (token
->next
!= NULL
)
504 else if (token
->parent
!= NULL
)
506 return anjuta_token_next_after_children (token
->parent
);
515 anjuta_token_previous (AnjutaToken
*token
)
517 if (token
->prev
!= NULL
)
523 return token
->parent
;
528 anjuta_token_last (AnjutaToken
*token
)
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
);
542 anjuta_token_parent (AnjutaToken
*token
)
544 return token
->parent
;
548 anjuta_token_list (AnjutaToken
*token
)
553 /* Item move functions
554 *---------------------------------------------------------------------------*/
557 anjuta_token_last_item (AnjutaToken
*list
)
563 anjuta_token_first_item (AnjutaToken
*list
)
565 AnjutaToken
*first
= NULL
;
569 if (list
->children
!= NULL
)
571 first
= list
->children
;
573 else if (list
->last
!= NULL
)
583 anjuta_token_next_item (AnjutaToken
*item
)
592 if ((item
->group
== NULL
) || (item
->group
->last
!= item
))
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
;
601 /* Loop if the current item has been deleted */
602 while ((next
!= NULL
) && (anjuta_token_get_flags (next
) & ANJUTA_TOKEN_REMOVED
));
609 anjuta_token_previous_item (AnjutaToken
*item
)
611 AnjutaToken
*prev
= NULL
;
618 for (prev
= item
->prev
; (prev
!= NULL
) && (prev
->group
!= item
->group
); prev
= prev
->group
);
621 /* Loop if the current item has been deleted */
622 while ((prev
!= NULL
) && (anjuta_token_get_flags (prev
) & ANJUTA_TOKEN_REMOVED
));
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.
641 anjuta_token_append_child (AnjutaToken
*parent
, AnjutaToken
*children
)
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
;
662 /* Find last children */
663 for (last
= parent
->children
; last
->next
!= NULL
;)
665 if ((last
->last
!= NULL
) && (last
->last
->parent
== last
->parent
))
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
)
695 while (token
->parent
!= parent
)
697 token
= token
->parent
;
698 if (token
->next
!= NULL
) break;
700 if (token
->next
== NULL
) break;
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.
718 anjuta_token_prepend_child (AnjutaToken
*parent
, AnjutaToken
*children
)
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
;;)
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;
739 child
->next
= parent
->children
;
740 if (child
->next
) child
->next
->prev
= child
;
741 parent
->children
= 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.
756 anjuta_token_prepend_items (AnjutaToken
*list
, AnjutaToken
*item
)
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 */
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
)
784 while (token
->parent
!= list
->parent
)
786 token
= token
->parent
;
787 if (token
->next
!= NULL
) break;
789 if (token
->next
== NULL
) break;
794 token
->next
= list
->next
;
795 if (token
->next
) token
->next
->prev
= token
;
800 if (list
->last
== NULL
)
802 while (token
->group
!= list
) token
= token
->group
;
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.
819 anjuta_token_insert_after (AnjutaToken
*sibling
, AnjutaToken
*list
)
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 */
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
)
848 while (token
->parent
!= sibling
->parent
)
850 token
= token
->parent
;
851 if (token
->next
!= NULL
) break;
853 if (token
->next
== NULL
) break;
858 for (last
= sibling
; last
->last
!= NULL
; last
= last
->last
);
860 token
->next
= last
->next
;
861 if (token
->next
) token
->next
->prev
= token
;
866 if ((sibling
->group
!= NULL
) && (sibling
->group
->last
== sibling
))
868 while (token
->group
!= sibling
->group
) token
= token
->group
;
869 sibling
->group
->last
= token
;
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.
885 anjuta_token_insert_before (AnjutaToken
*sibling
, AnjutaToken
*list
)
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 */
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
)
914 while (token
->parent
!= sibling
->parent
)
916 token
= token
->parent
;
917 if (token
->next
!= NULL
) break;
919 if (token
->next
== NULL
) break;
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
;
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
946 anjuta_token_delete_parent (AnjutaToken
*parent
)
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
)
969 while (token
->parent
!= parent
->parent
)
971 token
= token
->parent
;
972 if (token
->next
!= NULL
) break;
974 if (token
->next
== NULL
) break;
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
);
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 */
995 anjuta_token_merge (AnjutaToken
*first
, AnjutaToken
*end
)
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
))
1006 if (first
->parent
== NULL
)
1008 anjuta_token_insert_before (end
, first
);
1012 anjuta_token_insert_after (first
, end
);
1018 if ((end
->group
!= NULL
) && (end
->group
!= first
) && (end
->group
->last
== end
)) end
->group
->last
= first
;
1025 anjuta_token_merge_own_children (AnjutaToken
*group
)
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
))
1038 if (token
->last
!= NULL
)
1041 //token->last = NULL;
1043 token
->group
= group
;
1045 else if (next
== token
)
1055 anjuta_token_merge_children (AnjutaToken
*first
, AnjutaToken
*end
)
1061 if ((first
== end
) || (end
== NULL
))
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
)
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
;
1087 anjuta_token_free (end
);
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
1103 * Return value: the new list
1106 anjuta_token_merge_previous (AnjutaToken
*list
, AnjutaToken
*first
)
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
);
1129 AnjutaToken
*anjuta_token_split (AnjutaToken
*token
, guint size
)
1131 if (token
->data
.length
> size
)
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
;
1146 memcpy(token
->data
.pos
, token
->data
.pos
+ size
, token
->data
.length
- size
);
1158 anjuta_token_cut (AnjutaToken
*token
, guint pos
, guint size
)
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
;
1184 memcpy(copy
->data
.pos
, copy
->data
.pos
+ pos
, size
);
1186 copy
->data
.length
= size
;
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
));
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);
1219 anjuta_token_concat(AnjutaToken
*token
)
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
);
1233 *---------------------------------------------------------------------------*/
1236 anjuta_token_foreach_token (AnjutaToken
*token
, AnjutaTokenForeachFunc func
, gpointer user_data
)
1240 AnjutaToken
*last_token
;
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
)
1256 /* Last token still include additional tokens */
1257 last_token
= token
->last
;
1260 if (token
->children
!= NULL
)
1262 /* Check children, only for last token */
1264 token
= token
->children
;
1266 else if (token
->next
!= NULL
)
1268 /* Get next sibling */
1269 token
= token
->next
;
1277 token
= token
->parent
;
1278 if (token
== NULL
) break;
1279 if (token
->next
!= NULL
)
1281 token
= token
->next
;
1293 anjuta_token_foreach_content (AnjutaToken
*token
, AnjutaTokenForeachFunc func
, gpointer user_data
)
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
;
1303 last_token
= token
->last
== NULL
? token
: token
->last
;
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
)
1316 /* Last token still include additional tokens */
1317 last_token
= token
->last
;
1320 /* Enumerate children */
1321 token
= token
->children
;
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
)
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 */
1357 /* Parent group has additional token */
1358 last_parent
= token
->last
;
1362 if (token
->next
!= NULL
)
1364 /* Get next sibling */
1365 token
= token
->next
;
1371 token
= token
->parent
;
1372 if (token
!= NULL
) last_parent
= token
->last
;
1383 anjuta_token_foreach_container (AnjutaToken
*token
, AnjutaTokenForeachFunc func
, gpointer user_data
)
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
;
1393 last_token
= token
->last
== NULL
? token
: token
->last
;
1396 if (expand
&& (token
->children
!= NULL
))
1398 if (parent
== NULL
) parent
= token
;
1399 /* Enumerate children */
1400 token
= token
->children
;
1404 /* Take into account only the content of parent token */
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
)
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
;
1432 token
= token
->parent
;
1433 if (token
== parent
) parent
= NULL
;
1444 anjuta_token_foreach_post_order (AnjutaToken
*token
, AnjutaTokenForeachFunc func
, gpointer user_data
)
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
;
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
)
1468 /* Last token still include additional tokens */
1469 last_token
= token
->last
;
1472 /* Enumerate children */
1473 token
= token
->children
;
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
)
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 */
1505 /* Parent group has additional token */
1506 last_parent
= buffer
.last
;
1510 if (buffer
.next
!= NULL
)
1512 /* Get next sibling */
1513 token
= buffer
.next
;
1519 token
= buffer
.parent
;
1520 if (token
!= NULL
) last_parent
= token
->last
;
1526 while ((token
!= NULL
) && (token
->next
== NULL
))
1528 token
= token
->parent
;
1531 if (token
!= NULL
) token
= token
->next
;
1538 *---------------------------------------------------------------------------*/
1541 evaluate_raw_token (AnjutaToken
*token
, gpointer user_data
)
1543 GString
*value
= (GString
*)user_data
;
1545 anjuta_token_evaluate_token (token
, value
, TRUE
);
1549 evaluate_token (AnjutaToken
*token
, gpointer user_data
)
1551 GString
*value
= (GString
*)user_data
;
1553 anjuta_token_evaluate_token (token
, value
, FALSE
);
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 */
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');
1581 anjuta_token_is_empty (AnjutaToken
*token
)
1583 return (token
== NULL
) || ((token
->data
.length
== 0) && (token
->last
== NULL
) && (token
->children
== NULL
));
1588 *---------------------------------------------------------------------------*/
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
;
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)
1625 anjuta_token_dump (AnjutaToken
*token
)
1627 if (token
== NULL
) return;
1629 anjuta_token_dump_child (token
, 0, 0);
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);
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");
1656 if (token
->children
!= NULL
)
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
)
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;
1680 /* Constructor & Destructor
1681 *---------------------------------------------------------------------------*/
1683 AnjutaToken
*anjuta_token_new_string (AnjutaTokenType type
, const gchar
*value
)
1689 token
= anjuta_token_new_static (type
, NULL
);
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
);
1704 anjuta_token_new_string_len (AnjutaTokenType type
, gchar
*value
, gsize length
)
1710 token
= anjuta_token_new_static (type
, NULL
);
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
;
1725 anjuta_token_new_static_len (gint type
, const gchar
*pos
, gsize length
)
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
;
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
));
1744 anjuta_token_free_children (AnjutaToken
*token
)
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
)
1760 for (child
= anjuta_token_next (token
); child
!= NULL
; child
= anjuta_token_next (token
))
1762 anjuta_token_free (child
);
1763 if (child
== last
) break;
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
);
1784 anjuta_token_free (AnjutaToken
*token
)
1788 if (token
== NULL
) return NULL
;
1790 next
= anjuta_token_foreach_post_order (token
, free_token
, NULL
);