/* SCCS-info %W% %E% */ /*--------------------------------------------------------------------*/ /* */ /* VCG : Visualization of Compiler Graphs */ /* -------------------------------------- */ /* */ /* file: animation2.c */ /* version: 1.00.00 */ /* creation: 12.11.93 */ /* author: G. Sander (Version 1.00.00-...) */ /* Universitaet des Saarlandes, 66041 Saarbruecken */ /* ESPRIT Project #5399 Compare */ /* description: Animation demo 2 for VCG */ /* status: in work */ /* */ /*--------------------------------------------------------------------*/ /* $Id: animation2.c,v 1.7 1995/02/08 11:21:41 sander Exp $ */ /* * Copyright (C) 1993-2005 Saarland University * * This program and documentation is free software; you can redistribute * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * The software is available per anonymous ftp at ftp.cs.uni-sb.de. * Contact sander@cs.uni-sb.de for additional information. */ /* $Log: animation2.c,v $ * Revision 1.7 1995/02/08 11:21:41 sander * Distribution Version 1.3 * * Revision 1.6 1994/03/04 20:03:15 sander * Small bug "-a 1" should be "-a -1" in call of vcg. * * Revision 1.5 1994/03/02 14:29:05 sander * Gnu License message added. * Call of VCG improved by first looking for local vcg's. * * Revision 1.4 1994/01/21 20:05:00 sander * Signal handling adapted for Sys V. * Some portability problems solved for Silicon Graphics IRIS and IBM R6000. * * Revision 1.3 1994/01/05 20:07:42 sander * X11 bug: open xvcg with -geometry, fixed * * Revision 1.2 1994/01/03 17:43:24 sander * Remarks added. * * Revision 1.1 1993/12/06 11:23:59 sander * Initial revision * */ /*--------------------------------------------------------------------* * This is a small example how to program a animation. The protocol * used here is the following: * * The client (this program) sends signals to the server (VCG) when * the server should display the graph. * The server send a signal SIGUSR1 back to the client, when it is * ready with displaying. Thus the server need not the have write * access to the file. *--------------------------------------------------------------------*/ #include #include #include #include #include "../src/globals.h" /* Prototypes * ---------- */ void main _PP((void)); void next_state _PP((void)); void call_vcg _PP((void)); void signal_vcg _PP((int k)); void set_signal _PP((void)); int signal_handler _PP((int signl)); void create_graph _PP((int x,int y)); void open_graph _PP((void)); void close_graph _PP((void)); void create_node _PP((char *title,int x,int y)); void create_edge _PP((char *so,char *ta)); char *get_color _PP((void)); /* This must be an absolute path to the vcg-tool ! * No ~, .. or similar trash allowed. */ #ifndef VCGCALL #define VCGCALL "/RW/esprit/users/sander/ABC/vcg" #endif #ifndef VCGTOOL #define VCGTOOL "vcg" #endif /* Global Variables * ---------------- */ FILE *f = NULL; char filename[] = "animfile2.vcg"; /* Flag, indicates that the animation is still ongoing and that * we should wait for the next signal. */ int not_ready; /* Counter, indicates which instance of the graph should be generated. */ int act_state; /*--------------------------------------------------------------------*/ /* Main Routine * ------------ * The main program consists of a small sequence of pictures. * Each picture is generated by create_graph and reloaded into * the vcg by signal_vcg. The problem with synchronizing by * signals is, that we cannot write down the animation process * in a sequential manner. Each time a synchronizing signal * comes in, we have to generate a new state of the graph * and signal this to vcg, i.e. the process is event driven. * Pause causes the driver program to sleep until the next signal * event comes in. */ #ifdef ANSI_C void main(void) #else void main() #endif { set_signal(); create_graph(20,20); call_vcg(); not_ready = 1; act_state = 0; while (not_ready) pause(); /* wait for signal */ signal_vcg(- SIGUSR2); /* close vcg (does not work with X11 */ pause(); /* wait for signal */ sleep(3); signal_vcg(- SIGQUIT); /* exit vcg */ } /* Create the next state of the graph * ---------------------------------- */ #ifdef ANSI_C void next_state(void) #else void next_state() #endif { act_state++; if (act_state > 12) { not_ready=0; return; } if (act_state > 6) create_graph(20+(12-act_state)*40,20); else create_graph(20+act_state*40,20); sleep(1); signal_vcg(- SIGUSR1); /* reload file */ } /*--------------------------------------------------------------------*/ /* Communication with vcg */ /*--------------------------------------------------------------------*/ /* Call the vcg-tool * ----------------- * Calling means fork a child process that is the vcg-tool. */ int pid; /* Process Id of the vcg process */ #ifdef ANSI_C void call_vcg(void) #else void call_vcg() #endif { pid = fork(); switch (pid) { case -1: /* this is an error */ FPRINTF(stderr,"Cannot fork process vcg\n"); exit(-1); /* NEVER REACHED */ case 0: /* this is the child process: call vcg */ { char toolname[1024]; strcpy(toolname,"../src/"); strcat(toolname,VCGTOOL); if ((f = fopen(toolname,"r")) != NULL) { fclose(f); } else if ((f = fopen(VCGCALL,"r")) != NULL) { fclose(f); strcpy(toolname,VCGCALL); } else strcpy(toolname,VCGTOOL); PRINTF("Call %s\n",toolname); execl(toolname,toolname, "-a","-1", #ifdef X11 "-geometry","200x200-30+30", #endif filename,0L); } /* NEVER REACHED */ default: /* this is the father process: */ /* pid is now the ID of the child process */ ; } } /* Send a signal to the vcg-tool * ----------------------------- */ char cmdline[1024]; /* Buffer for the kill-command */ #ifdef ANSI_C void signal_vcg(int k) #else void signal_vcg(k) int k; #endif { SPRINTF(cmdline,"kill %d %d \n",k,pid); system(cmdline); } /*--------------------------------------------------------------------*/ /* Signal handling */ /*--------------------------------------------------------------------*/ /* * Initialisation of Signal Handler * -------------------------------- * This has to be done before the first signal is recognized. */ #ifdef ANSI_C void set_signal(void) #else void set_signal() #endif { if ( (int)signal(SIGUSR1,(void (*)())signal_handler) == -1 ) { FPRINTF(stderr,"Can't set USR1 process signal.\n"); exit(-1); } } /* * Signal Handler for Signal USR1 * ------------------------------ */ #ifdef ANSI_C int signal_handler(int signl) #else int signal_handler(signl) int signl; #endif { set_signal(); next_state(); return(0); } /*--------------------------------------------------------------------*/ /* Create an instance of the graph */ /*--------------------------------------------------------------------*/ /* Write a graph to the file * ------------------------- * After writing, we synchronize the file system to be sure that * writing is finished before the vcg starts loading. * Our simple graph consists of two nodes titled `A' and `B'. * The position of node `A' is fixed, but the position of node * `B' depends on x,y of this graph instance. */ #ifdef ANSI_C void create_graph(int x,int y) #else void create_graph(x,y) int x, y; #endif { f = fopen(filename,"w"); if (!f) return; open_graph(); create_node("A",100,100); create_node("B",x,y); create_edge("A","B"); close_graph(); fsync(fileno(f)); /* Assert that the file is written */ if (f) fclose(f); } /* Sequence to start a graph * ------------------------- */ #ifdef ANSI_C void open_graph(void) #else void open_graph() #endif { FPRINTF(f,"graph: { title:\"test\"\n"); FPRINTF(f," x: 30 y: 30\n"); FPRINTF(f," xmax: 300 ymax: 300\n"); FPRINTF(f," display_edge_labels: yes\n"); } /* Sequence to complete a graph * ---------------------------- */ #ifdef ANSI_C void close_graph(void) #else void close_graph() #endif { FPRINTF(f,"}\n"); } /* Write a node of title `title' and position `x',`y' to the file * -------------------------------------------------------------- */ #ifdef ANSI_C void create_node(char *title,int x,int y) #else void create_node(title,x,y) char *title; int x,y; #endif { FPRINTF(f," node: { title: \"%s\" label: \"%s\" ", title, title); FPRINTF(f,"loc: { x: %d y: %d } ", x, y); FPRINTF(f,"color: %s ",get_color()); FPRINTF(f,"textcolor: %s ",get_color()); FPRINTF(f,"bordercolor: %s ",get_color()); FPRINTF(f,"}\n"); } /* Write an edge * ------------- * between nodes of sourcetitle `so' and targettitle `ta'. */ #ifdef ANSI_C void create_edge(char *so,char *ta) #else void create_edge(so,ta) char *so,*ta; #endif { FPRINTF(f," edge: { sourcename: \"%s\" targetname: \"%s\" ", so, ta); FPRINTF(f,"label: \"demo\" "); FPRINTF(f,"color: %s ",get_color()); FPRINTF(f,"class: 1 "); FPRINTF(f,"}\n"); } /* Get an arbitrary color * ---------------------- * Colors except white are returned. * Consecutive calls of this function will return different colors. */ int color_cntr = 0; #ifdef ANSI_C char *get_color(void) #else char *get_color() #endif { color_cntr++; if (color_cntr>30) color_cntr = 0; switch (color_cntr) { case 0: return("blue"); case 1: return("red"); case 2: return("green"); case 3: return("yellow"); case 4: return("magenta"); case 5: return("cyan"); case 6: return("darkgrey"); case 7: return("darkblue"); case 8: return("darkred"); case 9: return("darkgreen"); case 10: return("darkyellow"); case 11: return("darkmagenta"); case 12: return("darkcyan"); case 13: return("gold"); case 14: return("lightgrey"); case 15: return("lightblue"); case 16: return("lightred"); case 17: return("lightgreen"); case 18: return("lightyellow"); case 19: return("lightmagenta"); case 20: return("lightcyan"); case 21: return("lilac"); case 22: return("turquoise"); case 23: return("aquamarine"); case 24: return("khaki"); case 25: return("purple"); case 26: return("yellowgreen"); case 27: return("pink"); case 28: return("orange"); case 29: return("orchid"); } return("black"); } /*--------------------------------------------------------------------*/