diff options
Diffstat (limited to 'mixlib')
| -rw-r--r-- | mixlib/Makefile.am | 10 | ||||
| -rw-r--r-- | mixlib/completion.c | 503 | ||||
| -rw-r--r-- | mixlib/completion.h | 73 | ||||
| -rw-r--r-- | mixlib/mix_vm_command.c | 25 | ||||
| -rw-r--r-- | mixlib/mix_vm_command.h | 3 | ||||
| -rw-r--r-- | mixlib/xmix_vm_command.h | 6 | 
6 files changed, 597 insertions, 23 deletions
diff --git a/mixlib/Makefile.am b/mixlib/Makefile.am index 8b7160e..b38af6d 100644 --- a/mixlib/Makefile.am +++ b/mixlib/Makefile.am @@ -1,6 +1,6 @@  ## Process this file with automake to produce Makefile.in -# Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. +# Copyright (C) 2000, 2001, 2006, 2014 Free Software Foundation, Inc.  #  # This file is free software; as a special exception the author gives  # unlimited permission to copy and/or distribute it, with or without @@ -15,7 +15,9 @@ SUBDIRS = testsuite  INCLUDES = -I$(includedir) -I$(top_srcdir) -DG_LOG_DOMAIN=\"libmix\"  noinst_LIBRARIES = libmix.a -libmix_a_SOURCES = gettext.h mix.h mix.c \ +libmix_a_SOURCES = gettext.h \ +                   completion.h completion.c \ +                   mix.h mix.c \  		   mix_types.h mix_types.c \  		   mix_ins.h mix_ins.c     \  	           mix_vm.h mix_vm.c xmix_vm.h xmix_vm.c \ @@ -35,7 +37,3 @@ libmix_a_SOURCES = gettext.h mix.h mix.c \  		   mix_config.c mix_config.h \                     mix_predicate.c mix_predicate.h \                     mix_predicate_list.c mix_predicate_list.h - - - - diff --git a/mixlib/completion.c b/mixlib/completion.c new file mode 100644 index 0000000..630708b --- /dev/null +++ b/mixlib/completion.c @@ -0,0 +1,503 @@ +/* Adapted from GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000.  See the AUTHORS + * file for a list of people on the GLib Team.  See the ChangeLog + * files for a list of changes.  These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Jose Antonio Ortega Ruiz 2014, for inclusion in MDK due + * to deprecation in new versions of Glib.  Only changes are renaming + * GCompletion to Completion and g_completion to completion. + */ + +/* + * MT safe + */ + +#include "config.h" + +#include "completion.h" + +#include <glib.h> +#include <string.h> + +/** + * SECTION:completion + * @title: Automatic String Completion + * @short_description: support for automatic completion using a group + *                     of target strings + * + * #Completion provides support for automatic completion of a string + * using any group of target strings. It is typically used for file + * name completion as is common in many UNIX shells. + * + * A #Completion is created using completion_new(). Target items are + * added and removed with completion_add_items(), + * completion_remove_items() and completion_clear_items(). A + * completion attempt is requested with completion_complete() or + * completion_complete_utf8(). When no longer needed, the + * #Completion is freed with completion_free(). + * + * Items in the completion can be simple strings (e.g. filenames), or + * pointers to arbitrary data structures. If data structures are used + * you must provide a #CompletionFunc in completion_new(), which + * retrieves the item's string from the data structure. You can change + * the way in which strings are compared by setting a different + * #CompletionStrncmpFunc in completion_set_compare(). + * + * Completion has been marked as deprecated, since this API is rarely + * used and not very actively maintained. + **/ + +/** + * Completion: + * @items: list of target items (strings or data structures). + * @func: function which is called to get the string associated with a + *        target item. It is %NULL if the target items are strings. + * @prefix: the last prefix passed to completion_complete() or + *          completion_complete_utf8(). + * @cache: the list of items which begin with @prefix. + * @strncmp_func: The function to use when comparing strings.  Use + *                completion_set_compare() to modify this function. + * + * The data structure used for automatic completion. + **/ + +/** + * CompletionFunc: + * @Param1: the completion item. + * + * Specifies the type of the function passed to completion_new(). It + * should return the string corresponding to the given target item. + * This is used when you use data structures as #Completion items. + * + * Returns: the string corresponding to the item. + **/ + +/** + * CompletionStrncmpFunc: + * @s1: string to compare with @s2. + * @s2: string to compare with @s1. + * @n: maximal number of bytes to compare. + * + * Specifies the type of the function passed to + * completion_set_compare(). This is used when you use strings as + * #Completion items. + * + * Returns: an integer less than, equal to, or greater than zero if + *          the first @n bytes of @s1 is found, respectively, to be + *          less than, to match, or to be greater than the first @n + *          bytes of @s2. + **/ + +static void completion_check_cache (Completion* cmp, +				    gchar**	 new_prefix); + +/** + * completion_new: + * @func: the function to be called to return the string representing + *        an item in the #Completion, or %NULL if strings are going to + *        be used as the #Completion items. + * + * Creates a new #Completion. + * + * Returns: the new #Completion. + **/ +Completion* +completion_new (CompletionFunc func) +{ +  Completion* gcomp; + +  gcomp = g_new (Completion, 1); +  gcomp->items = NULL; +  gcomp->cache = NULL; +  gcomp->prefix = NULL; +  gcomp->func = func; +  gcomp->strncmp_func = strncmp; + +  return gcomp; +} + +/** + * completion_add_items: + * @cmp: the #Completion. + * @items: (transfer none): the list of items to add. + * + * Adds items to the #Completion. + * + * Deprecated: 2.26: Rarely used API + **/ +void +completion_add_items (Completion* cmp, +                      GList*	     items) +{ +  GList* it; + +  g_return_if_fail (cmp != NULL); + +  /* optimize adding to cache? */ +  if (cmp->cache) +    { +      g_list_free (cmp->cache); +      cmp->cache = NULL; +    } + +  if (cmp->prefix) +    { +      g_free (cmp->prefix); +      cmp->prefix = NULL; +    } + +  it = items; +  while (it) +    { +      cmp->items = g_list_prepend (cmp->items, it->data); +      it = it->next; +    } +} + +/** + * completion_remove_items: + * @cmp: the #Completion. + * @items: (transfer none): the items to remove. + * + * Removes items from a #Completion. The items are not freed, so if the memory + * was dynamically allocated, free @items with g_list_free_full() after calling + * this function. + * + * Deprecated: 2.26: Rarely used API + **/ +void +completion_remove_items (Completion* cmp, +                         GList*	items) +{ +  GList* it; + +  g_return_if_fail (cmp != NULL); + +  it = items; +  while (cmp->items && it) +    { +      cmp->items = g_list_remove (cmp->items, it->data); +      it = it->next; +    } + +  it = items; +  while (cmp->cache && it) +    { +      cmp->cache = g_list_remove(cmp->cache, it->data); +      it = it->next; +    } +} + +/** + * completion_clear_items: + * @cmp: the #Completion. + * + * Removes all items from the #Completion. The items are not freed, so if the + * memory was dynamically allocated, it should be freed after calling this + * function. + * + * Deprecated: 2.26: Rarely used API + **/ +void +completion_clear_items (Completion* cmp) +{ +  g_return_if_fail (cmp != NULL); + +  g_list_free (cmp->items); +  cmp->items = NULL; +  g_list_free (cmp->cache); +  cmp->cache = NULL; +  g_free (cmp->prefix); +  cmp->prefix = NULL; +} + +static void +completion_check_cache (Completion* cmp, +			gchar**	     new_prefix) +{ +  register GList* list; +  register gsize len; +  register gsize i; +  register gsize plen; +  gchar* postfix; +  gchar* s; + +  if (!new_prefix) +    return; +  if (!cmp->cache) +    { +      *new_prefix = NULL; +      return; +    } + +  len = strlen(cmp->prefix); +  list = cmp->cache; +  s = cmp->func ? cmp->func (list->data) : (gchar*) list->data; +  postfix = s + len; +  plen = strlen (postfix); +  list = list->next; + +  while (list && plen) +    { +      s = cmp->func ? cmp->func (list->data) : (gchar*) list->data; +      s += len; +      for (i = 0; i < plen; ++i) +	{ +	  if (postfix[i] != s[i]) +	    break; +	} +      plen = i; +      list = list->next; +    } + +  *new_prefix = g_new0 (gchar, len + plen + 1); +  strncpy (*new_prefix, cmp->prefix, len); +  strncpy (*new_prefix + len, postfix, plen); +} + +/** + * completion_complete_utf8: + * @cmp: the #Completion + * @prefix: the prefix string, typically used by the user, which is compared + *    with each of the items + * @new_prefix: if non-%NULL, returns the longest prefix which is common to all + *    items that matched @prefix, or %NULL if no items matched @prefix. + *    This string should be freed when no longer needed. + * + * Attempts to complete the string @prefix using the #Completion target items. + * In contrast to completion_complete(), this function returns the largest common + * prefix that is a valid UTF-8 string, omitting a possible common partial + * character. + * + * You should use this function instead of completion_complete() if your + * items are UTF-8 strings. + * + * Return value: (element-type utf8) (transfer none): the list of items whose strings begin with @prefix. This should + * not be changed. + * + * Since: 2.4 + * + * Deprecated: 2.26: Rarely used API + **/ +GList* +completion_complete_utf8 (Completion  *cmp, +                          const gchar  *prefix, +                          gchar       **new_prefix) +{ +  GList *list; +  gchar *p, *q; + +  list = completion_complete (cmp, prefix, new_prefix); + +  if (new_prefix && *new_prefix) +    { +      p = *new_prefix + strlen (*new_prefix); +      q = g_utf8_find_prev_char (*new_prefix, p); + +      switch (g_utf8_get_char_validated (q, p - q)) +	{ +	case (gunichar)-2: +	case (gunichar)-1: +	  *q = 0; +	  break; +	default: ; +	} + +    } + +  return list; +} + +/** + * completion_complete: + * @cmp: the #Completion. + * @prefix: the prefix string, typically typed by the user, which is + *          compared with each of the items. + * @new_prefix: if non-%NULL, returns the longest prefix which is + *              common to all items that matched @prefix, or %NULL if + *              no items matched @prefix.  This string should be freed + *              when no longer needed. + * + * Attempts to complete the string @prefix using the #Completion + * target items. + * + * Returns: (transfer none): the list of items whose strings begin with + *          @prefix. This should not be changed. + * + * Deprecated: 2.26: Rarely used API + **/ +GList* +completion_complete (Completion* cmp, +                     const gchar* prefix, +                     gchar**	    new_prefix) +{ +  gsize plen, len; +  gboolean done = FALSE; +  GList* list; + +  g_return_val_if_fail (cmp != NULL, NULL); +  g_return_val_if_fail (prefix != NULL, NULL); + +  len = strlen (prefix); +  if (cmp->prefix && cmp->cache) +    { +      plen = strlen (cmp->prefix); +      if (plen <= len && ! cmp->strncmp_func (prefix, cmp->prefix, plen)) +	{ +	  /* use the cache */ +	  list = cmp->cache; +	  while (list) +	    { +	      GList *next = list->next; + +	      if (cmp->strncmp_func (prefix, +				     cmp->func ? cmp->func (list->data) : (gchar*) list->data, +				     len)) +		cmp->cache = g_list_delete_link (cmp->cache, list); + +	      list = next; +	    } +	  done = TRUE; +	} +    } + +  if (!done) +    { +      /* normal code */ +      g_list_free (cmp->cache); +      cmp->cache = NULL; +      list = cmp->items; +      while (*prefix && list) +	{ +	  if (!cmp->strncmp_func (prefix, +                                  cmp->func ? cmp->func (list->data) : (gchar*) list->data, +                                  len)) +	    cmp->cache = g_list_prepend (cmp->cache, list->data); +	  list = list->next; +	} +    } +  if (cmp->prefix) +    { +      g_free (cmp->prefix); +      cmp->prefix = NULL; +    } +  if (cmp->cache) +    cmp->prefix = g_strdup (prefix); +  completion_check_cache (cmp, new_prefix); + +  return *prefix ? cmp->cache : cmp->items; +} + +/** + * completion_free: + * @cmp: the #Completion. + * + * Frees all memory used by the #Completion. The items are not freed, so if + * the memory was dynamically allocated, it should be freed after calling this + * function. + * + * Deprecated: 2.26: Rarely used API + **/ +void +completion_free (Completion* cmp) +{ +  g_return_if_fail (cmp != NULL); + +  completion_clear_items (cmp); +  g_free (cmp); +} + +/** + * completion_set_compare: + * @cmp: a #Completion. + * @strncmp_func: the string comparison function. + * + * Sets the function to use for string comparisons. The default string + * comparison function is strncmp(). + * + * Deprecated: 2.26: Rarely used API + **/ +void +completion_set_compare(Completion *cmp, +                       CompletionStrncmpFunc strncmp_func) +{ +  cmp->strncmp_func = strncmp_func; +} + +#ifdef TEST_COMPLETION +#include <stdio.h> +int +main (int   argc, +      char* argv[]) +{ +  FILE *file; +  gchar buf[1024]; +  GList *list; +  GList *result; +  GList *tmp; +  Completion *cmp; +  gint i; +  gchar *longp = NULL; + +  if (argc < 3) +    { +      g_warning ("Usage: %s filename prefix1 [prefix2 ...]\n", argv[0]); +      return 1; +    } + +  file = fopen (argv[1], "r"); +  if (!file) +    { +      g_warning ("Cannot open %s\n", argv[1]); +      return 1; +    } + +  cmp = completion_new (NULL); +  list = g_list_alloc (); +  while (fgets (buf, 1024, file)) +    { +      list->data = g_strdup (buf); +      completion_add_items (cmp, list); +    } +  fclose (file); + +  for (i = 2; i < argc; ++i) +    { +      printf ("COMPLETING: %s\n", argv[i]); +      result = completion_complete (cmp, argv[i], &longp); +      g_list_foreach (result, (GFunc) printf, NULL); +      printf ("LONG MATCH: %s\n", longp); +      g_free (longp); +      longp = NULL; +    } + +  g_list_foreach (cmp->items, (GFunc) g_free, NULL); +  completion_free (cmp); +  g_list_free (list); + +  return 0; +} + +#endif diff --git a/mixlib/completion.h b/mixlib/completion.h new file mode 100644 index 0000000..271543b --- /dev/null +++ b/mixlib/completion.h @@ -0,0 +1,73 @@ +/* Adapted from GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GLib Team and others 1997-2000.  See the AUTHORS + * file for a list of people on the GLib Team.  See the ChangeLog + * files for a list of changes.  These files are distributed with + * GLib at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* + * Modified by Jose Antonio Ortega Ruiz 2014, for inclusion in MDK due + * to deprecation in new versions of Glib.  Only changes are renaming + * GCompletion to Completion and g_completion to completion. + */ + +#ifndef __COMPLETION_H__ +#define __COMPLETION_H__ + +#include <glib.h> + +typedef struct _Completion     Completion; + +typedef gchar*          (*CompletionFunc)      (gpointer); + +/* Completion + */ + +typedef gint (*CompletionStrncmpFunc) (const gchar *s1, +                                       const gchar *s2, +                                       gsize        n); + +struct _Completion +{ +  GList* items; +  CompletionFunc func; + +  gchar* prefix; +  GList* cache; +  CompletionStrncmpFunc strncmp_func; +}; + +Completion* completion_new (CompletionFunc func); +void completion_add_items (Completion* cmp, GList* items); +void completion_remove_items (Completion* cmp, GList* items); +void completion_clear_items (Completion* cmp); +GList* completion_complete (Completion* cmp, +                            const gchar* prefix, +                            gchar** new_prefix); +GList* completion_complete_utf8 (Completion *cmp, +                                 const gchar* prefix, +                                 gchar** new_prefix); +void completion_set_compare (Completion *cmp, +                             CompletionStrncmpFunc strncmp_func); +void completion_free (Completion* cmp); + +#endif /* __COMPLETION_H__ */ diff --git a/mixlib/mix_vm_command.c b/mixlib/mix_vm_command.c index e144d30..e91d67a 100644 --- a/mixlib/mix_vm_command.c +++ b/mixlib/mix_vm_command.c @@ -1,7 +1,7 @@  /* -*-c-*- -------------- mix_vm_command.c :   * Implementation of the functions declared in mix_vm_command.h   * ------------------------------------------------------------------ - * Copyright (C) 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2004, 2006, 2007, 2014 Free Software Foundation, Inc.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -15,13 +15,15 @@   *   * You should have received a copy of the GNU General Public License   * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA.   *   */  #include "xmix_vm_command.h"  #include "xmix_vm_handlers.h" +#include "completion.h"  #ifdef HAVE_LIBHISTORY  #  include <readline/history.h> @@ -91,16 +93,16 @@ mix_vm_command_usage (mix_vm_command_t cmd)  }  /* create a new command dispatcher */ -static GCompletion * +static Completion *  make_completions_ (void)  {    GList *cmds = NULL;    gint k; -  GCompletion *completions = g_completion_new (NULL); +  Completion *completions = completion_new (NULL);    for (k = 0; k < MIX_CMD_INVALID; ++k)      cmds = g_list_append (cmds, (gpointer) mix_vm_command_to_string (k)); -  g_completion_add_items (completions, cmds); +  completion_add_items (completions, cmds);    return completions;  } @@ -239,7 +241,7 @@ mix_vm_cmd_dispatcher_delete (mix_vm_cmd_dispatcher_t *dis)    g_hash_table_foreach_remove (dis->mem_preds, del_pred_, NULL);    g_hash_table_destroy (dis->mem_preds);    g_hash_table_destroy (dis->commands); -  g_completion_free (dis->completions); +  completion_free (dis->completions);    for (k = 0; k < MIX_CMD_INVALID; ++k)      {        del_hook_list_ (dis->pre_hooks[k]); @@ -260,7 +262,7 @@ mix_vm_cmd_dispatcher_register_new (mix_vm_cmd_dispatcher_t *dis,    g_return_if_fail (cmd != NULL);    g_hash_table_insert (dis->commands, (gpointer)cmd->name, (gpointer)cmd);    list = g_list_append (list, (gpointer)cmd->name); -  g_completion_add_items (dis->completions, list); +  completion_add_items (dis->completions, list);  }  const GList * @@ -274,7 +276,7 @@ mix_vm_cmd_dispatcher_complete (const mix_vm_cmd_dispatcher_t *dis,    g_return_val_if_fail (cmd != NULL, NULL);    cp = g_strdup (cmd); -  result = g_completion_complete (dis->completions, cp, prefix); +  result = completion_complete (dis->completions, cp, prefix);    g_free (cp);    return result;  } @@ -633,11 +635,10 @@ mix_vm_cmd_dispatcher_get_src_file_line (const mix_vm_cmd_dispatcher_t *dis,      {        enum {BUFF_SIZE = 256};        static gchar BUFFER[BUFF_SIZE]; -      int len = -	g_snprintf (BUFFER, BUFF_SIZE, "%s", mix_src_file_get_line (file, line)); +      int len = g_snprintf (BUFFER, BUFF_SIZE, +                            "%s", +                            mix_src_file_get_line (file, line));        if (len > 0 && BUFFER[len - 1] == '\n') BUFFER[len - 1] = '\0';        return BUFFER;      }  } - - diff --git a/mixlib/mix_vm_command.h b/mixlib/mix_vm_command.h index 65b78e9..bd5fb19 100644 --- a/mixlib/mix_vm_command.h +++ b/mixlib/mix_vm_command.h @@ -1,7 +1,7 @@  /* -*-c-*- ---------------- mix_vm_command.h :   * declarations for mix_vm_command_t, describing commands issued to a vm   * ------------------------------------------------------------------ - * Copyright (C) 2001, 2006, 2007 Free Software Foundation, Inc. + * Copyright (C) 2001, 2006, 2007, 2014 Free Software Foundation, Inc.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -251,4 +251,3 @@ mix_vm_cmd_dispatcher_get_vm (const mix_vm_cmd_dispatcher_t *dis);  #endif /* MIX_VM_COMMAND_H */ - diff --git a/mixlib/xmix_vm_command.h b/mixlib/xmix_vm_command.h index 8a6afae..95369aa 100644 --- a/mixlib/xmix_vm_command.h +++ b/mixlib/xmix_vm_command.h @@ -1,7 +1,7 @@  /* -*-c-*- ---------------- xmix_vm_command.h :   * Private type declarations form mix_vm_command   * ------------------------------------------------------------------ - * Copyright (C) 2001, 2004, 2007 Free Software Foundation, Inc. + * Copyright (C) 2001, 2004, 2007, 2014 Free Software Foundation, Inc.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@  #include "mix_eval.h"  #include "mix_predicate.h"  #include "mix_vm_command.h" +#include "completion.h"  /* configuration keys */ @@ -77,7 +78,7 @@ struct mix_vm_cmd_dispatcher_t    mix_time_t laptime;		/* last run time */    mix_time_t progtime;		/* current program running time */    GHashTable *commands;		/* local commands */ -  GCompletion *completions;	/* command completion list */ +  Completion *completions;	/* command completion list */    GSList *pre_hooks[HOOKNO_];	/* Pre-command hooks */    GSList *post_hooks[HOOKNO_];	/* Post-command hooks */    GSList *global_pre;		/* global pre-command hook */ @@ -97,4 +98,3 @@ log_error_ (mix_vm_cmd_dispatcher_t *dis, const gchar *fmt, ...);  #define wants_logs_(dis) (dis)->log_msg  #endif /* XMIX_VM_COMMAND_H */ -  | 
