Crossings Minimization  1.0
dot.c
Go to the documentation of this file.
1 /**
2  * @file dot.cxx
3  * @brief
4  * Module for reading files in .dot format
5  * @author Matt Stallmann
6  * @date 1998/07/17, adapted for new Crossings experiments, 2008/12/17
7  * @compile test program: gcc -g -Wall dot.c -o test_dot
8  * $Id: dot.c 2 2011-06-07 19:50:41Z mfms $
9  */
10 
11 // Copyright (C) 2008 Matthias Stallmann.
12 // Contact: matt_stallmann@ncsu.edu
13 //
14 // This program is free software; you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation; either version 2 of the License, or
17 // (at your option) any later version.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License along
25 // with this program (file COPYING.txt); if not, write to the Free Software
26 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
27 // USA.
28 
29 #include<stdlib.h> // abort()
30 #include<stdio.h>
31 #include<string.h>
32 #include<assert.h>
33 #include<ctype.h>
34 
35 #include"dot.h"
36 #include"defs.h"
37 
38 #define MAX_MSG_LENGTH 512
39 #define MAX_NAME_LENGTH 512
40 
43 static int line_number = 1;
44 
45 /* ----------- UTILITY FUNCTIONS -------------- */
46 
47 /**
48  * Prints the message in 'error_message' with the line number
49  * @param fatal if true, program will exit (fatal error)
50  */
51 static void error( bool fatal )
52 {
53  fprintf( stderr, "Line %d: %s\n", line_number, error_message );
54  if( fatal ) exit( EXIT_FAILURE );
55 }
56 
57 /**
58  * Skips blanks and comments in the input stream using a finite-state
59  * machine. Also updates the line number when appropriate.
60  * @param ch the starting character for the sequence, as provided by the
61  * client
62  * @return the character that ends the sequence of blanks and comments, to be
63  * used by the client
64  */
65 static int skip_blanks_and_comments( int ch, FILE * in_stream )
66 {
67  enum state_type { BLANK, C_COMMENT, CPP_COMMENT, SLASH, STAR } state = BLANK;
68 #ifdef DEBUG
69  printf( "-> skip_blanks_and_comments, ch = %d\n", ch );
70 #endif
71  bool done = false;
72  while( ! done )
73  {
74  switch( ch ) {
75  case '\n':
76  line_number++;
77  if( state == CPP_COMMENT ) { state = BLANK; break; }
78  case ' ': case '\t': case '\r':
79  if( state == SLASH )
80  {
81  // the slash was not the beginning of a comment and therefore ends
82  // the sequence
83  ungetc( ch, in_stream );
84  ch = '/';
85  done = true;
86  }
87  else if( state == STAR ) state = C_COMMENT;
88  break;
89  case '/':
90  if( state == BLANK ) state = SLASH;
91  else if( state == SLASH ) state = CPP_COMMENT;
92  else if( state == STAR ) state = BLANK;
93  break;
94  case '*':
95  if( state == C_COMMENT ) state = STAR;
96  else if( state == SLASH ) state = C_COMMENT;
97  else if( state == STAR ) state = C_COMMENT;
98  else if( state == BLANK ) done = true;
99  break;
100  case EOF:
101  done = true;
102  default:
103  if( state == SLASH )
104  {
105  // the slash was not the beginning of a comment and therefore ends
106  // the sequence
107  ungetc( ch, in_stream );
108  ch = '/';
109  done = true;
110  }
111  else if( state == STAR ) state = C_COMMENT;
112  else if( state == BLANK ) done = true;
113  break;
114  } // end, switch
115 #ifdef DEBUG
116  printf( " skipping, ch = %d, state = %d\n", ch, state );
117 #endif
118  if( ! done ) ch = getc( in_stream );
119  } // end, infinite loop
120 #ifdef DEBUG
121  printf( "<- skip_blanks_and_comments, ch = %d\n", ch );
122 #endif
123  return ch;
124 }
125 
126 /**
127  * Reads an identifier from the input stream into the buffer
128  * @param ch the beginning of the identifier
129  * @return the character after the identifier
130  */
131 static char read_identifier( int ch, FILE * in, char * id_buf )
132 {
133  int index = 0;
134  while( isalnum( ch ) || ch == '_' ) {
135  id_buf[ index++ ] = ch;
136  ch = getc( in );
137  }
138  id_buf[index] = '\0';
139  return ch;
140 }
141 
142 /* ----------- INPUT FUNCTIONS -------------- */
143 
144 void initDot( FILE * in )
145 {
146  int ch = getc( in );
147  ch = skip_blanks_and_comments( ch, in );
148  /** @todo eventually will want to pick up the first comment */
149  ungetc( ch, in );
150  char digraph[MAX_NAME_LENGTH];
151  fscanf( in, "%s", digraph );
152  if( strcmp( digraph, "digraph" ) != 0 )
153  {
154  sprintf( error_message, "expected 'digraph', got '%s'", digraph );
155  error( true );
156  }
157  fscanf( in, "%s", graph_name );
158  ch = getc( in );
159  ch = skip_blanks_and_comments( ch, in );
160  if( ch != '{' )
161  {
162  sprintf( error_message, "expected '{', got %c", ch );
163  error( true );
164  }
165 }
166 
168 {
169  strcpy( buffer, graph_name );
170 }
171 
172 bool nextEdge( FILE * in, char * src_buf, char * dst_buf )
173 {
174  char ch = getc( in );
175  ch = skip_blanks_and_comments( ch, in );
176  if( ch == EOF || ch == '}' ) return false;
177  ch = read_identifier( ch, in, src_buf );
178  if( ch == EOF )
179  {
180  sprintf( error_message, "premature end of file" );
181  error( true );
182  }
183  ch = skip_blanks_and_comments( ch, in );
184  int dash = ch;
185  int arrow_head = getc( in );
186  if( dash != '-' || arrow_head != '>' )
187  {
188  sprintf( error_message, "expected '->', got '%c%c'", dash, arrow_head );
189  error( true );
190  }
191  ch = getc( in );
192  ch = skip_blanks_and_comments( ch, in );
193  ch = read_identifier( ch, in, dst_buf );
194  if( ch == EOF )
195  {
196  sprintf( error_message, "premature end of file" );
197  error( true );
198  }
199  ch = skip_blanks_and_comments( ch, in );
200  if( ch != ';' )
201  {
202  sprintf( error_message, "expected ';', got '%c'", ch );
203  error( true );
204  }
205  return true;
206 }
207 
208 /* ----------- OUTPUT FUNCTIONS -------------- */
209 
210 void dotPreamble( FILE * out, const char * graph_name,
211  const char * seed_info )
212 {
213  fprintf( out, "/* %s */\n", seed_info );
214  fprintf( out, "digraph %s {\n", graph_name );
215 }
216 
217 void endDot( FILE * out )
218 {
219  fprintf( out, "}\n" );
220 }
221 
222 void outputEdge( FILE * out, const char * src_name,
223  const char * dst_name )
224 {
225  fprintf( out, " %s -> %s;\n", src_name, dst_name );
226 }
227 
228 #ifdef TEST
229 
230 /**
231  * Test program: reads a dot file from standard input and sends it to
232  * standard output.
233  */
234 static void test_dot()
235 {
236  initDot( stdin );
237  char name_buf[100];
238  getName( name_buf );
239  fprintf( stderr, "name = %s\n", name_buf );
240  dotPreamble( stdout, name_buf, "seed" );
241  char src_buf[100];
242  char dst_buf[100];
243  while ( nextEdge( stdin, src_buf, dst_buf ) ) {
244  fprintf( stderr, "src = %s, dst = %s\n", src_buf, dst_buf );
245  outputEdge( stdout, src_buf, dst_buf );
246  }
247  endDot( stdout );
248 }
249 
250 int main()
251 {
252  test_dot();
253  return 0;
254 }
255 
256 #endif
257 
258 /* [Last modified: 2011 04 19 at 20:48:01 GMT] */
void outputEdge(FILE *out, const char *src_name, const char *dst_name)
Definition: dot.c:222
void dotPreamble(FILE *out, const char *graph_name, const char *seed_info)
Definition: dot.c:210
static char error_message[MAX_MSG_LENGTH]
Definition: dot.c:41
void endDot(FILE *out)
Definition: dot.c:217
static char buffer[MAX_NAME_LENGTH]
Definition: heuristics.c:59
#define MAX_NAME_LENGTH
Definition: dot.c:39
Definitions common to all edge crossing heuristic source files.
static enum @0 state
static int skip_blanks_and_comments(int ch, FILE *in_stream)
Definition: dot.c:65
Module for reading files in .dot format.
static int line_number
Definition: dot.c:43
static void error(bool fatal)
Definition: dot.c:51
static char graph_name[MAX_NAME_LENGTH]
Definition: dot.c:42
static char read_identifier(int ch, FILE *in, char *id_buf)
Definition: dot.c:131
bool nextEdge(FILE *in, char *src_buf, char *dst_buf)
Definition: dot.c:172
#define MAX_MSG_LENGTH
Definition: dot.c:38
void initDot(FILE *in)
Definition: dot.c:144
void getNameFromDotFile(char *buffer)
Definition: dot.c:167
int main(int argc, char *argv[])
Definition: add_edges.c:185