Files
mercury/runtime/mercury_dlist.c
Zoltan Somogyi eeaa5eca56 Make a step towards supporting the automatic running of compiler-provided
Estimated hours taken: 4
Branches: main

Make a step towards supporting the automatic running of compiler-provided
initialization functions at startup. The idea is that in each module that
defines a solver type which wants to keep the solver state in a global
variable, the compiler will generate a function to initialize this global
variable and put a line containing

	REQUIRED_INIT function_name

in the generated .c file. Mkinit will then see this and put a call to the named
function in the program's init_modules_required function, which (once this diff
is installed) will be called from the tail end of mercury_init.

util/mkinit.c:
	Until now, mkinit didn't open .c files unless given the -x option,
	because doing so was expensive: the list of .c (and .init) files was
	scanned five times, and opening and reading each file five times is
	excessive. This diff changes that. Each file is now opened and read
	(until a line containing only ENDINIT) just once, and the info found
	therein put into some new mkinit data structures. The five scans
	through the file list now scan through these data structures instead.
	This is now fast enough to leave -x on all the time: mkinit -x now
	takes 3-4 seconds in the compiler directory, and at most 0.15s
	in the other directories.

	Add a sixth scan through the data structures to generate calls to
	the functions named in REQUIRED_INIT lines; make bunches of these calls
	the body of the program's init_modules_required function.

runtime/mercury_array_macro.h:
	Fix indentation.

runtime/mercury_dlist.[ch]:
	Move the documentation of the exported functions from the .c file
	to the .h file.

runtime/mercury_std.h:
	Add a missing () around a macro argument.
2005-08-11 01:12:53 +00:00

249 lines
4.7 KiB
C

