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 #include <stdlib.h>
33 #include <unistd.h>
34 #include <stdarg.h>
35 #include <signal.h>
36 #include <sys/wait.h>
37 #include <errno.h>
38 
39 #include "genC.h"
40 
41 #include "constants.h"
42 #include "misc.h"
43 
44 /* To monitor if we have already running daVinci: */
45 pid_t daVinci_pid = 0;
46 
47 /* The daVinci context control: */
50 
51 /* To process some eventual handler somewhere else: */
52 void ( * old_SIGCHLD_handler)() = NULL;
53 
54 /* The pipes to communicate with daVinci: */
57 
58 static string
60 {
61  static char * command = NULL;
62  static int command_size = 0;
63  int position = 0;
64  bool backslash_pending_p = FALSE;
65 
66  debug_on("DAVINCI_DEBUG_LEVEL");
67 
68  if (command_size == 0) {
69  /* Allocate some place the first time: */
70  command_size = 10;
71  command = malloc(10);
72  }
73 
74  /* A "\n" is used by daVinci to end answers: */
75  for(;;) {
76  char a_character;
77  /* Not optimized: read characters one by one... */
78  int length = read(read_from_daVinci_fd, &a_character, 1);
79  if (length == 0)
80  continue;
81 
82  if (length == 1) {
83  pips_debug(8, "Read character \"%c\" (%d)\n",
84  a_character, a_character);
85  if (a_character == '\n')
86  /* End of answer found: */
87  break;
88 
89  /* Deal with some '\' forms in strings: */
90  if (backslash_pending_p) {
91  backslash_pending_p = FALSE;
92  if (a_character == 'n')
93  a_character = '\n';
94  /* Else, '\\' -> '\', '\"' -> '"' without doing
95  anything. */
96  }
97  if (position == command_size - 2) {
98  /* No more place in the command buffer: */
99  command_size *= 2;
100  command = realloc(command, command_size);
101  }
102  command[position++] = a_character;
103  }
104  }
105  /* To mark the end to ease later parsing: */
106  command[position++] = '\001';
107  command[position] = '\0';
108 
109  debug_off();
110  return command;
111 }
112 
113 
114 static void
116 {
117  char * command = read_answer_from_daVinci();
118  char * buffer = malloc(strlen(command));
119 
120  for(;;) {
121  if (strcmp(command, "ok\001")) {
122  pips_debug(8, "\"ok\" parsed\n");
123  break;
124  }
125 
126  /* I love scanf-based parser... :-) */
127  if (sscanf(command, "context(\"Context_%d\")\001",
128  &daVinci_current_context) == 1) {
129  pips_debug(8, "Current context set to %d\n",
131  break;
132  }
133 
134  if (sscanf(command, "communication_error(\"%s\")\001",
135  buffer) == 1) {
136  user_warning("daVinci said...",
137  "communication_error(\"%s\")", buffer);
138  break;
139  }
140  }
141 }
142 
143 
144 /* Send a command to daVinci with an à la printf syntax: */
145 static void
146 send_command_to_daVinci(string command_format, ...)
147 {
148  va_list some_arguments;
149 
150  va_start(some_arguments, command_format);
151  vfprintf(write_to_daVinci_stream, command_format, some_arguments);
152  va_end(some_arguments);
153 
154  /* A "\n" is used by daVinci to end commands: */
156  fflush(write_to_daVinci_stream);
157 }
158 
159 
160 static void
162  int code,
163  struct sigcontext * scp,
164  char * addr)
165 {
166  pid_t pid;
167  int statusp;
168 
169  debug_on("DAVINCI_DEBUG_LEVEL");
170  pid = waitpid(daVinci_pid, &statusp, WNOHANG);
171 
172  pips_debug(5, "waitpid -> %d\n", pid);
173 
174  if (pid == -1) {
175  /* Not about daVinci, pass to the old handler: */
176  debug_off();
177  ( * old_SIGCHLD_handler)(sig, code, scp, addr);
178  }
179 
180  /* If the calling process is stopped, pid = 0: */
181  if (pid != 0 && (statusp & 255) != 127) {
182  /* Well, daVinci is no longer here... */
183  pips_debug(5, "daVinci pid %d exited with status %x\n",
184  daVinci_pid, statusp);
185  daVinci_pid = 0;
186  /* Restore the old handler: */
187  (void) signal(SIGCHLD, old_SIGCHLD_handler);
188  old_SIGCHLD_handler = NULL;
189  }
190  else {
191  /* Else, the process may have stopped: nothing to do. */
192  }
193  debug_off();
194 }
195 
196 
197 void
199 {
200  int pips_output_fd[2], pips_input_fd[2];
201 
202  debug_on("DAVINCI_DEBUG_LEVEL");
203  if (daVinci_pid != 0) {
204  /* It is not necessary to start another daVinci: */
205  debug_off();
206  return;
207  }
208 
209  /* Create the 2 pipes to communicate with daVinci.
210 
211  Hum, need some portability adjustment for SVR4... */
212  if (pipe(pips_output_fd) != 0 || pipe(pips_input_fd) != 0) {
213  perror("fork");
214  pips_internal_error("Cannot create the 2 pipes.\n");
215  }
216 
217  daVinci_pid = fork();
218  pips_debug(5, "daVinci_pid = %d\n", daVinci_pid);
219 
220  if (daVinci_pid == -1) {
221  perror("fork");
222  pips_internal_error("Cannot fork a process.\n");
223  }
224 
225  if (daVinci_pid == 0) {
226  /* This is the child: */
227  /* Connect the PIPS pipes to stdin and stdout of daVinci: */
228  if (dup2(pips_output_fd[0], fileno(stdin)) == -1
229  || dup2(pips_input_fd[1], fileno(stdout)) == -1) {
230  perror("dup2");
231  pips_internal_error("Cannot dup file descriptors.\n");
232  }
233 
234  execlp("daVinci", "daVinci", "-pipe", NULL);
235  perror("execl of daVinci");
236  pips_internal_error("Cannot start the daVinci process.\n");
237  /* Hum, the PIPS parent will go on... */
238  }
239  else {
240  /* The parent: */
241  write_to_daVinci_stream = fdopen(pips_output_fd[1], "w");
242  if (write_to_daVinci_stream == NULL)
243  pips_internal_error("Cannot fdopen pips_output_fd[1].\n");
244 
245  read_from_daVinci_fd = pips_input_fd[0];
246 
247  /* Install the handler to monitor daVinci: */
248  old_SIGCHLD_handler = signal(SIGCHLD, monitor_daVinci);
249 
250  /* Wait for the OK stuff. */
252  }
253  debug_off();
254 }
255 
256 
257 void
259 {
261  (void) printf("%s\n", read_answer_from_daVinci());
262  send_command_to_daVinci("multi(open_context(\"Context_%d\"))",
264 }
265 
266 void
267 send_graph_to_daVinci(string graph_file_name)
268 {
270  (void) printf("%s\n", read_answer_from_daVinci());
271  (void) printf("%s\n", read_answer_from_daVinci());
272 
273  /* Send the graph: */
274  send_command_to_daVinci("menu(file(open_graph(\"%s\")))",
275  graph_file_name);
276 }
277 
278 
280 {
281  /*
282  start_daVinci_if_not_running();
283  send_command_to_daVinci("multi(open_context(\"Context_1\"))");
284  */
285  send_graph_to_daVinci("ESSAI.pref-daVinci%");
286  send_graph_to_daVinci("ESSAI.pref-daVinci");
287  for (;;)
288  (void) printf("%s\n", read_answer_from_daVinci());
289 
290  system("sleep 100");
291  exit(0);
292 }
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:
main()
int read_from_daVinci_fd
void create_daVinci_new_context()
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
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
static void parse_daVinci_answer()
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()