[m-dev.] For review: using alternate installation dirs, round 2

Warwick Harvey wharvey at cs.monash.edu.au
Fri Jul 23 15:34:42 AEST 1999


Enough has changed since the last time that this probably warrants a full
re-review.  I'm posting the full diff anyway, since a relative diff would
probably be larger.  I *believe* I've addressed all the issues raised in the
last review (many of them in other changes already committed), with the
exception of dependencies on library files (see my previous post titled
"Automatic library dependencies" for why I don't plan to address this right
now).

I've also (again) included an example diff of
extras/references/samples/Mmakefile to show how this stuff works, but I
don't plan to commit it with the rest of this change, as it is more
appropriate to leave such changes until "easy" installation of libraries is
also done.

Warwick


Estimated hours taken: 70

Allow the user to conveniently use Mercury libraries installed in
non-standard places, by specifying the variables `EXTRA_LIBRARIES' and
`EXTRA_LIB_DIRS' in their Mmakefile.

doc/user_guide.texi:
	Documented the new `EXTRA_LIBRARIES' and `EXTRA_LIB_DIRS' Mmake
	variables.

scripts/Mmake.vars.in:
	Added/changed definitions appropriately to support the new
	variables.
	This included adding a `GRADESTRING' variable which holds the
	canonical name of the grade being used, taking into account all the
	grade flags.

scripts/c2init.in:
	Added a new option to `c2init':
	-I/--init-file-directory <directory> adds the directory to the list
		of directories to search for `.init' files.

scripts/mmake.in:
	Made sure `MERCURY_EXTRA_INT_DIRS' and `MERCURY_EXTRA_INIT_LIB_DIRS'
	are defined as shell variables, so that adding them to `MMAKE_VPATH'
	in an Mmakefile works.

util/mkinit.c:
	Added a new option `-I' to add a directory to the list of
	directories to search for `.init' files.


Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.180
diff -u -r1.180 user_guide.texi
--- user_guide.texi	1999/07/20 03:39:19	1.180
+++ user_guide.texi	1999/07/23 02:46:56
@@ -530,6 +530,18 @@
 Extra files to be processed by c2init.  These variables should not be
 used for specifying flags to c2init (that's what @code{C2INITFLAGS} is for)
 since they are also used to derive extra dependency information.
+
+ at item EXTRA_LIBRARIES
+A list of extra Mercury libraries to link into any programs or libraries
+that you are building.
+Libraries should be specified using their base name; that is, without any
+ at samp{lib} prefix or extension.
+For example the library including the files @file{libfoo.a} and
+ at file{foo.init} would be referred to as just @samp{foo}.
+
+ at item EXTRA_LIB_DIRS
+A list of extra Mercury library directory hierarchies to search when
+looking for extra libraries.
 @end table
 
 Other variables also exist - see
@@ -582,6 +594,7 @@
 * Building libraries::
 * Installing libraries::
 * Using libraries::
+* Supporting multiple grades and architectures::
 @end menu
 
 @node Writing libraries
@@ -778,6 +791,45 @@
 for each Mercury library being used are all put in a single directory,
 which is probably the simplest way of organizing things, but the
 Mercury implementation does not require that.
+
+ at node Supporting multiple grades and architectures
+ at section Supporting multiple grades and architectures
+
+In order to better support using and installing libraries in multiple
+grades, @samp{mmake} now has some support for alternative library directory
+hierarchies.
+These have the same structure as the @file{@var{prefix}/lib/mercury} tree,
+including the different subdirectories for different grades and different
+machine architectures.
+
+Automatically installing a library and all its associated files to such a
+tree is not yet supported, but until it is the user can use the same
+techniques used for building and installing the core Mercury libraries.
+
+Once a library is installed in such a hierarchy, using it is easy.
+Suppose the user wishes to use the library @samp{mypackage} (installed
+in the tree rooted at @samp{/some/directory/mypackage}) and the library
+ at samp{myotherlib} (installed in the tree rooted at
+ at samp{/some/directory/myotherlib}).
+The user need only set the following Mmake variables:
+
+ at example
+EXTRA_LIB_DIRS = /some/directory/mypackage /some/directory/myotherlib
+EXTRA_LIBRARIES = mypackage myotherlib
+ at end example
+
+Mmake will then ensure that the appropriate directories are searched for
+the relevant interface files, module initialisation files, compiled
+libraries, etc.
+
+One can specify extra libraries to be used on a program-by-program
+basis.  For instance, if the program @samp{foo} also uses the library
+ at samp{mylib4foo}, but the other programs governed by the Mmakefile don't,
+then one can declare:
+
+ at example
+EXTRA_LIBRARIES-foo = mylib4foo
+ at end example
 
 @node Debugging
 @chapter Debugging
Index: extras/references/samples/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/references/samples/Mmakefile,v
retrieving revision 1.2
diff -u -r1.2 Mmakefile
--- Mmakefile	1999/07/20 03:39:23	1.2
+++ Mmakefile	1999/07/23 02:46:56
@@ -9,14 +9,8 @@
 # We need to use a grade with trailing
 GRADEFLAGS += --use-trail
 
-MGNUCFLAGS= -I..
-
-# Link in the reference library from ..
-MCFLAGS += -I.. $(EXTRA_MCFLAGS)
-MLFLAGS += -R`pwd`/.. -L.. $(EXTRA_MLFLAGS)
-MLLIBS = -lglobal $(EXTRA_MLLIBS)
-VPATH = ..:$(MMAKE_VPATH)
-C2INITARGS = ../global.init
+EXTRA_LIB_DIRS = /home/wharvey/mercury/libdirs/extras/lib/mercury
+EXTRA_LIBRARIES = global
 
 # We need the following to use shared libraries on Linux
 #MGNUCFLAGS += -DPIC_REG
Index: scripts/Mmake.vars.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/Mmake.vars.in,v
retrieving revision 1.26
diff -u -r1.26 Mmake.vars.in
--- Mmake.vars.in	1999/07/20 03:39:18	1.26
+++ Mmake.vars.in	1999/07/23 02:46:57
@@ -12,9 +12,31 @@
 # Ensure that commands use /bin/sh not the user's shell
 SHELL		= /bin/sh
 
+ALL_EXTRA_LIBRARIES	= $(TARGET_EXTRA_LIBRARIES) $(EXTRA_LIBRARIES)
+EXTRA_LIB_DIRS		=
+EXTRA_LIBRARIES		=
+
+EXTRA_INT_DIRS		= $(patsubst %,%/ints,$(EXTRA_LIB_DIRS))
+MERCURY_EXTRA_INT_DIRS	= $(EXTRA_INT_DIRS)
+EXTRA_C_LIB_DIRS	= \
+	$(patsubst %,%/lib/$(GRADESTRING)/@FULLARCH@,$(EXTRA_LIB_DIRS)) \
+	$(patsubst %,%/lib/@FULLARCH@,$(EXTRA_LIB_DIRS))
+EXTRA_C_INCL_DIRS	= $(patsubst %,%/inc,$(EXTRA_LIB_DIRS))
+EXTRA_INIT_DIRS		= $(patsubst %,%/modules,$(EXTRA_LIB_DIRS))
+MERCURY_EXTRA_INIT_DIRS = $(EXTRA_INIT_DIRS)
+
 # Set the directory search path. 
 # (See the GNU Make manual for documentation about VPATH and GPATH.)
-MMAKE_VPATH	= $(MERCURY_INT_DIR)
+# We need to substitute all spaces with colons for the VPATH to work.
+# Getting a space to be recognised as the first argument of the subst
+# function is problematic; hence the `$(nullstring)' hack.
+# XXX Note that directory names with spaces in them (e.g. under Windows)
+# will cause problems for the VPATH settings below, as well as every
+# occurrence of $(patsubst ...), since GNU Make does not respect quotes.
+nullstring	=
+MMAKE_VPATH	= $(subst $(nullstring) ,:,$(strip \
+			$(MERCURY_EXTRA_INT_DIRS) $(MERCURY_INT_DIR)\
+			$(MERCURY_EXTRA_INIT_DIRS)))
 VPATH		= $(MMAKE_VPATH) # do not remove the `:' from this comment!!!
 #			 the above comment works around a misfeature of
 #			 autoconf which causes it to delete assignments to
