PIPS
daVinci_wrapper.c
Go to the documentation of this file.
1 /*
2 
3  $Id: daVinci_wrapper.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* All the stuff to use the graph viewer daVinci from PIPS.
28 
29  Ronan.Keryell@cri.ensmp.fr
30 
31  */
32 
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <stdarg.h>
36 #include <signal.h>
37 #include <sys/wait.h>
38 #include <errno.h>
39 
40 #include "genC.h"
41 
42 #include "constants.h"
43 #include "misc.h"
44 
45 /* To monitor if we have already running daVinci: */
46 pid_t daVinci_pid = 0;
47 
48 /* The daVinci context control: */
51 
52 /* To process some eventual handler somewhere else: */
53 void ( * old_SIGCHLD_handler)() = NULL;
54 
55 /* The pipes to communicate with daVinci: */
58 
59 static string
61 {
62  static char * command = NULL;
63  static int command_size = 0;
64  int position = 0;
65  bool backslash_pending_p = FALSE;
66 
67  debug_on("DAVINCI_DEBUG_LEVEL");
68 
69  if (command_size == 0) {
70  /* Allocate some place the first time: */
71  command_size = 10;
72  command = malloc(10);
73  }
74 
75  /* A "\n" is used by daVinci to end answers: */
76  for(;;) {
77  char a_character;
78  /* Not optimized: read characters one by one... */
79  int length = read(read_from_daVinci_fd, &a_character, 1);
80  if (length == 0)
81  continue;
82 
83  if (length == 1) {
84  pips_debug(8, "Read character \"%c\" (%d)\n",
85  a_character, a_character);
86  if (a_character == '\n')
87  /* End of answer found: */
88  break;
89 
90  /* Deal with some '\' forms in strings: */
91  if (backslash_pending_p) {
92  backslash_pending_p = FALSE;
93  if (a_character == 'n')
94  a_character = '\n';
95  /* Else, '\\' -> '\', '\"' -> '"' without doing
96  anything. */
97  }
98  if (position == command_size - 2) {
99  /* No more place in the command buffer: */
100  command_size *= 2;
101  command = realloc(command, command_size);
102  }
103  command[position++] = a_character;
104  }
105  }
106  /* To mark the end to ease later parsing: */
107  command[position++] = '\001';
108  command[position] = '\0';
109 
110  debug_off();
111  return command;
112 }
113 
114 
115 static void
117 {
118  char * command = read_answer_from_daVinci();
119  char * buffer = malloc(strlen(command));
120 
121  for(;;) {
122  if (strcmp(command, "ok\001")) {
123  pips_debug(8, "\"ok\" parsed\n");
124  break;
125  }
126 
127  /* I love scanf-based parser... :-) */
128  if (sscanf(command, "context(\"Context_%d\")\001",
129  &daVinci_current_context) == 1) {
130  pips_debug(8, "Current context set to %d\n",
132  break;
133  }
134 
135  if (sscanf(command, "communication_error(\"%s\")\001",
136  buffer) == 1) {
137  user_warning("daVinci said...",
138  "communication_error(\"%s\")", buffer);
139  break;
140  }
141  }
142 }
143 
144 
145 /* Send a command to daVinci with an à la printf syntax: */
146 static void
147 send_command_to_daVinci(string command_format, ...)
148 {
149  va_list some_arguments;
150 
151  va_start(some_arguments, command_format);
152  vfprintf(write_to_daVinci_stream, command_format, some_arguments);
153  va_end(some_arguments);
154 
155  /* A "\n" is used by daVinci to end commands: */
157  fflush(write_to_daVinci_stream);
158 }
159 
160 
161 static void
163  int code,
164  struct sigcontext * scp,
165  char * addr)
166 {
167  pid_t pid;
168  int statusp;
169 
170  debug_on("DAVINCI_DEBUG_LEVEL");
171  pid = waitpid(daVinci_pid, &statusp, WNOHANG);
172 
173  pips_debug(5, "waitpid -> %d\n", pid);
174 
175  if (pid == -1) {
176  /* Not about daVinci, pass to the old handler: */
177  debug_off();
178  ( * old_SIGCHLD_handler)(sig, code, scp, addr);
179  }
180 
181  /* If the calling process is stopped, pid = 0: */
182  if (pid != 0 && (statusp & 255) != 127) {
183  /* Well, daVinci is no longer here... */
184  pips_debug(5, "daVinci pid %d exited with status %x\n",
185  daVinci_pid, statusp);
186  daVinci_pid = 0;
187  /* Restore the old handler: */
188  (void) signal(SIGCHLD, old_SIGCHLD_handler);
189  old_SIGCHLD_handler = NULL;
190  }
191  else {
192  /* Else, the process may have stopped: nothing to do. */
193  }
194  debug_off();
195 }
196 
197 
198 void
200 {
201  int pips_output_fd[2], pips_input_fd[2];
202 
203  debug_on("DAVINCI_DEBUG_LEVEL");
204  if (daVinci_pid != 0) {
205  /* It is not necessary to start another daVinci: */
206  debug_off();
207  return;
208  }
209 
210  /* Create the 2 pipes to communicate with daVinci.
211 
212  Hum, need some portability adjustment for SVR4... */
213  if (pipe(pips_output_fd) != 0 || pipe(pips_input_fd) != 0) {
214  perror("fork");
215  pips_internal_error("Cannot create the 2 pipes.\n");
216  }
217 
218  daVinci_pid = fork();
219  pips_debug(5, "daVinci_pid = %d\n", daVinci_pid);
220 
221  if (daVinci_pid == -1) {
222  perror("fork");
223  pips_internal_error("Cannot fork a process.\n");
224  }
225 
226  if (daVinci_pid == 0) {
227  /* This is the child: */
228  /* Connect the PIPS pipes to stdin and stdout of daVinci: */
229  if (dup2(pips_output_fd[0], fileno(stdin)) == -1
230  || dup2(pips_input_fd[1], fileno(stdout)) == -1) {
231  perror("dup2");
232  pips_internal_error("Cannot dup file descriptors.\n");
233  }
234 
235  execlp("daVinci", "daVinci", "-pipe", NULL);
236  perror("execl of daVinci");
237  pips_internal_error("Cannot start the daVinci process.\n");
238  /* Hum, the PIPS parent will go on... */
239  }
240  else {
241  /* The parent: */
242  write_to_daVinci_stream = fdopen(pips_output_fd[1], "w");
243  if (write_to_daVinci_stream == NULL)
244  pips_internal_error("Cannot fdopen pips_output_fd[1].\n");
245 
246  read_from_daVinci_fd = pips_input_fd[0];
247 
248  /* Install the handler to monitor daVinci: */
249  old_SIGCHLD_handler = signal(SIGCHLD, monitor_daVinci);
250 
251  /* Wait for the OK stuff. */
253  }
254  debug_off();
255 }
256 
257 
258 void
260 {
262  (void) printf("%s\n", read_answer_from_daVinci());
263  send_command_to_daVinci("multi(open_context(\"Context_%d\"))",
265 }
266 
267 void
268 send_graph_to_daVinci(string graph_file_name)
269 {
271  (void) printf("%s\n", read_answer_from_daVinci());
272  (void) printf("%s\n", read_answer_from_daVinci());
273 
274  /* Send the graph: */
275  send_command_to_daVinci("menu(file(open_graph(\"%s\")))",
276  graph_file_name);
277 }
278 
279 
281 {
282  /*
283  start_daVinci_if_not_running();
284  send_command_to_daVinci("multi(open_context(\"Context_1\"))");
285  */
286  send_graph_to_daVinci("ESSAI.pref-daVinci%");
287  send_graph_to_daVinci("ESSAI.pref-daVinci");
288  for (;;)
289  (void) printf("%s\n", read_answer_from_daVinci());
290 
291  safe_system("sleep 100");
292  exit(0);
293 }
void * malloc(YYSIZE_T)
pid_t daVinci_pid
All the stuff to use the graph viewer daVinci from PIPS.
void start_daVinci_if_not_running()
void(* old_SIGCHLD_handler)()
To process some eventual handler somewhere else:
int daVinci_current_context
The daVinci context control:
static void parse_daVinci_answer()
main()
int read_from_daVinci_fd
void create_daVinci_new_context()
static void send_command_to_daVinci(string command_format,...)
Send a command to daVinci with an à la printf syntax:
static void monitor_daVinci(int sig, int code, struct sigcontext *scp, char *addr)
static string read_answer_from_daVinci()
void send_graph_to_daVinci(string graph_file_name)
int daVinci_next_context_to_create
FILE * write_to_daVinci_stream
The pipes to communicate with daVinci:
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define exit(code)
Definition: misc-local.h:54
#define user_warning(fn,...)
Definition: misc-local.h:262
void safe_system(string)
system.c
Definition: system.c:38
struct _newgen_struct_code_ * code
Definition: ri.h:79
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
int printf()
static string buffer
Definition: string.c:113