1 /* blisstog.c  version 1.0; B D McKay, Sep 2012. */
2 
3 #define USAGE "blisstog [-n#:#] [infile]*"
4 
5 #define HELPTEXT \
6 " Read files of graphs in Bliss (Dimacs) format and write\n\
7   them to stdout in sparse6 format.\n\
8 \n\
9   -n#:#  Specify a range of n values for output\n\
10   Input files with name *.gz are ungzipped\n"
11 
12 #define ZCAT "gunzip -c"  /* name of zcat command (might be "gunzip -c") */
13 
14 /*************************************************************************/
15 
16 #include "gtools.h"
17 
18 typedef struct
19 {
20    int v,w;
21 } vpair;
22 
23 static int
nextchar(FILE * f)24 nextchar(FILE *f)
25 {
26     char s[2];
27 
28     if (fscanf(f,"%1s",s) != 1) return EOF;
29     else                        return s[0];
30 }
31 
32 static boolean
readblissgraph(FILE * f,sparsegraph * g)33 readblissgraph(FILE *f, sparsegraph *g)
34 /* Reads a graph from Bliss format into a sparse graph */
35 {
36     int n,c;
37     unsigned long ne,j;
38     int haven;
39     int i,v,w;
40     int haveptn;
41     DYNALLSTAT(vpair,elist,elist_sz);
42 
43     haven = 0;
44     j = 0;
45     while ((c = nextchar(f)) >= 0)
46     {
47 	switch (c)
48 	{
49 	case 'c':
50 	    while ((c = getc(f)) != '\n' && c != EOF) {}
51 	    break;
52 
53 	case 'p':
54 	    if (haven)
55 	    {
56 		fprintf(stderr,"Duplicate p line\n");
57 		exit(1);
58 	    }
59 	    if (fscanf(f," edge %d %lu",&n,&ne) != 2)
60 	    {
61 		fprintf(stderr,"Bad p line\n");
62 		return FALSE;
63 	    }
64 	    haven = 1;
65             DYNALLOC1(vpair,elist,elist_sz,ne,"Alloc vpair");
66 	    break;
67 
68 	case 'n':
69 	    if (!haven)
70 	    {
71                 fprintf(stderr,"Missing p line\n");
72                 return FALSE;
73             }
74             if (fscanf(f,"%d%d",&w,&v) != 2 || w < 1 || w > n)
75             {
76                 fprintf(stderr,"Bad n line\n");
77                 return FALSE;
78             }
79 	    break;
80 
81 	case 'e':
82 	    if (!haven || j == ne)
83 	    {
84 		fprintf(stderr,"Missing p line or too many e lines\n");
85 		return FALSE;
86 	    }
87 	    if (fscanf(f,"%d%d",&v,&w) != 2 || v < 1 || w < 1 || v > n || w > n)
88 	    {
89 		fprintf(stderr,"Bad e line\n");
90 		return FALSE;
91 	    }
92 	    elist[j].v = v-1; elist[j].w = w-1;
93 	    ++j;
94 	    break;
95 
96 	default:
97 	    fprintf(stderr,"Unknown line %c\n",c);
98 	    return FALSE;
99 	}
100     }
101 
102     if (j != ne)
103     {
104         fprintf(stderr,"Wrong number of e lines\n");
105         exit(1);
106     }
107 
108     SG_ALLOC(*g,n,2*ne,"SG_ALLOC");
109     g->nv = n;
110     g->nde = 2*ne;
111 
112     for (i = 0; i < n; ++i) g->d[i] = 0;
113     for (j = 0; j < ne; ++j)
114     {
115 	++(g->d[elist[j].v]);
116 	++(g->d[elist[j].w]);
117     }
118     g->v[0] = 0;
119     for (i = 1; i < n; ++i) g->v[i] = g->v[i-1] + g->d[i-1];
120     for (i = 0; i < n; ++i) g->d[i] = 0;
121 
122     for (j = 0; j < ne; ++j)
123     {
124 	v = elist[j].v;
125 	w = elist[j].w;
126         g->e[g->v[v]+(g->d[v])++] = w;
127         g->e[g->v[w]+(g->d[w])++] = v;
128     }
129 
130     return TRUE;
131 }
132 
133 /**************************************************************************/
134 
135 int
main(int argc,char * argv[])136 main(int argc, char *argv[])
137 {
138     FILE *infile;
139     int j,firstarg;
140     SG_DECL(g);
141     size_t flen;
142     boolean ispipe;
143     int nmin,nmax;
144     char zcmd[515];
145 
146     HELP; PUTVERSION;
147 
148     nmax = -1;
149     if (argc >= 2 && argv[1][0] == '-' && argv[1][1] == 'n')
150     {
151 	if (sscanf(argv[1]+2,"%d:%d",&nmin,&nmax) == 2) {}
152         else if (sscanf(argv[1]+2,":%d",&nmax) == 1) { nmin = 1; }
153         else if (sscanf(argv[1]+2,"%d:",&nmin) == 1) { nmax = NAUTY_INFINITY; }
154         else  gt_abort(">E blisstog: bad -n switch\n");
155 
156 	firstarg = 2;
157     }
158     else
159 	firstarg = 1;
160 
161     if (argc == firstarg)
162     {
163 	if (!readblissgraph(stdin,&g))
164 	{
165 	    fprintf(stderr,">E Bliss error in file %s\n","stdin");
166 	    gt_abort(NULL);
167 	}
168 	else
169 	    writes6_sg(stdout,&g);
170     }
171     else
172     {
173         for (j = firstarg; j < argc; ++j)
174 	{
175 	    flen = strlen(argv[j]);
176             if (flen >= 3 && strcmp(argv[j]+flen-3,".gz") == 0)
177             {
178                 sprintf(zcmd,"%s \"%s\"",ZCAT,argv[j]);
179                 if ((infile = popen(zcmd,"r")) == NULL)
180                 {
181                     fprintf(stderr,
182                          ">E blisstog: cannot open zcat pipe for \"%s\"\n",
183                          argv[j]);
184                     gt_abort(NULL);
185                 }
186 		ispipe = TRUE;
187             }
188             else
189             {
190 	        if ((infile = fopen(argv[j],"r")) == NULL)
191 	        {
192 	            fprintf(stderr,">E Can't open file %s\n",argv[j]);
193 		    gt_abort(NULL);
194 	        }
195 		ispipe = FALSE;
196 	    }
197 
198 	    if (!readblissgraph(infile,&g))
199 	    {
200 	        fprintf(stderr,">E Bliss error in file %s\n",argv[j]);
201 		gt_abort(NULL);
202 	    }
203 	    else if (nmax < 0 || (g.nv >= nmin && g.nv <= nmax))
204             {
205 		sortlists_sg(&g);
206 	        writes6_sg(stdout,&g);
207 	    }
208 
209 	    if (ispipe) pclose(infile); else fclose(infile);
210         }
211     }
212 
213     exit(0);
214 }
215