@@ -23,15 +45,17 @@
 
 DEFAULT_GRADE	= $(MERCURY_DEFAULT_GRADE)
 GRADE		= $(DEFAULT_GRADE)
+GRADESTRING	= $(shell $(MCOGS) $(ALL_GRADEFLAGS))
 
 ALL_GRADEFLAGS  = $(GRADEFLAGS) $(EXTRA_GRADEFLAGS) $(TARGET_GRADEFLAGS)
 GRADEFLAGS	= --grade $(GRADE)
 EXTRA_GRADEFLAGS =
 
 MC		= mmc
-ALL_MCFLAGS	= $(MCFLAGS) $(EXTRA_MCFLAGS) $(TARGET_MCFLAGS)
+ALL_MCFLAGS	= $(MCFLAGS) $(EXTRA_MCFLAGS) $(TARGET_MCFLAGS) $(LIB_MCFLAGS)
 MCFLAGS		=
 EXTRA_MCFLAGS	=
+LIB_MCFLAGS	= $(patsubst %,-I %,$(EXTRA_INT_DIRS))
 
 MCS		= $(MC) --split-c-files --compile-only
 MCG		= $(MC) --compile-to-c
@@ -41,15 +65,24 @@
 MCSI		= $(MC) --make-short-interface
 MCOI		= $(MC) --make-optimization-interface
 MCTOI		= $(MC) --make-transitive-optimization-interface
