libanjuta: Fix some warnings and made AnjutaPluginDescription a boxed type
[anjuta.git] / libanjuta / anjuta-token.c
blobfbeaf1ad690af7d4f03dff1cebaabe37ea5602bf
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->last != NULL) token = token->last;
174 while (token->next == NULL)
176 token = token->parent;
177 if (token == NULL) return NULL;
178 while (token->last != NULL) token = token->last;
181 return token->next;
184 static AnjutaToken *
185 anjuta_token_copy (AnjutaToken *token)
187 AnjutaToken *copy = NULL;
189 if (token != NULL)
191 copy = g_slice_new0 (AnjutaToken);
192 copy->data.type = token->data.type;
193 copy->data.flags = token->data.flags;
194 if ((copy->data.flags & ANJUTA_TOKEN_STATIC) || (token->data.pos == NULL))
196 copy->data.pos = token->data.pos;
198 else
200 copy->data.pos = g_strdup (token->data.pos);
202 copy->data.length = token->data.length;
205 return copy;
209 * anjuta_token_unlink_token:
210 * @token: a #AnjutaToken object.
212 * Unlink a single token, not the complete item, from the token tree.
214 * Return value: the removed token tree
216 static AnjutaToken *
217 anjuta_token_unlink_token (AnjutaToken *token)
220 if (token->prev != NULL)
222 token->prev->next = token->next;
224 else if ((token->parent != NULL) && (token->parent->children == token))
226 token->parent->children = token->next;
228 token->parent = NULL;
230 if ((token->group != NULL) && (token->group->last == token))
232 AnjutaToken *prev;
234 for (prev = token->prev; prev != NULL; prev = prev->prev)
236 if (prev->group == token->group)
238 /* Find previous token in the same group */
239 token->group->last = prev;
240 break;
242 else if (prev == token->group)
244 /* No more token in group */
245 token->group->last = NULL;
246 break;
251 if (token->next != NULL)
253 token->next->prev = token->prev;
254 token->next = NULL;
256 token->prev = NULL;
258 return token;
262 * anjuta_token_insert_token_before:
263 * @sibling: a #AnjutaToken object.
264 * @token: a #AnjutaToken object.
266 * Insert token before sibling.
268 * Return value: inserted token
270 static AnjutaToken *
271 anjuta_token_insert_token_before (AnjutaToken *sibling, AnjutaToken *token)
273 token->prev = sibling->prev;
274 token->next = sibling;
276 if (token->prev != NULL)
278 token->prev->next = token;
280 sibling->prev = token;
282 if ((sibling->parent != NULL) && (sibling->parent->children == sibling))
284 sibling->parent->children = token;
286 token->parent = sibling->parent;
288 return token;
291 static void
292 anjuta_token_evaluate_token (AnjutaToken *token, GString *value, gboolean raw)
294 if ((token != NULL) && (token->data.length != 0))
296 if (!raw)
298 switch (anjuta_token_get_type (token))
300 case ANJUTA_TOKEN_COMMENT:
301 case ANJUTA_TOKEN_OPEN_QUOTE:
302 case ANJUTA_TOKEN_CLOSE_QUOTE:
303 case ANJUTA_TOKEN_ESCAPE:
304 case ANJUTA_TOKEN_MACRO:
305 case ANJUTA_TOKEN_EOV:
306 return;
307 default:
308 break;
311 g_string_append_len (value, anjuta_token_get_string (token), anjuta_token_get_length (token));
315 static void
316 anjuta_token_show (AnjutaToken *token, gint indent, gchar parent)
318 static gchar type[] = "\0";
319 const gchar *string;
320 gsize length;
322 type[0] = parent;
323 fprintf (stderr, "%*s%s %p", indent, "", type, token);
324 fprintf (stderr, ": %d ",
325 anjuta_token_get_type (token));
326 string = anjuta_token_get_string (token);
327 length = anjuta_token_get_length (token);
328 if (string == NULL)
330 /* Value doesn't contain a newline */
331 fprintf (stderr, "(%lu)", length);
333 else
335 const gchar *newline;
337 newline = g_strrstr_len (string, length, "\n");
338 if (newline == NULL)
340 /* Value doesn't contain a newline */
341 fprintf (stderr, "\"%.*s\"",
342 length,
343 string);
345 else
347 /* Value contains a newline, take care of indentation */
348 newline++;
349 fprintf (stderr, "\"%.*s",
350 newline - string,
351 string);
352 for (;;)
354 length -= newline - string;
355 string = newline;
357 newline = g_strrstr_len (string, length, "\n");
358 if (newline == NULL) break;
360 newline++;
361 fprintf (stderr, "%*s %.*s",
362 indent, "",
363 newline - string,
364 string);
366 fprintf (stderr, "%*s %.*s\"",
367 indent, "",
368 length,
369 string);
372 fprintf (stderr, " %p/%p (%p/%p) %s\n",
373 token->last, token->children,
374 token->group, token->parent,
375 anjuta_token_get_flags (token) & ANJUTA_TOKEN_REMOVED ? " (removed)" : "");
378 static AnjutaToken*
379 anjuta_token_dump_child (AnjutaToken *token, gint indent, gchar type)
381 AnjutaToken *last;
382 AnjutaToken *child;
384 anjuta_token_show (token, indent, type);
385 indent += 4;
387 last = token;
388 if (token->last != NULL)
392 child = last->next;
393 if (child == NULL) break;
394 last = anjuta_token_dump_child (child, indent, '+');
396 while (child != token->last);
399 if (token->children != NULL)
401 for (child = token->children; child != NULL; child = child->next)
403 child = anjuta_token_dump_child (child, indent, '*');
407 return last;
410 static gboolean
411 anjuta_token_check_child (AnjutaToken *token, AnjutaToken *parent)
413 if (token->parent != parent)
415 anjuta_token_show (token, 0, 0);
416 fprintf(stderr, "Error: Children has %p as parent instead of %p\n", token->parent, parent);
417 return FALSE;
420 return anjuta_token_check (token);
423 /* Get and set functions
424 *---------------------------------------------------------------------------*/
426 void
427 anjuta_token_set_type (AnjutaToken *token, gint type)
429 token->data.type = type;
432 gint
433 anjuta_token_get_type (AnjutaToken *token)
435 return token->data.type;
438 void
439 anjuta_token_set_flags (AnjutaToken *token, gint flags)
441 AnjutaToken *child;
442 AnjutaToken *last = token->last;
444 for (child = token; child != NULL; child = anjuta_token_next_child (child, &last))
446 child->data.flags |= flags;
450 void
451 anjuta_token_clear_flags (AnjutaToken *token, gint flags)
453 token->data.flags &= ~flags;
456 gint
457 anjuta_token_get_flags (AnjutaToken *token)
459 return token->data.flags;
462 void
463 anjuta_token_set_string (AnjutaToken *token, const gchar *data, gsize length)
465 if (!(token->data.flags & ANJUTA_TOKEN_STATIC))
467 g_free (token->data.pos);
468 token->data.flags |= ANJUTA_TOKEN_STATIC;
470 token->data.pos = (gchar *)data;
471 token->data.length = length;
474 const gchar *
475 anjuta_token_get_string (AnjutaToken *token)
477 return token->data.pos;
480 void
481 anjuta_token_set_length (AnjutaToken *token, gsize length)
483 token->data.length = length;
486 gsize
487 anjuta_token_get_length (AnjutaToken *token)
489 return token->data.length;
492 /* Basic move functions
493 *---------------------------------------------------------------------------*/
495 AnjutaToken *
496 anjuta_token_next (AnjutaToken *token)
498 if (token->children != NULL)
500 return token->children;
502 else if (token->next != NULL)
504 return token->next;
506 else if (token->parent != NULL)
508 return anjuta_token_next_after_children (token->parent);
510 else
512 return NULL;
516 AnjutaToken *
517 anjuta_token_previous (AnjutaToken *token)
519 if (token->prev != NULL)
521 return token->prev;
523 else
525 return token->parent;
529 AnjutaToken *
530 anjuta_token_last (AnjutaToken *token)
532 AnjutaToken *last;
534 for (last = token; last->last != NULL; last = last->last);
535 if (last->children != NULL)
537 for (last = last->children; last->next != NULL; last = last->next);
540 return last;
543 AnjutaToken *
544 anjuta_token_parent (AnjutaToken *token)
546 return token->parent;
549 AnjutaToken *
550 anjuta_token_list (AnjutaToken *token)
552 return token->group;
555 /* Item move functions
556 *---------------------------------------------------------------------------*/
558 AnjutaToken *
559 anjuta_token_last_item (AnjutaToken *list)
561 return list->last;
564 AnjutaToken *
565 anjuta_token_first_item (AnjutaToken *list)
567 AnjutaToken *first = NULL;
569 if (list != NULL)
571 if (list->children != NULL)
573 first = list->children;
575 else if (list->last != NULL)
577 first = list->next;
581 return first;
584 AnjutaToken *
585 anjuta_token_next_item (AnjutaToken *item)
587 AnjutaToken *next;
589 if (item != NULL)
593 next = NULL;
594 if ((item->group == NULL) || (item->group->last != item))
596 AnjutaToken *last;
597 for (last = item; last->last != NULL; last = last->last);
598 next = anjuta_token_next (last);
599 if ((next != NULL) && (next->group != item->group)) next = NULL;
601 item = next;
603 /* Loop if the current item has been deleted */
604 while ((next != NULL) && (anjuta_token_get_flags (next) & ANJUTA_TOKEN_REMOVED));
607 return next;
610 AnjutaToken *
611 anjuta_token_previous_item (AnjutaToken *item)
613 AnjutaToken *prev = NULL;
616 if (item != NULL)
620 for (prev = item->prev; (prev != NULL) && (prev->group != item->group); prev = prev->group);
621 item = prev;
623 /* Loop if the current item has been deleted */
624 while ((prev != NULL) && (anjuta_token_get_flags (prev) & ANJUTA_TOKEN_REMOVED));
627 return prev;
630 /* Add/Insert/Remove tokens
631 *---------------------------------------------------------------------------*/
634 * anjuta_token_append_child:
635 * @parent: a #AnjutaToken object used as parent.
636 * @children: a #AnjutaToken object.
638 * Insert all tokens in children as the last children of the given parent.
640 * Return value: The first token append.
642 AnjutaToken *
643 anjuta_token_append_child (AnjutaToken *parent, AnjutaToken *children)
645 AnjutaToken *token;
646 AnjutaToken *last;
647 AnjutaToken *old_group;
648 AnjutaToken *old_parent;
650 g_return_val_if_fail (parent != NULL, NULL);
651 g_return_val_if_fail (children != NULL, NULL);
653 old_group = children->group;
654 old_parent = children->parent;
656 if (parent->children == NULL)
658 parent->children = children;
660 children->prev = NULL;
662 else
664 /* Find last children */
665 for (last = parent->children; last->next != NULL;)
667 if ((last->last != NULL) && (last->last->parent == last->parent))
669 last = last->last;
671 else
673 last = last->next;
677 last->next = children;
678 children->prev = last;
681 /* Update each token */
682 for (token = children;;)
684 if (token->parent == old_parent) token->parent = parent;
685 if (token->group == old_group) token->group = parent->group;
687 if (token->children != NULL)
689 token = token->children;
691 else if (token->next != NULL)
693 token = token->next;
695 else
697 while (token->parent != parent)
699 token = token->parent;
700 if (token->next != NULL) break;
702 if (token->next == NULL) break;
703 token = token->next;
707 return children;
711 * anjuta_token_prepend_child:
712 * @parent: a #AnjutaToken object used as parent.
713 * @children: a #AnjutaToken object.
715 * Insert all tokens in children as the first children of the given parent.
717 * Return value: The first token append.
719 AnjutaToken *
720 anjuta_token_prepend_child (AnjutaToken *parent, AnjutaToken *children)
722 AnjutaToken *child;
723 AnjutaToken *last = NULL;
725 g_return_val_if_fail (parent != NULL, NULL);
726 g_return_val_if_fail (children != NULL, NULL);
728 /* Update each token */
729 for (child = children;;)
731 AnjutaToken *next;
733 if (child->parent == children->parent) child->parent = parent;
734 if (child->group == children->group) child->group = parent->group;
736 next = anjuta_token_next_child (child, &last);
737 if (next == NULL) break;
738 child = next;
741 child->next = parent->children;
742 if (child->next) child->next->prev = child;
743 parent->children = children;
745 return children;
749 * anjuta_token_prepend_items:
750 * @list: a #AnjutaToken object used as list.
751 * @item: a #AnjutaToken object.
753 * Insert all tokens in item as item of the given list.
755 * Return value: The first token append.
757 AnjutaToken *
758 anjuta_token_prepend_items (AnjutaToken *list, AnjutaToken *item)
760 AnjutaToken *token;
761 AnjutaToken *old_group;
762 AnjutaToken *old_parent;
764 g_return_val_if_fail (list != NULL, NULL);
765 g_return_val_if_fail (item != NULL, NULL);
767 old_group = item->group;
768 old_parent = item->parent;
770 /* Update each token */
771 for (token = item;;)
773 if (token->parent == old_parent) token->parent = list->parent;
774 if (token->group == old_group) token->group = list;
776 if (token->children != NULL)
778 token = token->children;
780 else if (token->next != NULL)
782 token = token->next;
784 else
786 while (token->parent != list->parent)
788 token = token->parent;
789 if (token->next != NULL) break;
791 if (token->next == NULL) break;
792 token = token->next;
796 token->next = list->next;
797 if (token->next) token->next->prev = token;
799 list->next = item;
800 item->prev = list;
802 if (list->last == NULL)
804 while (token->group != list) token = token->group;
805 list->last = token;
808 return item;
812 * anjuta_token_insert_after:
813 * @sibling: a #AnjutaToken object.
814 * @list: a #AnjutaToken object.
816 * Insert all tokens after sibling.
818 * Return value: The first token inserted.
820 AnjutaToken *
821 anjuta_token_insert_after (AnjutaToken *sibling, AnjutaToken *list)
823 AnjutaToken *last;
824 AnjutaToken *token;
825 AnjutaToken *old_group;
826 AnjutaToken *old_parent;
828 g_return_val_if_fail (sibling != NULL, NULL);
829 g_return_val_if_fail (list != NULL, NULL);
831 old_group = list->group;
832 old_parent = list->parent;
834 /* Update each token */
835 for (token = list;;)
837 if (token->parent == old_parent) token->parent = sibling->parent;
838 if (token->group == old_group) token->group = sibling->group;
840 if (token->children != NULL)
842 token = token->children;
844 else if (token->next != NULL)
846 token = token->next;
848 else
850 while (token->parent != sibling->parent)
852 token = token->parent;
853 if (token->next != NULL) break;
855 if (token->next == NULL) break;
856 token = token->next;
860 for (last = sibling; last->last != NULL; last = last->last);
862 token->next = last->next;
863 if (token->next) token->next->prev = token;
865 last->next = list;
866 list->prev = last;
868 if ((sibling->group != NULL) && (sibling->group->last == sibling))
870 while (token->group != sibling->group) token = token->group;
871 sibling->group->last = token;
874 return list;
878 * anjuta_token_insert_before:
879 * @sibling: a #AnjutaToken object.
880 * @list: a #AnjutaToken object.
882 * Insert all tokens before sibling.
884 * Return value: The first token inserted.
886 AnjutaToken *
887 anjuta_token_insert_before (AnjutaToken *sibling, AnjutaToken *list)
889 AnjutaToken *last;
890 AnjutaToken *token;
891 AnjutaToken *old_group;
892 AnjutaToken *old_parent;
894 g_return_val_if_fail (sibling != NULL, NULL);
895 g_return_val_if_fail (list != NULL, NULL);
897 old_group = list->group;
898 old_parent = list->parent;
900 /* Update each token */
901 for (token = list;;)
903 if (token->parent == old_parent) token->parent = sibling->parent;
904 if (token->group == old_group) token->group = sibling->group;
906 if (token->children != NULL)
908 token = token->children;
910 else if (token->next != NULL)
912 token = token->next;
914 else
916 while (token->parent != sibling->parent)
918 token = token->parent;
919 if (token->next != NULL) break;
921 if (token->next == NULL) break;
922 token = token->next;
926 for (last = sibling; last->last != NULL; last = last->last);
928 token->next = sibling;
929 list->prev = sibling->prev;
930 sibling->prev = token;
932 if (list->prev) list->prev->next = list;
934 if ((list->parent != NULL) && (list->parent->children == sibling)) list->parent->children = list;
936 return list;
940 * anjuta_token_delete_parent:
941 * @parent: a #AnjutaToken object used as parent.
943 * Delete only the parent token.
945 * Return value: the first children
947 AnjutaToken *
948 anjuta_token_delete_parent (AnjutaToken *parent)
950 AnjutaToken *token;
952 g_return_val_if_fail (parent != NULL, NULL);
954 if (parent->children == NULL) return NULL;
956 /* Update each token */
957 for (token = parent->children;;)
959 if (token->parent == parent) token->parent = parent->parent;
961 if (token->children != NULL)
963 token = token->children;
965 else if (token->next != NULL)
967 token = token->next;
969 else
971 while (token->parent != parent->parent)
973 token = token->parent;
974 if (token->next != NULL) break;
976 if (token->next == NULL) break;
977 token = token->next;
981 token->next = parent->next;
982 if (token->next) token->next->prev = token;
984 parent->next = parent->children;
985 parent->children->prev = parent;
986 parent->children = NULL;
988 return anjuta_token_free (parent);
991 /* Merge function
992 *---------------------------------------------------------------------------*/
994 /* anjuta_token_merge can be used with first or end being a floating token and
995 * on already grouped tokens to change the group organisation */
996 AnjutaToken *
997 anjuta_token_merge (AnjutaToken *first, AnjutaToken *end)
999 AnjutaToken *next;
1001 if ((first == end) || (end == NULL)) return first;
1003 /* Insert first or end in the same sequence if it is not already the case */
1004 for (next = first; next != end; next = anjuta_token_next (next))
1006 if (next == NULL)
1008 if (first->parent == NULL)
1010 anjuta_token_insert_before (end, first);
1012 else
1014 anjuta_token_insert_after (first, end);
1016 break;
1019 first->last = end;
1020 if ((end->group != NULL) && (end->group != first) && (end->group->last == end)) end->group->last = first;
1021 end->group = first;
1023 return first;
1026 AnjutaToken *
1027 anjuta_token_merge_own_children (AnjutaToken *group)
1029 AnjutaToken *token;
1030 AnjutaToken *next = NULL;
1032 if (group->last != NULL) return group;
1034 if (group->last->last != NULL) group->last = group->last->last;
1036 for (token = anjuta_token_next (group); (token != NULL) && (token != group->last); token = anjuta_token_next (token))
1038 if (next == NULL)
1040 if (token->last != NULL)
1042 next = token->last;
1043 //token->last = NULL;
1045 token->group = group;
1047 else if (next == token)
1049 next = NULL;
1053 return group;
1056 AnjutaToken *
1057 anjuta_token_merge_children (AnjutaToken *first, AnjutaToken *end)
1059 if (first == NULL)
1061 return end;
1063 if ((first == end) || (end == NULL))
1065 return first;
1068 if (first->parent == NULL)
1070 first->parent = end->parent;
1072 if (first->next == NULL)
1074 anjuta_token_insert_before (end, first);
1076 anjuta_token_unlink_token (end);
1077 if (end->last != NULL)
1079 AnjutaToken *child;
1081 first->last = end->last;
1082 for (child = anjuta_token_next (first); child != first->last; child = anjuta_token_next (child))
1084 if (child->group == end) child->group = first;
1086 first->last->group = first;
1088 end->group = first;
1089 anjuta_token_free (end);
1091 return first;
1095 * anjuta_token_merge_previous:
1096 * @list: a #AnjutaToken object representing a list
1097 * @first: a #AnjutaToken object for the new beginning of the list
1099 * If the list token is not already linked with first, it is inserted
1100 * just before first.
1101 * If the list token is already linked, it must be in the same list after
1102 * first token. It it possible to have several tokens beweent list and
1103 * first.
1105 * Return value: the new list
1107 AnjutaToken *
1108 anjuta_token_merge_previous (AnjutaToken *list, AnjutaToken *first)
1110 AnjutaToken *token;
1112 if ((first == NULL) || (list == first)) return list;
1114 /* Change group of all tokens from end to first
1115 * if the list is already linked */
1116 if ((list->prev != NULL) || (list->parent != NULL))
1118 for (token = first; token != NULL; token = anjuta_token_next_item (token))
1120 token->group = list;
1124 token = anjuta_token_next (list);
1125 anjuta_token_unlink_token (list);
1126 anjuta_token_insert_token_before (first, list);
1128 return list;
1131 AnjutaToken *anjuta_token_split (AnjutaToken *token, guint size)
1133 if (token->data.length > size)
1135 AnjutaToken *copy;
1137 copy = anjuta_token_copy (token);
1138 anjuta_token_insert_before (token, copy);
1140 copy->data.length = size;
1141 if (token->data.flags & ANJUTA_TOKEN_STATIC)
1143 token->data.pos += size;
1144 token->data.length -= size;
1146 else
1148 memcpy(token->data.pos, token->data.pos + size, token->data.length - size);
1151 return copy;
1153 else
1155 return token;
1159 AnjutaToken *
1160 anjuta_token_cut (AnjutaToken *token, guint pos, guint size)
1162 AnjutaToken *copy;
1164 copy = anjuta_token_copy (token);
1166 if (pos >= token->data.length)
1168 if (!(copy->data.flags & ANJUTA_TOKEN_STATIC))
1170 g_free (copy->data.pos);
1172 copy->data.pos = NULL;
1173 copy->data.length = 0;
1175 if ((pos + size) > token->data.length)
1177 size = token->data.length - pos;
1180 if (copy->data.flags & ANJUTA_TOKEN_STATIC)
1182 copy->data.pos += pos;
1184 else
1186 memmove(copy->data.pos, copy->data.pos + pos, size);
1188 copy->data.length = size;
1190 return copy;
1193 static void
1194 concat_token (AnjutaToken *token, gpointer user_data)
1196 AnjutaToken *first = (AnjutaToken *)user_data;
1198 if (anjuta_token_get_length (token) > 0)
1200 if (anjuta_token_get_string (first) == NULL)
1202 anjuta_token_set_string (first, anjuta_token_get_string (token), anjuta_token_get_length (token));
1204 else if ((first != NULL) && ((anjuta_token_get_string(first) + anjuta_token_get_length (first)) == anjuta_token_get_string (token)))
1206 anjuta_token_set_string (first, anjuta_token_get_string (first), anjuta_token_get_length (first) + anjuta_token_get_length (token));
1208 else
1210 AnjutaToken *new;
1212 new = anjuta_token_new_static_len (ANJUTA_TOKEN_CONTENT, anjuta_token_get_string (token), anjuta_token_get_length (token));
1213 anjuta_token_insert_after (first, new);
1214 anjuta_token_merge (first, new);
1220 AnjutaToken *
1221 anjuta_token_concat(AnjutaToken *token)
1223 AnjutaToken *new;
1225 new = anjuta_token_new_static (ANJUTA_TOKEN_CONTENT, NULL);
1226 anjuta_token_foreach_token (token, concat_token, new);
1228 anjuta_token_insert_token_before (token, new);
1229 anjuta_token_free (token);
1231 return new;
1234 /* Token foreach
1235 *---------------------------------------------------------------------------*/
1237 void
1238 anjuta_token_foreach_token (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1240 if (token != NULL)
1242 AnjutaToken *last_token;
1243 gint child = 0;
1245 last_token = token->last == NULL ? token : token->last;
1246 while (token != NULL)
1248 if (child == 0) func (token, user_data);
1250 /* Check if we have found the last token */
1251 if (token == last_token)
1253 /* Find last token */
1254 if (token->last == NULL)
1256 break;
1258 /* Last token still include additional tokens */
1259 last_token = token->last;
1262 if (token->children != NULL)
1264 /* Check children, only for last token */
1265 child++;
1266 token = token->children;
1268 else if (token->next != NULL)
1270 /* Get next sibling */
1271 token = token->next;
1273 else
1275 /* Get parent */
1276 for (;;)
1278 child--;
1279 token = token->parent;
1280 if (token == NULL) break;
1281 if (token->next != NULL)
1283 token = token->next;
1284 break;
1291 return;
1294 void
1295 anjuta_token_foreach_content (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1297 if (token != NULL)
1299 AnjutaToken *last_parent; /* If not NULL, token belong to a parent and
1300 * are not taken into account */
1301 AnjutaToken *last_token;
1302 gboolean expand = TRUE;
1304 last_parent = NULL;
1305 last_token = token->last == NULL ? token : token->last;
1306 for (;;)
1308 if (expand && (token->children != NULL))
1310 /* Children of the last token does not belong to the group */
1311 if (token == last_token)
1313 /* Find last token */
1314 if (token->last == NULL)
1316 break;
1318 /* Last token still include additional tokens */
1319 last_token = token->last;
1322 /* Enumerate children */
1323 token = token->children;
1325 else
1327 if (token->children == NULL)
1329 /* Take into account only the content of token having no children */
1330 if (last_parent == NULL)
1332 /* Take into account only the content of group having no children */
1333 func (token, user_data);
1337 /* Check if we have found the last token */
1338 if (token == last_token)
1340 /* Find last token */
1341 if (token->last == NULL)
1343 break;
1345 /* Last token still include additional tokens */
1346 last_token = token->last;
1349 if (token == last_parent)
1351 /* Find last parent */
1352 if (token->last == NULL)
1354 /* Found complete group having children */
1355 last_parent = NULL;
1357 else
1359 /* Parent group has additional token */
1360 last_parent = token->last;
1364 if (token->next != NULL)
1366 /* Get next sibling */
1367 token = token->next;
1368 expand = TRUE;
1370 else
1372 /* Get parent */
1373 token = token->parent;
1374 if (token != NULL) last_parent = token->last;
1375 expand = FALSE;
1381 return;
1384 void
1385 anjuta_token_foreach_container (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1387 if (token != NULL)
1389 AnjutaToken *parent; /* If not NULL, token belong to a parent and
1390 * are not taken into account */
1391 AnjutaToken *last_token;
1392 gboolean expand = TRUE;
1394 parent = NULL;
1395 last_token = token->last == NULL ? token : token->last;
1396 for (;;)
1398 /* Take into account only the content of parent token */
1399 if (expand && (parent == NULL))
1401 func (token, user_data);
1403 if (expand && (token->children != NULL))
1405 if (parent == NULL) parent = token;
1406 /* Enumerate children */
1407 token = token->children;
1409 else
1411 /* Check if we have found the last token */
1412 if (token == last_token)
1414 /* Find last token */
1415 if (token->last == NULL)
1417 break;
1419 /* Last token still include additional tokens */
1420 last_token = token->last;
1423 if (token->next != NULL)
1425 /* Get next sibling */
1426 token = token->next;
1427 expand = TRUE;
1429 else
1431 /* Get parent */
1432 token = token->parent;
1433 if (token == parent) parent = NULL;
1434 expand = FALSE;
1440 return;
1443 AnjutaToken *
1444 anjuta_token_foreach_post_order (AnjutaToken *token, AnjutaTokenForeachFunc func, gpointer user_data)
1446 if (token != NULL)
1448 AnjutaToken *last_parent; /* If not NULL, token belong to a parent */
1449 AnjutaToken *last_token;
1450 AnjutaToken buffer; /* Temporary token allowing func to destroy
1451 * the current token */
1452 gboolean expand = TRUE;
1454 last_parent = NULL;
1455 last_token = token->last == NULL ? token : token->last;
1456 while (token != NULL)
1458 if (expand && (token->children != NULL))
1460 /* Check if we have found the last token */
1461 if (token == last_token)
1463 /* Find last token */
1464 if (token->last == NULL)
1466 break;
1468 /* Last token still include additional tokens */
1469 last_token = token->last;
1472 /* Enumerate children */
1473 token = token->children;
1475 else
1477 /* Save token data in case it is destroyed */
1478 memcpy (&buffer, token, sizeof (buffer));
1479 /* Take into account all token */
1480 func (token, user_data);
1482 /* Check if we have found the last token */
1483 if (token == last_token)
1485 /* Find last token */
1486 if (buffer.last == NULL)
1488 token = &buffer;
1489 break;
1491 /* Last token still include additional tokens */
1492 last_token = buffer.last;
1495 if (token == last_parent)
1497 /* Find last parent */
1498 if (buffer.last == NULL)
1500 /* Found complete group having children */
1501 last_parent = NULL;
1503 else
1505 /* Parent group has additional token */
1506 last_parent = buffer.last;
1510 if (buffer.next != NULL)
1512 /* Get next sibling */
1513 token = buffer.next;
1514 expand = TRUE;
1516 else
1518 /* Get parent */
1519 token = buffer.parent;
1520 if (token != NULL) last_parent = token->last;
1521 expand = FALSE;
1526 while ((token != NULL) && (token->next == NULL))
1528 token = token->parent;
1531 if (token != NULL) token = token->next;
1534 return token;
1537 /* Token evaluation
1538 *---------------------------------------------------------------------------*/
1540 static void
1541 evaluate_raw_token (AnjutaToken *token, gpointer user_data)
1543 GString *value = (GString *)user_data;
1545 anjuta_token_evaluate_token (token, value, TRUE);
1548 static void
1549 evaluate_token (AnjutaToken *token, gpointer user_data)
1551 GString *value = (GString *)user_data;
1553 anjuta_token_evaluate_token (token, value, FALSE);
1557 gchar *
1558 anjuta_token_evaluate (AnjutaToken *token)
1560 GString *value = g_string_new (NULL);
1562 anjuta_token_foreach_content (token, evaluate_token, value);
1564 /* Return NULL and free data for an empty string */
1565 return g_string_free (value, *(value->str) == '\0');
1568 /* Does not evaluate content if token is a variable */
1569 gchar *
1570 anjuta_token_evaluate_name (AnjutaToken *token)
1572 GString *value = g_string_new (NULL);
1574 anjuta_token_foreach_container (token, evaluate_token, value);
1576 /* Return NULL and free data for an empty string */
1577 return g_string_free (value, *(value->str) == '\0');
1580 gboolean
1581 anjuta_token_is_empty (AnjutaToken *token)
1583 return (token == NULL) || ((token->data.length == 0) && (token->last == NULL) && (token->children == NULL));
1587 /* Other functions
1588 *---------------------------------------------------------------------------*/
1590 gboolean
1591 anjuta_token_compare (AnjutaToken *toka, AnjutaToken *tokb)
1593 if (tokb->data.type)
1595 if (tokb->data.type != toka->data.type) return FALSE;
1598 if (tokb->data.type != ANJUTA_TOKEN_NONE)
1600 if (tokb->data.length != 0)
1602 if (toka->data.length != tokb->data.length) return FALSE;
1604 if ((toka->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE) && (tokb->data.flags & ANJUTA_TOKEN_CASE_INSENSITIVE))
1606 if (g_ascii_strncasecmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1608 else
1610 if (strncmp (toka->data.pos, tokb->data.pos, toka->data.length) != 0) return FALSE;
1615 if (tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS)
1617 if ((toka->data.flags & tokb->data.flags & ANJUTA_TOKEN_PUBLIC_FLAGS) == 0)
1618 return FALSE;
1621 return TRUE;
1624 void
1625 anjuta_token_dump (AnjutaToken *token)
1627 if (token == NULL) return;
1629 anjuta_token_dump_child (token, 0, 0);
1632 void
1633 anjuta_token_dump_link (AnjutaToken *token)
1635 AnjutaToken *last = token;
1637 while (last->last != NULL) last = last->last;
1639 for (; token != last; token = anjuta_token_next (token))
1641 anjuta_token_show (token, 0, 0);
1645 gboolean
1646 anjuta_token_check (AnjutaToken *token)
1648 if ((token->children != NULL) && (token->last != NULL))
1650 anjuta_token_show (token, 0, 0);
1651 fprintf(stderr, "Error: Previous token has both non NULL children and last\n");
1653 return FALSE;
1656 if (token->children != NULL)
1658 AnjutaToken *child;
1660 for (child = token->children; child != NULL; child = child->next)
1662 if (!anjuta_token_check_child (child, token)) return FALSE;
1666 if (token->last != NULL)
1668 AnjutaToken *child;
1670 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (child))
1672 if (!anjuta_token_check (child)) return FALSE;
1673 if (child == token->last) break;
1677 return TRUE;
1680 /* Constructor & Destructor
1681 *---------------------------------------------------------------------------*/
1683 AnjutaToken *anjuta_token_new_string (AnjutaTokenType type, const gchar *value)
1685 AnjutaToken *token;
1687 if (value == NULL)
1689 token = anjuta_token_new_static (type, NULL);
1691 else
1693 token = g_slice_new0 (AnjutaToken);
1694 token->data.type = type & ANJUTA_TOKEN_TYPE;
1695 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1696 token->data.pos = g_strdup (value);
1697 token->data.length = strlen (value);
1700 return token;
1703 AnjutaToken*
1704 anjuta_token_new_string_len (AnjutaTokenType type, gchar *value, gsize length)
1706 AnjutaToken *token;
1708 if (value == NULL)
1710 token = anjuta_token_new_static (type, NULL);
1712 else
1714 token = g_slice_new0 (AnjutaToken);
1715 token->data.type = type & ANJUTA_TOKEN_TYPE;
1716 token->data.flags = type & ANJUTA_TOKEN_FLAGS;
1717 token->data.pos = value;
1718 token->data.length = length;
1721 return token;
1724 AnjutaToken *
1725 anjuta_token_new_static_len (gint type, const gchar *pos, gsize length)
1727 AnjutaToken *token;
1729 token = g_slice_new0 (AnjutaToken);
1730 token->data.type = type & ANJUTA_TOKEN_TYPE;
1731 token->data.flags = (type & ANJUTA_TOKEN_FLAGS) | ANJUTA_TOKEN_STATIC;
1732 token->data.pos = (gchar *)pos;
1733 token->data.length = length;
1735 return token;
1738 AnjutaToken *anjuta_token_new_static (AnjutaTokenType type, const char *value)
1740 return anjuta_token_new_static_len (type, value, value == NULL ? 0 : strlen (value));
1743 AnjutaToken*
1744 anjuta_token_free_children (AnjutaToken *token)
1746 AnjutaToken *child;
1747 AnjutaToken *last;
1749 if (token == NULL) return NULL;
1751 for (child = token->children; child != NULL; child = token->children)
1753 anjuta_token_free (child);
1755 token->children = NULL;
1757 if (token->last != NULL)
1759 last = token->last;
1760 for (child = anjuta_token_next (token); child != NULL; child = anjuta_token_next (token))
1762 anjuta_token_free (child);
1763 if (child == last) break;
1766 token->last = NULL;
1768 return token;
1771 static void
1772 free_token (AnjutaToken *token, gpointer user_data)
1774 anjuta_token_unlink_token (token);
1775 if ((token->data.pos != NULL) && !(token->data.flags & ANJUTA_TOKEN_STATIC))
1777 g_free (token->data.pos);
1779 g_slice_free (AnjutaToken, token);
1783 AnjutaToken*
1784 anjuta_token_free (AnjutaToken *token)
1786 AnjutaToken *next;
1788 if (token == NULL) return NULL;
1790 next = anjuta_token_foreach_post_order (token, free_token, NULL);
1792 return next;