mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-18 15:26:31 +00:00
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.
249 lines
4.7 KiB
C
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;
|
|
}
|