+MCOGS		= $(MC) --output-grade-string
 
-ALL_MCIFLAGS	= $(MCIFLAGS) $(EXTRA_MCIFLAGS) $(TARGET_MCFLAGS)
-ALL_MCPIFLAGS	= $(MCPIFLAGS) $(EXTRA_MCPIFLAGS) $(TARGET_MCFLAGS)
-ALL_MCSIFLAGS	= $(MCSIFLAGS) $(EXTRA_MCSIFLAGS) $(TARGET_MCFLAGS)
-ALL_MCOIFLAGS	= $(MCOIFLAGS) $(EXTRA_MCOIFLAGS) $(TARGET_MCFLAGS)
-ALL_MCTOIFLAGS	= $(MCTOIFLAGS) $(EXTRA_MCTOIFLAGS) $(TARGET_MCFLAGS)
-ALL_MCDFLAGS	= $(MCDFLAGS) $(EXTRA_MCDFLAGS) $(TARGET_MCFLAGS)
-ALL_MCGFLAGS	= $(MCGFLAGS) $(EXTRA_MCGFLAGS) $(TARGET_MCFLAGS)
-ALL_MCSFLAGS	= $(MCSFLAGS) $(EXTRA_MCSFLAGS) $(TARGET_MCFLAGS)
+ALL_MCIFLAGS	= $(MCIFLAGS) $(EXTRA_MCIFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCPIFLAGS	= $(MCPIFLAGS) $(EXTRA_MCPIFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCSIFLAGS	= $(MCSIFLAGS) $(EXTRA_MCSIFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCOIFLAGS	= $(MCOIFLAGS) $(EXTRA_MCOIFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCTOIFLAGS	= $(MCTOIFLAGS) $(EXTRA_MCTOIFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCDFLAGS	= $(MCDFLAGS) $(EXTRA_MCDFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCGFLAGS	= $(MCGFLAGS) $(EXTRA_MCGFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
+ALL_MCSFLAGS	= $(MCSFLAGS) $(EXTRA_MCSFLAGS) $(TARGET_MCFLAGS) \
+		  $(LIB_MCFLAGS)
 
 MCIFLAGS	= $(MCFLAGS)
 MCPIFLAGS	= $(MCFLAGS)
@@ -74,13 +107,17 @@
 # the options which should be passed to them.
 #
 C2INIT		= c2init
-ALL_C2INITFLAGS	= $(C2INITFLAGS) $(EXTRA_C2INITFLAGS) $(TARGET_C2INITFLAGS)
+ALL_C2INITFLAGS	= $(C2INITFLAGS) $(EXTRA_C2INITFLAGS) $(TARGET_C2INITFLAGS) \
+		  $(LIB_C2INITFLAGS)
 C2INITFLAGS	=
 EXTRA_C2INITFLAGS =
+LIB_C2INITFLAGS	= $(patsubst %,--init-file-directory %,$(EXTRA_INIT_DIRS))
 
-ALL_C2INITARGS	= $(C2INITARGS) $(EXTRA_C2INITARGS) $(TARGET_C2INITARGS)
+ALL_C2INITARGS	= $(C2INITARGS) $(EXTRA_C2INITARGS) $(TARGET_C2INITARGS) \
+		  $(LIB_C2INITARGS)
 C2INITARGS	=
 EXTRA_C2INITARGS =
+LIB_C2INITARGS	= $(patsubst %,%.init,$(ALL_EXTRA_LIBRARIES))
 
 MGNUC		= mgnuc
 ALL_MGNUCFLAGS	= $(MGNUCFLAGS) $(EXTRA_MGNUCFLAGS) $(TARGET_MGNUCFLAGS) \
@@ -93,15 +130,18 @@
 EXTRA_CFLAGS	=
 
 ML		= ml
-ALL_MLFLAGS	= $(MLFLAGS) $(EXTRA_MLFLAGS) $(TARGET_MLFLAGS)
+ALL_MLFLAGS	= $(MLFLAGS) $(EXTRA_MLFLAGS) $(TARGET_MLFLAGS) $(LIB_MLFLAGS)
 MLFLAGS		= $(EXTRA_MLFLAGS)
 EXTRA_MLFLAGS	=
+LIB_MLFLAGS	= $(patsubst %,-R%,$(EXTRA_C_LIB_DIRS)) \
+		  $(patsubst %,-L%,$(EXTRA_C_LIB_DIRS))
 
 MLOBJS		=
 MLPICOBJS	= $(MLOBJS:.o=.$(EXT_FOR_PIC_OBJECTS))
-ALL_MLLIBS	= $(MLLIBS) $(EXTRA_MLLIBS) $(TARGET_MLLIBS)
+ALL_MLLIBS	= $(MLLIBS) $(EXTRA_MLLIBS) $(TARGET_MLLIBS) $(LIB_MLLIBS)
 MLLIBS		=
 EXTRA_MLLIBS	=
+LIB_MLLIBS	= $(patsubst %,-l%,$(ALL_EXTRA_LIBRARIES))
 
 MNC		= mnc
 ALL_MNCFLAGS	= $(MNCFLAGS) $(EXTRA_MNCFLAGS) $(TARGET_MNCFLAGS)
@@ -250,6 +290,15 @@
   $(maybe-target-RANLIBFLAGS-$(findstring undefined,$(origin RANLIBFLAGS-$@)))
 maybe-target-RANLIBFLAGS- = $(RANLIBFLAGS-$@)
 maybe-target-RANLIBFLAGS-undefined =
+
+# Note we strip any trailing `_init.c' from `$@' so we get the appropriate
+# "base" name, regardless of whether this variable ends up being used as
+# an argument of a `c2init' rule or an `ml' rule.
+TARGET_EXTRA_LIBRARIES = \
+  $(maybe-target-EXTRA_LIBRARIES-$(findstring undefined,\
+		$(origin EXTRA_LIBRARIES-$(patsubst %_init.c,%,$@))))
+maybe-target-EXTRA_LIBRARIES- = $(EXTRA_LIBRARIES-$(patsubst %_init.c,%,$@))
+maybe-target-EXTRA_LIBRARIES-undefined =
 
 # Support for compiling Mercury programs with Prolog will probably be
 # dropped one of these days, so it's probably not worth bothering with these.
Index: scripts/c2init.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/c2init.in,v
retrieving revision 1.24
diff -u -r1.24 c2init.in
--- c2init.in	1999/06/01 09:46:17	1.24
+++ c2init.in	1999/07/23 02:46:57
@@ -41,6 +41,9 @@
 		(declared in \"init.h\") that can be called from C code.
 		(A more fine-grained interface is also available;
 		see \"init.h\" for details.)
+	-I <directory>, --init-file-directory <directory>
+		Include <directory> in the list of directories searched to
+		locate \`.init' files.
 	-w <label>, --entry-point <label>
 		Set entry point to <label>.
 		(Default value is \`mercury__main_2_0'.)
@@ -88,6 +91,7 @@
 library_opt=""
 extra_inits_opt=""
 aditi_opt=""
+extra_init_dirs=""
 
 # include the file `init_grade_options.sh-subr'
 @INIT_GRADE_OPTIONS@
@@ -113,6 +117,9 @@
 	-l-|--no-library)
 		library_opt="";;
 
+	-I|--init-file-directory)
+		extra_init_dirs="$extra_init_dirs -I $2"; shift;;
+
 	-w|--entry-point)
 		defentry="$2"; shift;;
 
@@ -176,10 +183,10 @@
 case $# in
 	0) exec $MKINIT $aditi_opt -c"$maxcalls" $init_opt $trace_opt \
 		$library_opt -w"$defentry" $extra_inits_opt \
-		$MERCURY_MOD_LIB_MODS
+		$extra_init_dirs $EXTRA_INIT_FILES $MERCURY_MOD_LIB_MODS
 	   ;;
 	*) exec $MKINIT $aditi_opt -c"$maxcalls" $init_opt $trace_opt \
-		$library_opt -w"$defentry" $extra_inits_opt "$@" \
-		$MERCURY_MOD_LIB_MODS
+		$library_opt -w"$defentry" $extra_inits_opt \
+		$extra_init_dirs "$@" $EXTRA_INIT_FILES $MERCURY_MOD_LIB_MODS
 	   ;;
 esac
Index: scripts/mmake.in
===================================================================
RCS file: /home/mercury1/repository/mercury/scripts/mmake.in,v
retrieving revision 1.28
diff -u -r1.28 mmake.in
--- mmake.in	1999/07/20 03:39:18	1.28
+++ mmake.in	1999/07/23 02:46:57
@@ -66,6 +66,8 @@
 MMAKE_VARS=${MMAKE_VARS=$MMAKE_DIR/Mmake.vars}
 MMAKE_RULES=${MMAKE_RULES=$MMAKE_DIR/Mmake.rules}
 MERCURY_INT_DIR=${MERCURY_INT_DIR=@LIBDIR@/ints}
+MERCURY_EXTRA_INT_DIRS=${MERCURY_EXTRA_INT_DIRS=}
+MERCURY_EXTRA_INIT_LIB_DIRS=${MERCURY_EXTRA_INIT_LIB_DIRS=}
 MERCURY_DEFAULT_GRADE=${MERCURY_DEFAULT_GRADE=@DEFAULT_GRADE@}
 MKTEMP=@MKTEMP@
 
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.52
diff -u -r1.52 mkinit.c
--- mkinit.c	1999/06/29 19:08:32	1.52
+++ mkinit.c	1999/07/23 02:46:57
@@ -23,6 +23,8 @@
 #include	<string.h>
 #include	<ctype.h>
 #include	<errno.h>
+#include	<unistd.h>
+#include	<sys/stat.h>
 #include	"getopt.h"
 #include	"mercury_conf.h"
 #include	"mercury_std.h"
@@ -32,7 +34,7 @@
 #define	MAXLINE		256	/* maximum number of characters per line */
 				/* (characters after this limit are ignored) */
 
-/* --- used to collect Aditi data constant names --- */
+/* --- used to collect a list of strings, e.g. Aditi data constant names --- */
 
 typedef struct String_List_struct {
 		char *data;
@@ -57,6 +59,12 @@
 static int num_modules = 0;
 static int num_errors = 0;
 
+	/* List of directories to search for init files */
+static String_List *init_file_dirs = NULL;
+
+	/* Pointer to tail of the init_file_dirs list */
+static String_List **init_file_dirs_tail = &init_file_dirs;
+
 	/* List of names of Aditi-RL code constants. */
 static String_List *rl_data = NULL;
 
@@ -229,6 +237,8 @@
 /* --- function prototypes --- */
 static	void parse_options(int argc, char *argv[]);
 static	void usage(void);
+static	void do_path_search(void);
+static	char *find_init_file(const char *basename);
 static	void output_headers(void);
 static	void output_sub_init_functions(void);
 static	void output_main_init_function(void);
@@ -279,6 +289,8 @@
 
 	parse_options(argc, argv);
 
+	do_path_search();
+
 	output_headers();
 	output_sub_init_functions();
 	output_main_init_function();
@@ -304,8 +316,9 @@
 static void 
 parse_options(int argc, char *argv[])
 {
-	int	c;
-	while ((c = getopt(argc, argv, "ac:iltw:x")) != EOF) {
+	int c;
+	String_List *tmp_slist;
+	while ((c = getopt(argc, argv, "ac:iI:ltw:x")) != EOF) {
 		switch (c) {
 		case 'a':
 			aditi = TRUE;
@@ -320,6 +333,17 @@
 			need_initialization_code = TRUE;
 			break;
 
+		case 'I':
+			tmp_slist = (String_List *)
+					checked_malloc(sizeof(String_List));
+			tmp_slist->next = NULL;
+			tmp_slist->data = (char *)
+					checked_malloc(strlen(optarg) + 1);
+			strcpy(tmp_slist->data, optarg);
+			*init_file_dirs_tail = tmp_slist;
+			init_file_dirs_tail = &tmp_slist->next;
+			break;
+
 		case 'l':
 			output_main_func = FALSE;
 			break;
@@ -353,6 +377,74 @@
 	fprintf(stderr,
 "Usage: mkinit [-a] [-c maxcalls] [-w entry] [-i] [-l] [-t] [-x] files...\n");
 	exit(1);
+}
+
+/*---------------------------------------------------------------------------*/
+
+	/*
+	** Scan the list of files for ones not found in the current
+	** directory, and replace them with their full path equivalent
+	** if they are found in the list of search directories.
+	*/
+static void
+do_path_search(void)
+{
+	int filenum;
+	char *init_file;
+
+	for (filenum = 0; filenum < num_files; filenum++) {
+		init_file = find_init_file(files[filenum]);
+		if (init_file != NULL)
+			files[filenum] = init_file;
+	}
+}
+
+	/*
+	** Search the init file directory list to locate the file.
+	** If the file is in the current directory or is not in any of the
+	** search directories, then return NULL.  Otherwise return the full
+	** path name to the file.
+	** It is the caller's responsibility to free the returned buffer
+	** holding the full path name when it is no longer needed.
+	*/
+static char *
+find_init_file(const char *basename)
+{
+	struct stat buf;
+	char *filename;
+	char *dirname;
+	String_List *dir_ptr;
+	int dirlen;
+	int baselen;
+	int len;
+
+	if (stat(basename, &buf) == 0) {
+		/* File is in current directory, so no search required */
+		return NULL;
+	}
+
+	baselen = strlen(basename);
+
+	for (dir_ptr = init_file_dirs; dir_ptr != NULL;
+			dir_ptr = dir_ptr->next)
+	{
+		dirname = dir_ptr->data;
+		dirlen = strlen(dirname);
+		len = dirlen + 1 + baselen;
+
+		filename = (char *) checked_malloc(len + 1);
+		strcpy(filename, dirname);
+		filename[dirlen] = '/';
+		strcpy(filename + dirlen + 1, basename);
+
+		if (stat(filename, &buf) == 0)
+			return filename;
+
+		free(filename);
+	}
+
+	/* Did not find file */
+	return NULL;
 }
 
 /*---------------------------------------------------------------------------*/

--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list