/* SCCS-info %W% %E% */ /*--------------------------------------------------------------------*/ /* */ /* VCG : Visualization of Compiler Graphs */ /* -------------------------------------- */ /* */ /* file: animation1.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 1 for VCG */ /* status: in work */ /* */ /*--------------------------------------------------------------------*/ /* $Id: animation1.c,v 1.6 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: animation1.c,v $ * Revision 1.6 1995/02/08 11:21:41 sander * Distribution Version 1.3 * * 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 touches the file, if it is ready with displaying, * thus the client waits for a change of the time stamp of the * file. *--------------------------------------------------------------------*/ #include #include #include #include #include #include #include "../src/globals.h" /* Prototypes * ---------- */ void main _PP((void)); void call_vcg _PP((void)); void signal_vcg _PP((int k)); void wait_for_vcg _PP((void)); void get_time _PP((char *fn)); 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[] = "animfile1.vcg"; /*--------------------------------------------------------------------*/ /* 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 calls of get_time and wait_for_vcg * are used for time synchronisation. */ #ifdef ANSI_C void main(void) #else void main() #endif { int i,x,y; x = 20; y = 20; create_graph(x,y); get_time(filename); call_vcg(); wait_for_vcg(); for (i=0; i<4; i++) { x = x + 40; create_graph(x,y); get_time(filename); signal_vcg(- SIGUSR1); /* reload file */ wait_for_vcg(); } for (i=0; i<4; i++) { y = y + 40; create_graph(x,y); get_time(filename); signal_vcg(- SIGUSR1); /* reload file */ wait_for_vcg(); } for (i=0; i<4; i++) { x = x - 40; create_graph(x,y); get_time(filename); signal_vcg(- SIGUSR1); /* reload file */ wait_for_vcg(); } for (i=0; i<4; i++) { y = y - 40; create_graph(x,y); get_time(filename); signal_vcg(- SIGUSR1); /* reload file */ wait_for_vcg(); } signal_vcg(- SIGUSR2); /* close vcg (does not work with X11) */ sleep(3); signal_vcg(- SIGQUIT); /* exit vcg */ } /*--------------------------------------------------------------------*/ /* 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 { FILE *f; 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); } /* Wait until a new time stamp * --------------------------- * The file containing the graph specification is touched after * loading it. Thus we wait for a new time stamp of the file, * that indicates that the loading is finished. */ time_t file_touch_time1, file_touch_time2; /* time stamps */ #ifdef ANSI_C void wait_for_vcg(void) #else void wait_for_vcg() #endif { int i; i = 0; /* Wait maximal 60 seconds */ while (i<60) { file_touch_time2 = file_touch_time1; get_time(filename); sleep(1); /* 1 seconds */ if (file_touch_time1!=file_touch_time2) { return; } i++; } FPRINTF(stderr,"Timeout\n"); exit(-1); } /* get the touch-time of a file named fn * ------------------------------------- */ #ifdef ANSI_C void get_time(char *fn) #else void get_time(fn) char *fn; #endif { struct stat file_stat; if (!stat(fn,&file_stat)) file_touch_time1 = file_stat.st_mtime; else { FPRINTF(stderr,"Cannot get time of %s\n", filename); exit(-1); } } /*--------------------------------------------------------------------*/ /* 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)); fsync(fileno(f)); fsync(fileno(f)); 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"); } /*--------------------------------------------------------------------*/