Scippy

SCIP

Solving Constraint Integer Programs

dialog.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file dialog.c
17  * @brief methods for user interface dialog
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 #ifdef WITH_READLINE
28 #include <stdio.h>
29 #include <readline/readline.h>
30 #include <readline/history.h>
31 #endif
32 
33 #include "scip/scip.h"
34 #include "scip/def.h"
35 #include "blockmemshell/memory.h"
36 #include "scip/set.h"
37 #include "scip/pub_misc.h"
38 #include "scip/dialog.h"
39 
40 #include "scip/struct_dialog.h"
41 
42 
43 
44 
45 /*
46  * read line methods
47  */
48 
49 #ifdef WITH_READLINE
50 
51 /** reads a line of input from stdin */
52 static
54  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
55  const char* prompt, /**< prompt to display */
56  SCIP_Bool* endoffile /**< pointer to store whether the end of the input file was reached */
57  )
58 {
59  char* s;
60 
61  assert(endoffile != NULL);
62 
63  s = readline(prompt);
64  if( s != NULL )
65  {
66  (void)strncpy(&dialoghdlr->buffer[dialoghdlr->bufferpos], s,
67  (unsigned int)(dialoghdlr->buffersize - dialoghdlr->bufferpos));
68  free(s);
69  *endoffile = FALSE;
70  }
71  else
72  *endoffile = TRUE;
73 
74  return SCIP_OKAY;
75 }
76 
77 /** puts the given string on the command history */
78 static
80  const char* s /**< string to add to the command history */
81  )
82 {
83  add_history(s);
84 
85  return SCIP_OKAY;
86 }
87 
88 /** returns the current length of the history list */
89 static
91  void
92  )
93 {
94 #ifndef NO_REMOVE_HISTORY
95  return history_length;
96 #else
97  return 0;
98 #endif
99 }
100 
101 /** removes a single element from the history list */
102 static
104  int pos /**< list position of history entry to remove */
105  )
106 {
107 #ifndef NO_REMOVE_HISTORY
108  HIST_ENTRY* entry;
109 
110  entry = remove_history(pos);
111 
112  /* Free readline/history storage: there seem to be differences in the versions (and the amount of
113  * data to be freed). The following should be a good approximation; if it doesn't work define
114  * NO_REMOVE_HISTORY - see the INSTALL file. This will produce minor memory leaks.
115  */
116 #if RL_VERSION_MAJOR >= 5
117  (void)free_history_entry(entry);
118 #else
119  if( entry != NULL )
120  {
121  free((void*)entry->line);
122  free(entry);
123  }
124 #endif
125 #endif
126 
127  return SCIP_OKAY;
128 }
129 
130 #else
131 
132 /** reads a line of input from stdin */
133 static
135  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
136  const char* prompt, /**< prompt to display */
137  SCIP_Bool* endoffile /**< pointer to store whether the end of the input file was reached */
138  )
139 {
140  char* s;
141 
142  assert(dialoghdlr != NULL);
143  assert(dialoghdlr->buffer != NULL);
144  assert(dialoghdlr->bufferpos < dialoghdlr->buffersize);
145  assert(dialoghdlr->buffer[dialoghdlr->bufferpos] == '\0');
146  assert(endoffile != NULL);
147 
148  /* check for EOF (due to CTRL-D or unexpected end of piped-in file) */
149  if( feof(stdin) )
150  *endoffile = TRUE;
151  else
152  {
153  char* result;
154 
155  /* display prompt */
156  printf("%s", prompt);
157 
158  /* read line from stdin */
159  result = fgets(&dialoghdlr->buffer[dialoghdlr->bufferpos], dialoghdlr->buffersize - dialoghdlr->bufferpos, stdin);
160  assert(result != NULL);
161  (void) result; /* disable compiler warning [-Wunused-result] */
162 
163  /* replace newline with \0 */
164  s = strchr(&dialoghdlr->buffer[dialoghdlr->bufferpos], '\n');
165  if( s != NULL )
166  *s = '\0';
167  *endoffile = FALSE;
168  }
169 
170  return SCIP_OKAY;
171 }
172 
173 /** puts the given string on the command history */
174 static
176  const char* s /**< string to add to the command history */
177  )
178 { /*lint --e{715}*/
179  /* nothing to do here */
180  return SCIP_OKAY;
181 }
182 
183 /** returns the current length of the history list */
184 static
186  void
187  )
188 {
189  return 0;
190 }
191 
192 /** removes a single element from the history list */
193 static
195  int pos /**< list position of history entry to remove */
196  )
197 { /*lint --e{715}*/
198  /* nothing to do here */
199  return SCIP_OKAY;
200 }
201 
202 #endif
203 
204 /** frees a single linelist entry, but not its successors */
205 static
207  SCIP_LINELIST** linelist /**< pointer to line list */
208  )
209 {
210  assert(linelist != NULL);
211 
212  BMSfreeMemoryArray(&(*linelist)->inputline);
213  BMSfreeMemory(linelist);
214 }
215 
216 /** frees a linelist entry and all of its successors */
217 static
219  SCIP_LINELIST** linelist /**< pointer to line list */
220  )
221 {
222  assert(linelist != NULL);
223 
224  while( *linelist != NULL )
225  {
226  SCIP_LINELIST* nextline;
227 
228  nextline = (*linelist)->nextline;
229  linelistFree(linelist);
230  *linelist = nextline;
231  }
232 }
233 
234 /** reads a line of input from stdin or from the stored input lines in the input list */
235 static
237  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
238  const char* prompt, /**< prompt to display */
239  SCIP_Bool* endoffile /**< pointer to store whether the end of the input file was reached */
240  )
241 {
242  assert(dialoghdlr != NULL);
243  assert(dialoghdlr->buffer != NULL);
244  assert(dialoghdlr->bufferpos < dialoghdlr->buffersize);
245  assert(dialoghdlr->buffer[dialoghdlr->bufferpos] == '\0');
246  assert(endoffile != NULL);
247 
248  *endoffile = FALSE;
249 
250  if( dialoghdlr->inputlist == NULL )
251  {
252  /* read a line from stdin */
253  SCIP_CALL( readLine(dialoghdlr, prompt, endoffile) );
254  }
255  else
256  {
257  SCIP_LINELIST* nextline;
258 
259  /* copy the next input line into the input buffer */
260  (void)strncpy(&dialoghdlr->buffer[dialoghdlr->bufferpos], dialoghdlr->inputlist->inputline,
261  (size_t)(dialoghdlr->buffersize - dialoghdlr->bufferpos)); /*lint !e571 !e776*/
262  dialoghdlr->buffer[dialoghdlr->buffersize-1] = '\0';
263 
264  /* free the input line */
265  nextline = dialoghdlr->inputlist->nextline;
266  if( dialoghdlr->inputlistptr == &(dialoghdlr->inputlist->nextline) )
267  dialoghdlr->inputlistptr = &dialoghdlr->inputlist;
268  linelistFree(&dialoghdlr->inputlist);
269  dialoghdlr->inputlist = nextline;
270  assert(dialoghdlr->inputlistptr != NULL);
271  assert(*dialoghdlr->inputlistptr == NULL);
272  }
273 
274  return SCIP_OKAY;
275 }
276 
277 
278 
279 
280 /*
281  * dialog handler
282  */
283 
284 /** copies the given dialog to a new scip */
286  SCIP_DIALOG* dialog, /**< dialog */
287  SCIP_SET* set /**< SCIP_SET of SCIP to copy to */
288  )
289 {
290  assert(dialog != NULL);
291  assert(set != NULL);
292  assert(set->scip != NULL);
293 
294  if( dialog->dialogcopy != NULL )
295  {
296  SCIPdebugMessage("including dialog %s in subscip %p\n", SCIPdialogGetName(dialog), (void*)set->scip);
297  SCIP_CALL( dialog->dialogcopy(set->scip, dialog) );
298  }
299  return SCIP_OKAY;
300 }
301 
302 /** creates a dialog handler */
304  SCIP_SET* set, /**< global SCIP settings */
305  SCIP_DIALOGHDLR** dialoghdlr /**< pointer to store dialog handler */
306  )
307 { /*lint --e{715}*/
308 #ifdef WITH_READLINE
309  char readlineversion[20];
310 #endif
311 
312  assert(dialoghdlr != NULL);
313 
314  SCIP_ALLOC( BMSallocMemory(dialoghdlr) );
315  (*dialoghdlr)->rootdialog = NULL;
316  (*dialoghdlr)->inputlist = NULL;
317  (*dialoghdlr)->inputlistptr = &(*dialoghdlr)->inputlist;
318  (*dialoghdlr)->buffersize = SCIP_MAXSTRLEN;
319  (*dialoghdlr)->nprotectedhistelems = -1;
320  SCIP_ALLOC( BMSallocMemoryArray(&(*dialoghdlr)->buffer, (*dialoghdlr)->buffersize) );
321 
322  SCIPdialoghdlrClearBuffer(*dialoghdlr);
323 
324 #ifdef WITH_READLINE
325  (void) SCIPsnprintf(readlineversion, sizeof(readlineversion), "Readline %s", rl_library_version);
326  SCIP_CALL( SCIPsetIncludeExternalCode(set, readlineversion, "GNU library for command line editing (gnu.org/s/readline)") );
327 #endif
328 
329  return SCIP_OKAY;
330 }
331 
332 /** frees a dialog handler and it's dialog tree */
334  SCIP* scip, /**< SCIP data structure */
335  SCIP_DIALOGHDLR** dialoghdlr /**< pointer to dialog handler */
336  )
337 {
338  assert(dialoghdlr != NULL);
339 
340  SCIP_CALL( SCIPdialoghdlrSetRoot(scip, *dialoghdlr, NULL) );
341  linelistFreeAll(&(*dialoghdlr)->inputlist);
342  BMSfreeMemoryArray(&(*dialoghdlr)->buffer);
343  BMSfreeMemory(dialoghdlr);
344 
345  return SCIP_OKAY;
346 }
347 
348 /** executes the root dialog of the dialog handler */
350  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
351  SCIP_SET* set /**< global SCIP settings */
352  )
353 {
354  SCIP_DIALOG* dialog;
355 
356  assert(dialoghdlr != NULL);
357  assert(dialoghdlr->buffer != NULL);
358 
359  /* clear the buffer, start with the root dialog */
360  SCIPdialoghdlrClearBuffer(dialoghdlr);
361  dialog = dialoghdlr->rootdialog;
362 
363  /* execute dialogs until a NULL is returned as next dialog */
364  while( dialog != NULL )
365  {
366  SCIP_CALL( SCIPdialogExec(dialog, set, dialoghdlr, &dialog) );
367 
368  /* reset buffer, it is was consumed completely */
369  if( dialoghdlr->buffer[dialoghdlr->bufferpos] == '\0' )
370  SCIPdialoghdlrClearBuffer(dialoghdlr);
371  }
372 
373  return SCIP_OKAY;
374 }
375 
376 /** makes given dialog the root dialog of dialog handler; captures dialog and releases former root dialog */
378  SCIP* scip, /**< SCIP data structure */
379  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
380  SCIP_DIALOG* dialog /**< dialog to be the root */
381  )
382 {
383  assert(dialoghdlr != NULL);
384 
385  if( dialoghdlr->rootdialog != NULL )
386  {
387  SCIP_CALL( SCIPdialogRelease(scip, &dialoghdlr->rootdialog) );
388  }
389  assert(dialoghdlr->rootdialog == NULL);
390 
391  dialoghdlr->rootdialog = dialog;
392 
393  if( dialog != NULL )
394  SCIPdialogCapture(dialog);
395 
396  return SCIP_OKAY;
397 }
398 
399 /** returns the root dialog of the dialog handler */
401  SCIP_DIALOGHDLR* dialoghdlr /**< dialog handler */
402  )
403 {
404  assert(dialoghdlr != NULL);
405 
406  return dialoghdlr->rootdialog;
407 }
408 
409 /** clears the input command buffer of the dialog handler */
411  SCIP_DIALOGHDLR* dialoghdlr /**< dialog handler */
412  )
413 {
414  assert(dialoghdlr != NULL);
415 
416  dialoghdlr->buffer[0] = '\0';
417  dialoghdlr->bufferpos = 0;
418 }
419 
420 /** returns TRUE iff input command buffer is empty */
422  SCIP_DIALOGHDLR* dialoghdlr /**< dialog handler */
423  )
424 {
425  assert(dialoghdlr != NULL);
426  assert(dialoghdlr->bufferpos < dialoghdlr->buffersize);
427 
428  return (dialoghdlr->buffer[dialoghdlr->bufferpos] == '\0');
429 }
430 
431 /** returns the next word in the handler's command buffer; if the buffer is empty, displays the given prompt or the
432  * current dialog's path and asks the user for further input; the user must not free or modify the returned string
433  */
435  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
436  SCIP_DIALOG* dialog, /**< current dialog */
437  const char* prompt, /**< prompt to display, or NULL to display the current dialog's path */
438  char** inputword, /**< pointer to store the next word in the handler's command buffer */
439  SCIP_Bool* endoffile /**< pointer to store whether the end of the input file was reached */
440  )
441 {
442  char path[SCIP_MAXSTRLEN];
443  char p[SCIP_MAXSTRLEN];
444  char* firstword;
445  int pos;
446 
447  assert(dialoghdlr != NULL);
448  assert(dialoghdlr->buffer != NULL);
449  assert(dialoghdlr->bufferpos < dialoghdlr->buffersize);
450  assert(inputword != NULL);
451  assert(endoffile != NULL);
452 
453  *endoffile = FALSE;
454 
455  /* get input from the user, if the buffer is empty */
456  if( SCIPdialoghdlrIsBufferEmpty(dialoghdlr) )
457  {
458  int len;
459 
460  /* clear the buffer */
461  SCIPdialoghdlrClearBuffer(dialoghdlr);
462 
463  if( prompt == NULL )
464  {
465  /* use current dialog's path as prompt */
466  SCIPdialogGetPath(dialog, '/', path);
467  (void) SCIPsnprintf(p, SCIP_MAXSTRLEN, "%s> ", path);
468  prompt = p;
469  }
470 
471  /* read command line from stdin or from the input line list */
472  SCIP_CALL( readInputLine(dialoghdlr, prompt, endoffile) );
473 
474  /* strip trailing spaces */
475  len = (int)strlen(&dialoghdlr->buffer[dialoghdlr->bufferpos]);
476  if( len > 0 )
477  {
478  while( isspace((unsigned char)dialoghdlr->buffer[dialoghdlr->bufferpos + len - 1]) )
479  {
480  dialoghdlr->buffer[dialoghdlr->bufferpos + len - 1] = '\0';
481  len--;
482  }
483  }
484 
485  /* insert command in command history */
486  if( dialoghdlr->buffer[dialoghdlr->bufferpos] != '\0' )
487  {
488  SCIP_CALL( SCIPdialoghdlrAddHistory(dialoghdlr, NULL, &dialoghdlr->buffer[dialoghdlr->bufferpos], FALSE) );
489  }
490  }
491 
492  /* the last character in the buffer must be a '\0' */
493  dialoghdlr->buffer[dialoghdlr->buffersize-1] = '\0';
494 
495  /* skip leading spaces: find start of first word */
496  while( isspace((unsigned char)dialoghdlr->buffer[dialoghdlr->bufferpos]) )
497  dialoghdlr->bufferpos++;
498  firstword = &dialoghdlr->buffer[dialoghdlr->bufferpos];
499 
500  pos = dialoghdlr->bufferpos;
501  while( dialoghdlr->buffer[dialoghdlr->bufferpos] != '\0' && !isspace((unsigned char)dialoghdlr->buffer[dialoghdlr->bufferpos]) )
502  {
503  assert(pos <= dialoghdlr->bufferpos);
504 
505  switch( dialoghdlr->buffer[dialoghdlr->bufferpos] )
506  {
507  case '"':
508  dialoghdlr->bufferpos++;
509  /* read characters as they are until the next " */
510  while( dialoghdlr->buffer[dialoghdlr->bufferpos] != '\0' && dialoghdlr->buffer[dialoghdlr->bufferpos] != '"' )
511  {
512  /* watch out for \" and \\ which should be treated as " and \, respectively */
513  if( dialoghdlr->buffer[dialoghdlr->bufferpos] == '\\'
514  && (dialoghdlr->buffer[dialoghdlr->bufferpos+1] == '"'
515  || dialoghdlr->buffer[dialoghdlr->bufferpos+1] == '\\') )
516  {
517  dialoghdlr->bufferpos++;
518  }
519  dialoghdlr->buffer[pos] = dialoghdlr->buffer[dialoghdlr->bufferpos];
520  pos++;
521  dialoghdlr->bufferpos++;
522  }
523  if( dialoghdlr->buffer[dialoghdlr->bufferpos] == '"' )
524  dialoghdlr->bufferpos++; /* skip final " */
525  break;
526  case '\'':
527  dialoghdlr->bufferpos++;
528  /* read characters as they are until the next ' */
529  while( dialoghdlr->buffer[dialoghdlr->bufferpos] != '\0' && dialoghdlr->buffer[dialoghdlr->bufferpos] != '\'' )
530  {
531  /* watch out for \' and \\ which should be treated as ' and \, respectively */
532  if( dialoghdlr->buffer[dialoghdlr->bufferpos] == '\\'
533  && (dialoghdlr->buffer[dialoghdlr->bufferpos+1] == '\''
534  || dialoghdlr->buffer[dialoghdlr->bufferpos+1] == '\\') )
535  {
536  dialoghdlr->bufferpos++;
537  }
538  dialoghdlr->buffer[pos] = dialoghdlr->buffer[dialoghdlr->bufferpos];
539  pos++;
540  dialoghdlr->bufferpos++;
541  }
542  if( dialoghdlr->buffer[dialoghdlr->bufferpos] == '\'' )
543  dialoghdlr->bufferpos++; /* skip final ' */
544  break;
545  case '\\':
546  /* if the next character is a space, a ", or a ', read next character as it is;
547  * otherwise, treat the \ as normal character
548  */
549  if( dialoghdlr->buffer[dialoghdlr->bufferpos+1] == ' '
550  || dialoghdlr->buffer[dialoghdlr->bufferpos+1] == '"'
551  || dialoghdlr->buffer[dialoghdlr->bufferpos+1] == '\'' )
552  {
553  dialoghdlr->bufferpos++;
554  }
555  /*lint -fallthrough*/
556  default:
557  dialoghdlr->buffer[pos] = dialoghdlr->buffer[dialoghdlr->bufferpos];
558  pos++;
559  dialoghdlr->bufferpos++;
560  break;
561  }
562  }
563  assert(pos <= dialoghdlr->bufferpos);
564 
565  /* move buffer to the next position */
566  if( dialoghdlr->buffer[dialoghdlr->bufferpos] != '\0' )
567  dialoghdlr->bufferpos++;
568 
569  /* truncate the command word in the buffer */
570  if( dialoghdlr->buffer[pos] != '\0' )
571  dialoghdlr->buffer[pos] = '\0';
572 
573  /* remove additional spaces */
574  while( isspace((unsigned char)dialoghdlr->buffer[dialoghdlr->bufferpos]) )
575  dialoghdlr->bufferpos++;
576 
577  *inputword = firstword;
578 
579  SCIPdebugMessage("next word: <%s>\n", *inputword);
580 
581  return SCIP_OKAY;
582 }
583 
584 /** adds a single line of input to the dialog handler which is treated as if the user entered the command line */
586  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
587  const char* inputline /**< input line to add */
588  )
589 {
590  SCIP_LINELIST* linelist;
591 
592  assert(dialoghdlr != NULL);
593  assert(dialoghdlr->inputlistptr != NULL);
594  assert(*dialoghdlr->inputlistptr == NULL);
595  assert(inputline != NULL);
596 
597  SCIP_ALLOC( BMSallocMemory(&linelist) );
598  SCIP_ALLOC( BMSduplicateMemoryArray(&linelist->inputline, inputline, strlen(inputline)+1) );
599  linelist->nextline = NULL;
600  *dialoghdlr->inputlistptr = linelist;
601  dialoghdlr->inputlistptr = &linelist->nextline;
602 
603  return SCIP_OKAY;
604 }
605 
606 /** adds a command to the command history of the dialog handler; if a dialog is given, the command is preceeded
607  * by the dialog's command path; if no command is given, only the path to the dialog is added to the command history
608  */
610  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
611  SCIP_DIALOG* dialog, /**< current dialog, or NULL */
612  const char* command, /**< command string to add to the command history, or NULL */
613  SCIP_Bool escapecommand /**< should special characters in command be prefixed by an escape char? */
614  )
615 {
616  char s[SCIP_MAXSTRLEN];
617  char h[SCIP_MAXSTRLEN];
618  SCIP_Bool cleanuphistory;
619 
620  assert(dialoghdlr != NULL);
621 
622  /* the current history list should be cleaned up if a dialog is given (i.e. the command is not partial) */
623  cleanuphistory = (dialog != NULL);
624 
625  /* generate the string to add to the history */
626  s[SCIP_MAXSTRLEN-1] = '\0';
627  h[SCIP_MAXSTRLEN-1] = '\0';
628 
629  if( command != NULL )
630  {
631  if( escapecommand )
632  SCIPescapeString(h, SCIP_MAXSTRLEN, command);
633  else
634  (void)strncpy(h, command, SCIP_MAXSTRLEN-1);
635  }
636  else
637  h[0] = '\0';
638 
639  while( dialog != NULL && dialog != dialoghdlr->rootdialog )
640  {
641  if( h[0] == '\0' )
642  (void)strncpy(h, dialog->name, SCIP_MAXSTRLEN-1);
643  else
644  {
645  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "%s %s", dialog->name, h);
646  (void)strncpy(h, s, SCIP_MAXSTRLEN-1);
647  }
648  dialog = dialog->parent;
649  }
650 
651  /* clean up the unmarked history entries */
652  if( cleanuphistory )
653  {
654  int i;
655 
656  for( i = getHistoryLength()-1; i >= dialoghdlr->nprotectedhistelems; --i )
657  {
658  SCIP_CALL( removeHistory(i) );
659  }
660  }
661 
662  /* add command to history */
663  if( h[0] != '\0' )
664  {
665  SCIP_CALL( addHistory(h) );
666  }
667 
668  /* if the history string was a full command line, protect the history entry from future cleanups */
669  if( cleanuphistory )
670  {
671  dialoghdlr->nprotectedhistelems = getHistoryLength();
672  }
673 
674  return SCIP_OKAY;
675 }
676 
677 
678 
679 
680 /*
681  * dialog
682  */
683 
684 /** ensures, that sub-dialogs array can store at least the given number of sub-dialogs */
685 static
687  SCIP_DIALOG* dialog, /**< dialog */
688  SCIP_SET* set, /**< global SCIP settings */
689  int num /**< minimal storage size for sub-dialogs */
690  )
691 {
692  assert(dialog != NULL);
693 
694  if( num > dialog->subdialogssize )
695  {
696  int newsize;
697 
698  newsize = SCIPsetCalcMemGrowSize(set, num);
699  SCIP_ALLOC( BMSreallocMemoryArray(&(dialog->subdialogs), newsize) );
700  dialog->subdialogssize = newsize;
701  }
702  assert(num <= dialog->subdialogssize);
703 
704  return SCIP_OKAY;
705 }
706 
707 /** creates and captures a user interface dialog */
709  SCIP_DIALOG** dialog, /**< pointer to store the dialog */
710  SCIP_DECL_DIALOGCOPY ((*dialogcopy)), /**< copy method of dialog or NULL if you don't want to copy your plugin into sub-SCIPs */
711  SCIP_DECL_DIALOGEXEC ((*dialogexec)), /**< execution method of dialog */
712  SCIP_DECL_DIALOGDESC ((*dialogdesc)), /**< description output method of dialog, or NULL */
713  SCIP_DECL_DIALOGFREE ((*dialogfree)), /**< destructor of dialog to free user data, or NULL */
714  const char* name, /**< name of dialog: command name appearing in parent's dialog menu */
715  const char* desc, /**< description of dialog used if description output method is NULL */
716  SCIP_Bool issubmenu, /**< is the dialog a sub-menu? */
717  SCIP_DIALOGDATA* dialogdata /**< user defined dialog data */
718  )
719 {
720  assert(dialog != NULL);
721  assert(name != NULL);
722 
723  SCIP_ALLOC( BMSallocMemory(dialog) );
724  (*dialog)->dialogcopy = dialogcopy;
725  (*dialog)->dialogexec = dialogexec;
726  (*dialog)->dialogdesc = dialogdesc;
727  (*dialog)->dialogfree = dialogfree;
728 
729  SCIP_ALLOC( BMSduplicateMemoryArray(&(*dialog)->name, name, strlen(name)+1) );
730  if( desc != NULL )
731  {
732  SCIP_ALLOC( BMSduplicateMemoryArray(&(*dialog)->desc, desc, strlen(desc)+1) );
733  }
734  else
735  (*dialog)->desc = NULL;
736 
737  (*dialog)->issubmenu = issubmenu;
738  (*dialog)->parent = NULL;
739  (*dialog)->subdialogs = NULL;
740  (*dialog)->nsubdialogs = 0;
741  (*dialog)->subdialogssize = 0;
742  (*dialog)->nuses = 0;
743  (*dialog)->dialogdata = dialogdata;
744 
745  /* capture dialog */
746  SCIPdialogCapture(*dialog);
747 
748  return SCIP_OKAY;
749 }
750 
751 /** frees dialog and all of its sub-dialogs */
752 static
754  SCIP* scip, /**< SCIP data structure */
755  SCIP_DIALOG** dialog /**< pointer to dialog */
756  )
757 {
758  int i;
759 
760  assert(dialog != NULL);
761  assert(*dialog != NULL);
762  assert((*dialog)->nuses == 0);
763 
764  /* call destructor of dialog */
765  if( (*dialog)->dialogfree != NULL )
766  {
767  SCIP_CALL( (*dialog)->dialogfree(scip, *dialog) );
768  }
769 
770  /* release sub-dialogs */
771  for( i = 0; i < (*dialog)->nsubdialogs; ++i )
772  {
773  SCIP_CALL( SCIPdialogRelease(scip, &(*dialog)->subdialogs[i]) );
774  }
775  BMSfreeMemoryArrayNull(&(*dialog)->subdialogs);
776 
777  BMSfreeMemoryArrayNull(&(*dialog)->name);
778  BMSfreeMemoryArrayNull(&(*dialog)->desc);
779  BMSfreeMemory(dialog);
780 
781  return SCIP_OKAY;
782 }
783 
784 /** captures a dialog */
786  SCIP_DIALOG* dialog /**< dialog */
787  )
788 {
789  assert(dialog != NULL);
790 
791  dialog->nuses++;
792 }
793 
794 /** releases a dialog */
796  SCIP* scip, /**< SCIP data structure */
797  SCIP_DIALOG** dialog /**< pointer to dialog */
798  )
799 {
800  assert(dialog != NULL);
801 
802  (*dialog)->nuses--;
803  if( (*dialog)->nuses == 0 )
804  {
805  SCIP_CALL( dialogFree(scip, dialog) );
806  }
807 
808  return SCIP_OKAY;
809 }
810 
811 /** executes dialog */
813  SCIP_DIALOG* dialog, /**< dialog */
814  SCIP_SET* set, /**< global SCIP settings */
815  SCIP_DIALOGHDLR* dialoghdlr, /**< dialog handler */
816  SCIP_DIALOG** nextdialog /**< pointer to store the next dialog to process */
817  )
818 {
819  assert(dialog != NULL);
820  assert(dialog->dialogexec != NULL);
821  assert(set != NULL);
822  assert(nextdialog != NULL);
823 
824  SCIP_CALL( dialog->dialogexec(set->scip, dialog, dialoghdlr, nextdialog) );
825 
826  return SCIP_OKAY;
827 }
828 
829 /** comparison method for sorting dialogs w.r.t. to their name */
830 static
832 {
833  return strcmp( SCIPdialogGetName((SCIP_DIALOG*)elem1), SCIPdialogGetName((SCIP_DIALOG*)elem2) );
834 }
835 
836 /** adds a sub-dialog to the given dialog as menu entry and captures the sub-dialog */
838  SCIP_DIALOG* dialog, /**< dialog */
839  SCIP_SET* set, /**< global SCIP settings */
840  SCIP_DIALOG* subdialog /**< sub-dialog to add as menu entry in dialog */
841  )
842 {
843  assert(dialog != NULL);
844  assert(subdialog != NULL);
845 
846  /* check, if sub-dialog already exists */
847  if( SCIPdialogHasEntry(dialog, SCIPdialogGetName(subdialog)) )
848  {
849  SCIPerrorMessage("dialog entry with name <%s> already exists in dialog <%s>\n",
850  SCIPdialogGetName(subdialog), SCIPdialogGetName(dialog));
851  return SCIP_INVALIDDATA;
852  }
853 
854  /* resize the sub-dialogs array */
855  SCIP_CALL( ensureSubdialogMem(dialog, set, dialog->nsubdialogs+1) );
856 
857  /* link the dialogs as parent-child pair; the sub-dialogs are sorted non-decreasing w.r.t. their name */
858  SCIPsortedvecInsertPtr((void**)dialog->subdialogs, dialogComp, (void*)subdialog, &dialog->nsubdialogs, NULL);
859  subdialog->parent = dialog;
860 
861  /* capture sub-dialog */
862  SCIPdialogCapture(subdialog);
863 
864  return SCIP_OKAY;
865 }
866 
867 /** returns TRUE iff a dialog entry matching exactly the given name is existing in the given dialog */
869  SCIP_DIALOG* dialog, /**< dialog */
870  const char* entryname /**< name of the dialog entry to find */
871  )
872 {
873  SCIP_DIALOG** subdialogs;
874  int nsubdialogs;
875  int i;
876 
877  assert(dialog != NULL);
878  assert(entryname != NULL);
879 
880  /* check entryname w.r.t. available dialog options */
881  subdialogs = SCIPdialogGetSubdialogs(dialog);
882  nsubdialogs = SCIPdialogGetNSubdialogs(dialog);
883  for( i = 0; i < nsubdialogs; ++i )
884  {
885  /* check, if the sub-dialog's name matches entryname */
886  if( strcmp(entryname, SCIPdialogGetName(subdialogs[i])) == 0 )
887  return TRUE;
888  }
889 
890  return FALSE;
891 }
892 
893 /** searches the dialog for entries corresponding to the given name;
894  * If a complete match is found, the entry is returned as "subdialog" and
895  * the return value is 1.
896  * If no dialog entry completely matches the given "entryname", the number
897  * of entries with names beginning with "entryname" is returned. If this
898  * number is 1, the single match is returned as "subdialog". Otherwise,
899  * "subdialog" is set to NULL.
900  */
902  SCIP_DIALOG* dialog, /**< dialog */
903  const char* entryname, /**< name of the dialog entry to find */
904  SCIP_DIALOG** subdialog /**< pointer to store the found dialog entry */
905  )
906 {
907  SCIP_DIALOG** subdialogs;
908  unsigned int namelen;
909  int nsubdialogs;
910  int nfound;
911  int i;
912 
913  assert(dialog != NULL);
914  assert(entryname != NULL);
915  assert(subdialog != NULL);
916 
917  *subdialog = NULL;
918 
919  /* check entryname w.r.t. available dialog options */
920  subdialogs = SCIPdialogGetSubdialogs(dialog);
921  nsubdialogs = SCIPdialogGetNSubdialogs(dialog);
922  namelen = (unsigned int) strlen(entryname);
923  nfound = 0;
924  for( i = 0; i < nsubdialogs; ++i )
925  {
926  /* check, if the beginning of the sub-dialog's name matches entryname */
927  if( strncmp(entryname, SCIPdialogGetName(subdialogs[i]), namelen) == 0 )
928  {
929  *subdialog = subdialogs[i];
930  nfound++;
931 
932  /* if entryname exactly matches the sub-dialog's name, use this sub-dialog */
933  if( namelen == (unsigned int) strlen(SCIPdialogGetName(subdialogs[i])) )
934  return 1;
935  }
936  }
937 
938  if( nfound != 1 )
939  *subdialog = NULL;
940 
941  return nfound;
942 }
943 
944 /** displays the dialog's menu */
946  SCIP_DIALOG* dialog, /**< dialog */
947  SCIP* scip /**< SCIP data structure */
948  )
949 {
950  int i;
951 
952  assert(dialog != NULL);
953 
954  /* display the dialog's sub menus */
955  for( i = 0; i < dialog->nsubdialogs; ++i )
956  {
957  if( SCIPdialogIsSubmenu(dialog->subdialogs[i]) )
958  {
959  SCIP_CALL( SCIPdialogDisplayMenuEntry(dialog->subdialogs[i], scip) );
960  }
961  }
962 
963  /* display the dialog's menu options */
964  for( i = 0; i < dialog->nsubdialogs; ++i )
965  {
966  if( !SCIPdialogIsSubmenu(dialog->subdialogs[i]) )
967  {
968  SCIP_CALL( SCIPdialogDisplayMenuEntry(dialog->subdialogs[i], scip) );
969  }
970  }
971 
972  if( dialog->nsubdialogs == 0 )
973  SCIPdialogMessage(scip, NULL, "<no options available>\n");
974 
975  return SCIP_OKAY;
976 }
977 
978 /** displays the entry for the dialog in it's parent's menu */
980  SCIP_DIALOG* dialog, /**< dialog */
981  SCIP* scip /**< SCIP data structure */
982  )
983 {
984  char name[SCIP_MAXSTRLEN];
985 
986  assert(dialog != NULL);
987 
988  /* display the dialog's name */
989  if( dialog->issubmenu )
990  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "<%s>", dialog->name);
991  else
992  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "%s", dialog->name);
993  SCIPdialogMessage(scip, NULL, " %-21s ", name);
994  if( strlen(name) > 21 )
995  {
996  /* break the line, and start the description in the next line */
997  SCIPdialogMessage(scip, NULL, "\n --> ");
998  }
999 
1000  /* display the dialog's description */
1001  if( dialog->dialogdesc != NULL )
1002  {
1003  SCIP_CALL( dialog->dialogdesc(scip, dialog) );
1004  }
1005  else
1006  SCIPdialogMessage(scip, NULL, "%s",dialog->desc);
1007  SCIPdialogMessage(scip, NULL, "\n");
1008 
1009  return SCIP_OKAY;
1010 }
1011 
1012 /** displays all dialog entries with names starting with the given "entryname" */
1014  SCIP_DIALOG* dialog, /**< dialog */
1015  SCIP* scip, /**< SCIP data structure */
1016  const char* entryname /**< name of the dialog entry to find */
1017  )
1018 {
1019  SCIP_DIALOG** subdialogs;
1020  unsigned int namelen;
1021  int nsubdialogs;
1022  int i;
1023 
1024  assert(dialog != NULL);
1025  assert(entryname != NULL);
1026 
1027  /* check entryname w.r.t. available dialog options */
1028  subdialogs = SCIPdialogGetSubdialogs(dialog);
1029  nsubdialogs = SCIPdialogGetNSubdialogs(dialog);
1030  namelen = (unsigned int) strlen(entryname);
1031  for( i = 0; i < nsubdialogs; ++i )
1032  {
1033  /* check, if the beginning of the sub-dialog's name matches entryname */
1034  if( strncmp(entryname, SCIPdialogGetName(subdialogs[i]), namelen) == 0 )
1035  {
1036  SCIP_CALL( SCIPdialogDisplayMenuEntry(subdialogs[i], scip) );
1037  }
1038  }
1039 
1040  return SCIP_OKAY;
1041 }
1042 
1043 /** gets the name of the current path in the dialog tree, separated by the given character */
1045  SCIP_DIALOG* dialog, /**< dialog */
1046  const char sepchar, /**< separation character to insert in path */
1047  char* path /**< string buffer to store the path */
1048  )
1049 {
1050  char s[SCIP_MAXSTRLEN];
1051 
1052  assert(dialog != NULL);
1053 
1054  (void)strncpy(path, dialog->name, SCIP_MAXSTRLEN);
1055  path[SCIP_MAXSTRLEN - 1] = '\0';
1056 
1057  dialog = dialog->parent;
1058  while( dialog != NULL )
1059  {
1060  (void)SCIPsnprintf(s, SCIP_MAXSTRLEN, "%s%c%s", dialog->name, sepchar, path);
1061  (void)strncpy(path, s, SCIP_MAXSTRLEN);
1062  path[SCIP_MAXSTRLEN - 1] = '\0';
1063  dialog = dialog->parent;
1064  }
1065 }
1066 
1067 /** gets the command name of the dialog */
1068 const char* SCIPdialogGetName(
1069  SCIP_DIALOG* dialog /**< dialog */
1070  )
1071 {
1072  assert(dialog != NULL);
1073 
1074  return dialog->name;
1075 }
1076 
1077 /** gets the description of the dialog */
1078 const char* SCIPdialogGetDesc(
1079  SCIP_DIALOG* dialog /**< dialog */
1080  )
1081 {
1082  assert(dialog != NULL);
1083 
1084  return dialog->desc;
1085 }
1086 
1087 /** returns whether the dialog is a sub menu */
1089  SCIP_DIALOG* dialog /**< dialog */
1090  )
1091 {
1092  assert(dialog != NULL);
1093 
1094  return dialog->issubmenu;
1095 }
1096 
1097 /** gets the parent dialog of the given dialog */
1099  SCIP_DIALOG* dialog /**< dialog */
1100  )
1101 {
1102  assert(dialog != NULL);
1103 
1104  return dialog->parent;
1105 }
1106 
1107 /** gets the array of sub-dialogs associated with the given dialog */
1109  SCIP_DIALOG* dialog /**< dialog */
1110  )
1111 {
1112  assert(dialog != NULL);
1113 
1114  return dialog->subdialogs;
1115 }
1116 
1117 /** gets the number of sub-dialogs associated with the given dialog */
1119  SCIP_DIALOG* dialog /**< dialog */
1120  )
1121 {
1122  assert(dialog != NULL);
1123 
1124  return dialog->nsubdialogs;
1125 }
1126 
1127 /** gets the user defined data associated with the given dialog */
1129  SCIP_DIALOG* dialog /**< dialog */
1130  )
1131 {
1132  assert(dialog != NULL);
1133 
1134  return dialog->dialogdata;
1135 }
1136 
1137 /** sets user data of dialog; user has to free old data in advance! */
1139  SCIP_DIALOG* dialog, /**< dialog */
1140  SCIP_DIALOGDATA* dialogdata /**< new dialog user data */
1141  )
1142 {
1143  assert(dialog != NULL);
1144 
1145  dialog->dialogdata = dialogdata;
1146 }
const char * SCIPdialogGetName(SCIP_DIALOG *dialog)
Definition: dialog.c:1068
static SCIP_RETCODE dialogFree(SCIP *scip, SCIP_DIALOG **dialog)
Definition: dialog.c:753
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:122
SCIP_RETCODE SCIPdialogRelease(SCIP *scip, SCIP_DIALOG **dialog)
Definition: dialog.c:795
#define SCIP_DECL_DIALOGCOPY(x)
Definition: type_dialog.h:53
SCIP_RETCODE SCIPdialogExec(SCIP_DIALOG *dialog, SCIP_SET *set, SCIP_DIALOGHDLR *dialoghdlr, SCIP_DIALOG **nextdialog)
Definition: dialog.c:812
#define SCIP_MAXSTRLEN
Definition: def.h:196
#define NULL
Definition: lpi_spx.cpp:129
void SCIPdialogMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1222
const char * SCIPdialogGetDesc(SCIP_DIALOG *dialog)
Definition: dialog.c:1078
SCIP_RETCODE SCIPdialogDisplayCompletions(SCIP_DIALOG *dialog, SCIP *scip, const char *entryname)
Definition: dialog.c:1013
datastructures for user interface dialog
#define FALSE
Definition: def.h:52
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:7579
void SCIPdialogGetPath(SCIP_DIALOG *dialog, const char sepchar, char *path)
Definition: dialog.c:1044
#define TRUE
Definition: def.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4264
SCIP_LINELIST * nextline
Definition: struct_dialog.h:56
SCIP_RETCODE SCIPdialogDisplayMenuEntry(SCIP_DIALOG *dialog, SCIP *scip)
Definition: dialog.c:979
static void linelistFree(SCIP_LINELIST **linelist)
Definition: dialog.c:206
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:76
struct SCIP_DialogData SCIP_DIALOGDATA
Definition: type_dialog.h:42
static void linelistFreeAll(SCIP_LINELIST **linelist)
Definition: dialog.c:218
#define SCIPdebugMessage
Definition: pub_message.h:77
int SCIPdialogGetNSubdialogs(SCIP_DIALOG *dialog)
Definition: dialog.c:1118
SCIP_Bool SCIPdialoghdlrIsBufferEmpty(SCIP_DIALOGHDLR *dialoghdlr)
Definition: dialog.c:421
char * inputline
Definition: struct_dialog.h:55
#define BMSfreeMemory(ptr)
Definition: memory.h:117
static SCIP_RETCODE ensureSubdialogMem(SCIP_DIALOG *dialog, SCIP_SET *set, int num)
Definition: dialog.c:686
SCIP * scip
Definition: struct_set.h:58
void SCIPdialogCapture(SCIP_DIALOG *dialog)
Definition: dialog.c:785
#define SCIP_DECL_DIALOGDESC(x)
Definition: type_dialog.h:73
SCIP_Bool SCIPdialogIsSubmenu(SCIP_DIALOG *dialog)
Definition: dialog.c:1088
SCIP_DIALOGDATA * SCIPdialogGetData(SCIP_DIALOG *dialog)
Definition: dialog.c:1128
SCIP_RETCODE SCIPdialogDisplayMenu(SCIP_DIALOG *dialog, SCIP *scip)
Definition: dialog.c:945
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:120
SCIP_DIALOG * SCIPdialoghdlrGetRoot(SCIP_DIALOGHDLR *dialoghdlr)
Definition: dialog.c:400
SCIP_DIALOG ** subdialogs
Definition: struct_dialog.h:44
#define SCIPerrorMessage
Definition: pub_message.h:45
static SCIP_RETCODE addHistory(const char *s)
Definition: dialog.c:175
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:7551
SCIP_DIALOG * parent
Definition: struct_dialog.h:43
SCIP_RETCODE SCIPdialoghdlrCreate(SCIP_SET *set, SCIP_DIALOGHDLR **dialoghdlr)
Definition: dialog.c:303
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:258
SCIP_RETCODE SCIPdialoghdlrGetWord(SCIP_DIALOGHDLR *dialoghdlr, SCIP_DIALOG *dialog, const char *prompt, char **inputword, SCIP_Bool *endoffile)
Definition: dialog.c:434
SCIP_Bool issubmenu
Definition: struct_dialog.h:49
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:111
SCIP_LINELIST * inputlist
Definition: struct_dialog.h:63
int subdialogssize
Definition: struct_dialog.h:47
public data structures and miscellaneous methods
SCIP_RETCODE SCIPdialogCreate(SCIP_DIALOG **dialog, SCIP_DECL_DIALOGCOPY((*dialogcopy)), SCIP_DECL_DIALOGEXEC((*dialogexec)), SCIP_DECL_DIALOGDESC((*dialogdesc)), SCIP_DECL_DIALOGFREE((*dialogfree)), const char *name, const char *desc, SCIP_Bool issubmenu, SCIP_DIALOGDATA *dialogdata)
Definition: dialog.c:708
SCIP_DIALOGDATA * dialogdata
Definition: struct_dialog.h:45
internal methods for user interface dialog
#define SCIP_Bool
Definition: def.h:49
static int getHistoryLength(void)
Definition: dialog.c:185
SCIP_RETCODE SCIPsetIncludeExternalCode(SCIP_SET *set, const char *name, const char *description)
Definition: set.c:3819
static SCIP_DECL_SORTPTRCOMP(dialogComp)
Definition: dialog.c:831
SCIP_LINELIST ** inputlistptr
Definition: struct_dialog.h:64
SCIP_DIALOG ** SCIPdialogGetSubdialogs(SCIP_DIALOG *dialog)
Definition: dialog.c:1108
SCIP_RETCODE SCIPdialoghdlrSetRoot(SCIP *scip, SCIP_DIALOGHDLR *dialoghdlr, SCIP_DIALOG *dialog)
Definition: dialog.c:377
#define SCIP_DECL_DIALOGFREE(x)
Definition: type_dialog.h:61
void SCIPsortedvecInsertPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *keyval, int *len, int *pos)
SCIP_Bool SCIPdialogHasEntry(SCIP_DIALOG *dialog, const char *entryname)
Definition: dialog.c:868
#define SCIP_DECL_DIALOGEXEC(x)
Definition: type_dialog.h:87
SCIP_RETCODE SCIPdialogCopyInclude(SCIP_DIALOG *dialog, SCIP_SET *set)
Definition: dialog.c:285
SCIP_DIALOG * rootdialog
Definition: struct_dialog.h:62
void SCIPdialogSetData(SCIP_DIALOG *dialog, SCIP_DIALOGDATA *dialogdata)
Definition: dialog.c:1138
SCIP_RETCODE SCIPdialoghdlrAddHistory(SCIP_DIALOGHDLR *dialoghdlr, SCIP_DIALOG *dialog, const char *command, SCIP_Bool escapecommand)
Definition: dialog.c:609
static SCIP_RETCODE readLine(SCIP_DIALOGHDLR *dialoghdlr, const char *prompt, SCIP_Bool *endoffile)
Definition: dialog.c:134
static SCIP_RETCODE readInputLine(SCIP_DIALOGHDLR *dialoghdlr, const char *prompt, SCIP_Bool *endoffile)
Definition: dialog.c:236
int SCIPdialogFindEntry(SCIP_DIALOG *dialog, const char *entryname, SCIP_DIALOG **subdialog)
Definition: dialog.c:901
#define BMSallocMemory(ptr)
Definition: memory.h:92
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:80
SCIP_RETCODE SCIPdialogAddEntry(SCIP_DIALOG *dialog, SCIP_SET *set, SCIP_DIALOG *subdialog)
Definition: dialog.c:837
void SCIPdialoghdlrClearBuffer(SCIP_DIALOGHDLR *dialoghdlr)
Definition: dialog.c:410
SCIP_RETCODE SCIPdialoghdlrExec(SCIP_DIALOGHDLR *dialoghdlr, SCIP_SET *set)
Definition: dialog.c:349
common defines and data types used in all packages of SCIP
SCIP_RETCODE SCIPdialoghdlrAddInputLine(SCIP_DIALOGHDLR *dialoghdlr, const char *inputline)
Definition: dialog.c:585
SCIP_RETCODE SCIPdialoghdlrFree(SCIP *scip, SCIP_DIALOGHDLR **dialoghdlr)
Definition: dialog.c:333
#define SCIP_ALLOC(x)
Definition: def.h:269
static SCIP_RETCODE removeHistory(int pos)
Definition: dialog.c:194
SCIP callable library.
SCIP_DIALOG * SCIPdialogGetParent(SCIP_DIALOG *dialog)
Definition: dialog.c:1098
memory allocation routines