Previous Up

10.7  Defining a new C main() function

GNU Prolog allows the user to define his own main() function. This can be useful to perform several tasks before starting the Prolog engine. To do this simply define a classical main(argc, argv) function. The following functions can then be used:

int Pl_Start_Prolog (int argc, char *argv[])
void Pl_Stop_Prolog (void)
void Pl_Reset_Prolog (void)
PlBool Pl_Try_Execute_Top_Level(void)

The function Pl_Start_Prolog(argc, argv) initializes the Prolog engine (argc and argv are the command-line variables). This function collects all linked objects (issued from the compilation of Prolog files) and initializes them. The initialization of a Prolog object file consists in adding to appropriate tables new atoms, new predicates and executing its system directives. A system directive is generated by the Prolog to WAM compiler to reflect a (user) directive executed at compile-time such as op/3 (section 7.1.11). Indeed, when the compiler encounters such a directive it immediately executes it and also generates a system directive to execute it at the start of the executable. When all system directives have been executed the Prolog engine executes all initialization directives defined with initialization/1 (section 7.1.14). The function returns the number of user directives (i.e. initialization/1) executed. This function must be called only once.

The function Pl_Stop_Prolog() stops the Prolog engine. This function must be called only once after all Prolog treatment have been done.

The function Pl_Reset_Prolog() reinitializes the Prolog engine (i.e. reset all Prolog stacks).

The function Pl_Try_Execute_Top_Level() executes the top-level if linked (section 4.4.3) and returns PL_TRUE. If the top-level is not present the functions returns PL_FALSE.

Here is the definition of the default GNU Prolog main() function:

static int
Main_Wrapper(int argc, char *argv[])
{
 int nb_user_directive;
 PlBool top_level;
 nb_user_directive = Pl_Start_Prolog(argc, argv);
 top_level = Pl_Try_Execute_Top_Level();
 Pl_Stop_Prolog();
 if (top_level || nb_user_directive)
 return 0;
 fprintf(stderr,
 "Warning: no initial goal executed\n"
 " use a directive :- initialization(Goal)\n"
 " or remove the link option --no-top-level"
 " (or --min-bips or --min-size)\n");
 return 1;
}
int
main(int argc, char *argv[])
{
 return Main_Wrapper(argc, argv);
}

Note that under some circumstances it is necessary to encapsulate the code of main() inside an intermediate function called by main(). Indeed, some C compilers (e.g. gcc) treats main() particularly, producing an incompatible code w.r.t GNU Prolog. So it is a good idea to always use a wrapper function as shown above.

10.7.1  Example: asking for ancestors

In this example we use the following Prolog code (in a file called new_main.pl):

parent(bob, mary).
parent(jane, mary).
parent(mary, peter).
parent(paul, peter).
parent(peter, john).
anc(X, Y):-
 parent(X, Y).
anc(X, Z) :-
 parent(X, Y),
 anc(Y, Z).

The following file (called new_main_c.c) defines a main() function read the name of a person and displaying all successors of that person. This is equivalent to the Prolog query: anc(Result, Name).

static int
Main_Wrapper(int argc, char *argv[])
{
 int func;
 PlTerm arg[10];
 char str[100];
 char *sol[100];
 int i, nb_sol = 0;
 PlBool res;
 Pl_Start_Prolog(argc, argv);
 func = Pl_Find_Atom("anc");
 for (;;)
 {
 printf("\nEnter a name (or 'end' to finish): ");
 fflush(stdout);
 scanf("%s", str);
 if (strcmp(str, "end") == 0)
 break;
 Pl_Query_Begin(PL_TRUE);
 arg[0] = Pl_Mk_Variable();
 arg[1] = Pl_Mk_String(str);
 nb_sol = 0;
 res = Pl_Query_Call(func, 2, arg);
 while (res)
 {
 sol[nb_sol++] = Pl_Rd_String(arg[0]);
 res = Pl_Query_Next_Solution();
 }
 Pl_Query_End(PL_RECOVER);
 for (i = 0; i < nb_sol; i++)
 printf(" solution: %s\n", sol[i]);
 printf("%d solution(s)\n", nb_sol);
 }
 Pl_Stop_Prolog();
 return 0;
}
int
main(int argc, char *argv[])
{
 return Main_Wrapper(argc, argv);
}

The compilation produces an executable called new_main:

% gplc new_main.pl new_main_c.c

Examples of use:

Enter a name (or 'end' to finish): john
 solution: peter
 solution: bob
 solution: jane
 solution: mary
 solution: paul
5 solution(s)
Enter a name (or 'end' to finish): mary
 solution: bob
 solution: jane
2 solution(s)
Enter a name (or 'end' to finish): end

Copyright (C) 1999-2021 Daniel Diaz Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. More about the copyright
Previous Up

AltStyle によって変換されたページ (->オリジナル) /