/*
** Copyright (C) 1995, 1997, 1999-2000, 2004-2005 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/*
** Linked list module.
*/
#include "mercury_imp.h"
#include <stdio.h>
#include "mercury_memory.h"
#include "mercury_dlist.h"
MR_Dlist *
MR_dlist_makelist0(void)
{
MR_Dlist *list;
list = MR_GC_NEW(MR_Dlist);
MR_dlist_data(list) = NULL;
MR_dlist_next(list) = list;
MR_dlist_prev(list) = list;
return list;
}
MR_Dlist *
MR_dlist_makelist(const void *data)
{
MR_Dlist *list;
MR_assert(data != NULL);
list = MR_dlist_makelist0();
MR_dlist_addhead(list, data);
return list;
}
MR_Dlist *
MR_dlist_addhead(MR_Dlist *list, const void *data)
{
MR_Dlist *item;
if (list == NULL) {
list = MR_dlist_makelist0();
}
item = MR_GC_NEW(MR_Dlist);
MR_dlist_data(item) = data;
MR_dlist_length_field(list)++;
/* item's pointers */
MR_dlist_next(item) = MR_dlist_next(list);
MR_dlist_prev(item) = list;
/* neighbours' pointers */
MR_dlist_next(MR_dlist_prev(item)) = item;
MR_dlist_prev(MR_dlist_next(item)) = item;
return list;
}
MR_Dlist *
MR_dlist_addtail(MR_Dlist *list, const void *data)
{
MR_Dlist *item;
if (list == NULL) {
list = MR_dlist_makelist0();
}
item = MR_GC_NEW(MR_Dlist);
MR_dlist_data(item) = data;
MR_dlist_length_field(list)++;
/* item's pointers */
MR_dlist_next(item) = list;
MR_dlist_prev(item) = MR_dlist_prev(list);
/* neighbours' pointers */
MR_dlist_next(MR_dlist_prev(item)) = item;
MR_dlist_prev(MR_dlist_next(item)) = item;
return list;
}
MR_Dlist *
MR_dlist_addlist(MR_Dlist *list1, MR_Dlist *list2)
{
if (list1 == NULL) {
list1 = MR_dlist_makelist0();
}
if (list2 == NULL) {
list2 = MR_dlist_makelist0();
}
if (MR_dlist_length(list2) > 0) {
if (MR_dlist_length(list1) == 0) {
MR_dlist_data(list1) = MR_dlist_data(list2);
/* pointers from header */
MR_dlist_next(list1) = MR_dlist_next(list2);
MR_dlist_prev(list1) = MR_dlist_prev(list2);
/* pointers to header */
MR_dlist_prev(MR_dlist_next(list1)) = list1;
MR_dlist_next(MR_dlist_prev(list1)) = list1;
} else {
MR_dlist_length_field(list1) = MR_dlist_length(list1)
+ MR_dlist_length(list2);
/* end of list 1 to start of list 2 */
MR_dlist_next(MR_dlist_prev(list1)) =
MR_dlist_next(list2);
MR_dlist_prev(MR_dlist_next(list2)) =
MR_dlist_prev(list1);
/* end of list 2 to start of list 1 */
MR_dlist_next(MR_dlist_prev(list2)) = list1;
MR_dlist_prev(list1) = MR_dlist_prev(list2);
}
}
MR_GC_free(list2);
return list1;
}
MR_Dlist *
MR_dlist_addndlist(MR_Dlist *list1, MR_Dlist *list2)
{
MR_Dlist *ptr;
if (list1 == NULL) {
list1 = MR_dlist_makelist0();
}
if (list2 == NULL) {
list2 = MR_dlist_makelist0();
}
MR_for_dlist (ptr, list2) {
MR_dlist_addtail(list1, MR_dlist_data(ptr));
}
return list1;
}
void
MR_dlist_insert_before(MR_Dlist *list, MR_Dlist *where, const void *data)
{
MR_Dlist *item;
item = MR_GC_NEW(MR_Dlist);
MR_dlist_data(item) = data;
MR_dlist_length_field(list)++;
/* item's pointers */
MR_dlist_next(item) = where;
MR_dlist_prev(item) = MR_dlist_prev(where);
/* neighbour's pointers */
MR_dlist_next(MR_dlist_prev(item)) = item;
MR_dlist_prev(MR_dlist_next(item)) = item;
}
void
MR_dlist_insert_after(MR_Dlist *list, MR_Dlist *where, const void *data)
{
MR_Dlist *item;
item = MR_GC_NEW(MR_Dlist);
MR_dlist_data(item) = data;
MR_dlist_length_field(list)++;
/* item's pointers */
MR_dlist_next(item) = MR_dlist_next(where);
MR_dlist_prev(item) = where;
/* neighbour's pointers */
MR_dlist_next(MR_dlist_prev(item)) = item;
MR_dlist_prev(MR_dlist_next(item)) = item;
return;
}
/*
** Return the length of a given list.
*/
int
MR_dlist_maybe_null_length(const MR_Dlist *list)
{
if (list == NULL) {
return 0;
}
return MR_dlist_length(list);
}
/*
** Delete an item from its linked list, and free the node,
** and maybe the data.
*/
void
MR_dlist_delete(MR_Dlist *list, MR_Dlist *item, void (* func)(const void *))
{
if (list == NULL) {
return;
}
if (item == NULL) {
return;
}
if (func != NULL) {
func(MR_dlist_data(item));
}
MR_dlist_length_field(list)--;
MR_dlist_next(MR_dlist_prev(item)) = MR_dlist_next(item);
MR_dlist_prev(MR_dlist_next(item)) = MR_dlist_prev(item);
MR_GC_free(item);
return;
}
void
MR_dlist_oldlist(MR_Dlist *list, void (* func)(const void *))
{
MR_Dlist *ptr;
MR_Dlist *item;
if (list == NULL) {
return;
}
ptr = MR_dlist_next(list);
while (ptr != list) {
item = ptr;
ptr = MR_dlist_next(ptr);
if (func != NULL) {
func(MR_dlist_data(item));
}
MR_GC_free(item);
}
MR_GC_free(list);
return;
}