~ubuntu-branches/ubuntu/precise/graphviz/precise-security

« back to all changes in this revision

Viewing changes to cmd/tools/mmio.c

  • Committer: Bazaar Package Importer
  • Author(s): David Claughton
  • Date: 2010-03-24 22:45:18 UTC
  • mfrom: (1.2.7 upstream) (6.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100324224518-do441tthbqjaqjzd
Tags: 2.26.3-4
Add patch to fix segfault in circo. Backported from upstream snapshot
release.  Thanks to Francis Russell for his work on this.
(Closes: #575255)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: mmio.c,v 1.6 2009/06/03 01:56:55 ellson Exp $Revision:  */
 
2
/* vim:set shiftwidth=4 ts=8: */
 
3
 
 
4
/**********************************************************
 
5
*      This software is part of the graphviz package      *
 
6
*                http://www.graphviz.org/                 *
 
7
*                                                         *
 
8
*            Copyright (c) 1994-2004 AT&T Corp.           *
 
9
*                and is licensed under the                *
 
10
*            Common Public License, Version 1.0           *
 
11
*                      by AT&T Corp.                      *
 
12
*                                                         *
 
13
*        Information and Software Systems Research        *
 
14
*              AT&T Research, Florham Park NJ             *
 
15
**********************************************************/
 
16
/* 
 
17
*   Matrix Market I/O library for ANSI C
 
18
*
 
19
*   See http://math.nist.gov/MatrixMarket for details.
 
20
*
 
21
*
 
22
*/
 
23
 
 
24
 
 
25
#include <stdio.h>
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
#include <ctype.h>
 
29
 
 
30
#include "mmio.h"
 
31
 
 
32
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_,
 
33
                               int *nz_, double **val_, int **I_, int **J_)
 
34
{
 
35
    FILE *f;
 
36
    MM_typecode matcode;
 
37
    int M, N, nz;
 
38
    int i;
 
39
    double *val;
 
40
    int *I, *J;
 
41
 
 
42
    if ((f = fopen(fname, "r")) == NULL)
 
43
        return -1;
 
44
 
 
45
 
 
46
    if (mm_read_banner(f, &matcode) != 0) {
 
47
        fprintf(stderr,
 
48
                "mm_read_unsymetric: Could not process Matrix Market banner ");
 
49
        fprintf(stderr, " in file [%s]\n", fname);
 
50
        return -1;
 
51
    }
 
52
 
 
53
 
 
54
 
 
55
    if (!(mm_is_real(matcode) && mm_is_matrix(matcode) &&
 
56
          mm_is_sparse(matcode))) {
 
57
        fprintf(stderr, "Sorry, this application does not support ");
 
58
        fprintf(stderr, "Market Market type: [%s]\n",
 
59
                mm_typecode_to_str(matcode));
 
60
        return -1;
 
61
    }
 
62
 
 
63
    /* find out size of sparse matrix: M, N, nz .... */
 
64
 
 
65
    if (mm_read_mtx_crd_size(f, &M, &N, &nz) != 0) {
 
66
        fprintf(stderr,
 
67
                "read_unsymmetric_sparse(): could not parse matrix size.\n");
 
68
        return -1;
 
69
    }
 
70
 
 
71
    *M_ = M;
 
72
    *N_ = N;
 
73
    *nz_ = nz;
 
74
 
 
75
    /* reseve memory for matrices */
 
76
 
 
77
    I = (int *) malloc(nz * sizeof(int));
 
78
    J = (int *) malloc(nz * sizeof(int));
 
79
    val = (double *) malloc(nz * sizeof(double));
 
80
 
 
81
    *val_ = val;
 
82
    *I_ = I;
 
83
    *J_ = J;
 
84
 
 
85
    /* NOTE: when reading in doubles, ANSI C requires the use of the "l"  */
 
86
    /*   specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
 
87
    /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */
 
88
 
 
89
    for (i = 0; i < nz; i++) {
 
90
        fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
 
91
        I[i]--;                 /* adjust from 1-based to 0-based */
 
92
        J[i]--;
 
93
    }
 
94
    fclose(f);
 
95
 
 
96
    return 0;
 
97
}
 
98
 
 
99
int mm_is_valid(MM_typecode matcode)
 
100
{
 
101
    if (!mm_is_matrix(matcode))
 
102
        return 0;
 
103
    if (mm_is_dense(matcode) && mm_is_pattern(matcode))
 
104
        return 0;
 
105
    if (mm_is_real(matcode) && mm_is_hermitian(matcode))
 
106
        return 0;
 
107
    if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||
 
108
                                   mm_is_skew(matcode)))
 
109
        return 0;
 
110
    return 1;
 
111
}
 
112
 
 
113
int mm_read_banner(FILE * f, MM_typecode * matcode)
 
114
{
 
115
    char line[MM_MAX_LINE_LENGTH];
 
116
    char banner[MM_MAX_TOKEN_LENGTH];
 
117
    char mtx[MM_MAX_TOKEN_LENGTH];
 
118
    char crd[MM_MAX_TOKEN_LENGTH];
 
119
    char data_type[MM_MAX_TOKEN_LENGTH];
 
120
    char storage_scheme[MM_MAX_TOKEN_LENGTH];
 
121
    char *p;
 
122
 
 
123
 
 
124
    mm_clear_typecode(matcode);
 
125
 
 
126
    if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
 
127
        return MM_PREMATURE_EOF;
 
128
 
 
129
    if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,
 
130
               storage_scheme) != 5)
 
131
        return MM_PREMATURE_EOF;
 
132
 
 
133
    for (p = mtx; *p != '\0'; *p = tolower(*p), p++);   /* convert to lower case */
 
134
    for (p = crd; *p != '\0'; *p = tolower(*p), p++);
 
135
    for (p = data_type; *p != '\0'; *p = tolower(*p), p++);
 
136
    for (p = storage_scheme; *p != '\0'; *p = tolower(*p), p++);
 
137
 
 
138
    /* check for banner */
 
139
    if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) !=
 
140
        0)
 
141
        return MM_NO_HEADER;
 
142
 
 
143
    /* first field should be "mtx" */
 
144
    if (strcmp(mtx, MM_MTX_STR) != 0)
 
145
        return MM_UNSUPPORTED_TYPE;
 
146
    mm_set_matrix(matcode);
 
147
 
 
148
 
 
149
    /* second field describes whether this is a sparse matrix (in coordinate
 
150
       storgae) or a dense array */
 
151
 
 
152
 
 
153
    if (strcmp(crd, MM_SPARSE_STR) == 0)
 
154
        mm_set_sparse(matcode);
 
155
    else if (strcmp(crd, MM_DENSE_STR) == 0)
 
156
        mm_set_dense(matcode);
 
157
    else
 
158
        return MM_UNSUPPORTED_TYPE;
 
159
 
 
160
 
 
161
    /* third field */
 
162
 
 
163
    if (strcmp(data_type, MM_REAL_STR) == 0)
 
164
        mm_set_real(matcode);
 
165
    else if (strcmp(data_type, MM_COMPLEX_STR) == 0)
 
166
        mm_set_complex(matcode);
 
167
    else if (strcmp(data_type, MM_PATTERN_STR) == 0)
 
168
        mm_set_pattern(matcode);
 
169
    else if (strcmp(data_type, MM_INT_STR) == 0)
 
170
        mm_set_integer(matcode);
 
171
    else
 
172
        return MM_UNSUPPORTED_TYPE;
 
173
 
 
174
 
 
175
    /* fourth field */
 
176
 
 
177
    if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
 
178
        mm_set_general(matcode);
 
179
    else if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
 
180
        mm_set_symmetric(matcode);
 
181
    else if (strcmp(storage_scheme, MM_HERM_STR) == 0)
 
182
        mm_set_hermitian(matcode);
 
183
    else if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
 
184
        mm_set_skew(matcode);
 
185
    else
 
186
        return MM_UNSUPPORTED_TYPE;
 
187
 
 
188
 
 
189
    return 0;
 
190
}
 
191
 
 
192
int mm_write_mtx_crd_size(FILE * f, int M, int N, int nz)
 
193
{
 
194
    if (fprintf(f, "%d %d %d\n", M, N, nz) != 3)
 
195
        return MM_COULD_NOT_WRITE_FILE;
 
196
    else
 
197
        return 0;
 
198
}
 
199
 
 
200
int mm_read_mtx_crd_size(FILE * f, int *M, int *N, int *nz)
 
201
{
 
202
    char line[MM_MAX_LINE_LENGTH];
 
203
    int num_items_read;
 
204
 
 
205
    /* set return null parameter values, in case we exit with errors */
 
206
    *M = *N = *nz = 0;
 
207
 
 
208
    /* now continue scanning until you reach the end-of-comments */
 
209
    do {
 
210
        if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
 
211
            return MM_PREMATURE_EOF;
 
212
    } while (line[0] == '%');
 
213
 
 
214
    /* line[] is either blank or has M,N, nz */
 
215
    if (sscanf(line, "%d %d %d", M, N, nz) == 3)
 
216
        return 0;
 
217
 
 
218
    else
 
219
        do {
 
220
            num_items_read = fscanf(f, "%d %d %d", M, N, nz);
 
221
            if (num_items_read == EOF)
 
222
                return MM_PREMATURE_EOF;
 
223
        }
 
224
        while (num_items_read != 3);
 
225
 
 
226
    return 0;
 
227
}
 
228
 
 
229
 
 
230
int mm_read_mtx_array_size(FILE * f, int *M, int *N)
 
231
{
 
232
    char line[MM_MAX_LINE_LENGTH];
 
233
    int num_items_read;
 
234
    /* set return null parameter values, in case we exit with errors */
 
235
    *M = *N = 0;
 
236
 
 
237
    /* now continue scanning until you reach the end-of-comments */
 
238
    do {
 
239
        if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
 
240
            return MM_PREMATURE_EOF;
 
241
    } while (line[0] == '%');
 
242
 
 
243
    /* line[] is either blank or has M,N, nz */
 
244
    if (sscanf(line, "%d %d", M, N) == 2)
 
245
        return 0;
 
246
 
 
247
    else                        /* we have a blank line */
 
248
        do {
 
249
            num_items_read = fscanf(f, "%d %d", M, N);
 
250
            if (num_items_read == EOF)
 
251
                return MM_PREMATURE_EOF;
 
252
        }
 
253
        while (num_items_read != 2);
 
254
 
 
255
    return 0;
 
256
}
 
257
 
 
258
int mm_write_mtx_array_size(FILE * f, int M, int N)
 
259
{
 
260
    if (fprintf(f, "%d %d\n", M, N) != 2)
 
261
        return MM_COULD_NOT_WRITE_FILE;
 
262
    else
 
263
        return 0;
 
264
}
 
265
 
 
266
 
 
267
 
 
268
/*-------------------------------------------------------------------------*/
 
269
 
 
270
/******************************************************************/
 
271
/* use when I[], J[], and val[]J, and val[] are already allocated */
 
272
/******************************************************************/
 
273
 
 
274
int mm_read_mtx_crd_data(FILE * f, int M, int N, int nz, int I[], int J[],
 
275
                         double val[], MM_typecode matcode)
 
276
{
 
277
    int i;
 
278
    if (mm_is_complex(matcode)) {
 
279
        for (i = 0; i < nz; i++)
 
280
            if (fscanf
 
281
                (f, "%d %d %lg %lg", &I[i], &J[i], &val[2 * i],
 
282
                 &val[2 * i + 1])
 
283
                != 4)
 
284
                return MM_PREMATURE_EOF;
 
285
    } else if (mm_is_real(matcode)) {
 
286
        for (i = 0; i < nz; i++) {
 
287
            if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
 
288
                != 3)
 
289
                return MM_PREMATURE_EOF;
 
290
 
 
291
        }
 
292
    }
 
293
 
 
294
    else if (mm_is_pattern(matcode)) {
 
295
        for (i = 0; i < nz; i++)
 
296
            if (fscanf(f, "%d %d", &I[i], &J[i])
 
297
                != 2)
 
298
                return MM_PREMATURE_EOF;
 
299
    } else
 
300
        return MM_UNSUPPORTED_TYPE;
 
301
 
 
302
    return 0;
 
303
 
 
304
}
 
305
 
 
306
int mm_read_mtx_crd_entry(FILE * f, int *I, int *J,
 
307
                          double *real, double *imag, MM_typecode matcode)
 
308
{
 
309
    if (mm_is_complex(matcode)) {
 
310
        if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
 
311
            != 4)
 
312
            return MM_PREMATURE_EOF;
 
313
    } else if (mm_is_real(matcode)) {
 
314
        if (fscanf(f, "%d %d %lg\n", I, J, real)
 
315
            != 3)
 
316
            return MM_PREMATURE_EOF;
 
317
 
 
318
    }
 
319
 
 
320
    else if (mm_is_pattern(matcode)) {
 
321
        if (fscanf(f, "%d %d", I, J) != 2)
 
322
            return MM_PREMATURE_EOF;
 
323
    } else
 
324
        return MM_UNSUPPORTED_TYPE;
 
325
 
 
326
    return 0;
 
327
 
 
328
}
 
329
 
 
330
 
 
331
/************************************************************************
 
332
    mm_read_mtx_crd()  fills M, N, nz, array of values, and return
 
333
                        type code, e.g. 'MCRS'
 
334
 
 
335
                        if matrix is complex, values[] is of size 2*nz,
 
336
                            (nz pairs of real/imaginary values)
 
337
************************************************************************/
 
338
 
 
339
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
 
340
                    double **val, MM_typecode * matcode)
 
341
{
 
342
    int ret_code;
 
343
    FILE *f;
 
344
 
 
345
    if (strcmp(fname, "stdin") == 0)
 
346
        f = stdin;
 
347
    else if ((f = fopen(fname, "r")) == NULL)
 
348
        return MM_COULD_NOT_READ_FILE;
 
349
 
 
350
 
 
351
    if ((ret_code = mm_read_banner(f, matcode)) != 0)
 
352
        return ret_code;
 
353
 
 
354
    if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
 
355
          mm_is_matrix(*matcode)))
 
356
        return MM_UNSUPPORTED_TYPE;
 
357
 
 
358
    if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
 
359
        return ret_code;
 
360
 
 
361
 
 
362
    *I = (int *) malloc(*nz * sizeof(int));
 
363
    *J = (int *) malloc(*nz * sizeof(int));
 
364
    *val = NULL;
 
365
 
 
366
    if (mm_is_complex(*matcode)) {
 
367
        *val = (double *) malloc(*nz * 2 * sizeof(double));
 
368
        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
 
369
                                        *matcode);
 
370
        if (ret_code != 0)
 
371
            return ret_code;
 
372
    } else if (mm_is_real(*matcode)) {
 
373
        *val = (double *) malloc(*nz * sizeof(double));
 
374
        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
 
375
                                        *matcode);
 
376
        if (ret_code != 0)
 
377
            return ret_code;
 
378
    }
 
379
 
 
380
    else if (mm_is_pattern(*matcode)) {
 
381
        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
 
382
                                        *matcode);
 
383
        if (ret_code != 0)
 
384
            return ret_code;
 
385
    }
 
386
 
 
387
    if (f != stdin)
 
388
        fclose(f);
 
389
    return 0;
 
390
}
 
391
 
 
392
int mm_write_banner(FILE * f, MM_typecode matcode)
 
393
{
 
394
    char *str = mm_typecode_to_str(matcode);
 
395
    int ret_code;
 
396
 
 
397
    ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
 
398
    free(str);
 
399
    if (ret_code != 2)
 
400
        return MM_COULD_NOT_WRITE_FILE;
 
401
    else
 
402
        return 0;
 
403
}
 
404
 
 
405
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
 
406
                     double val[], MM_typecode matcode)
 
407
{
 
408
    FILE *f;
 
409
    int i;
 
410
 
 
411
    if (strcmp(fname, "stdout") == 0)
 
412
        f = stdout;
 
413
    else if ((f = fopen(fname, "w")) == NULL)
 
414
        return MM_COULD_NOT_WRITE_FILE;
 
415
 
 
416
    /* print banner followed by typecode */
 
417
    fprintf(f, "%s ", MatrixMarketBanner);
 
418
    fprintf(f, "%s\n", mm_typecode_to_str(matcode));
 
419
 
 
420
    /* print matrix sizes and nonzeros */
 
421
    fprintf(f, "%d %d %d\n", M, N, nz);
 
422
 
 
423
    /* print values */
 
424
    if (mm_is_pattern(matcode))
 
425
        for (i = 0; i < nz; i++)
 
426
            fprintf(f, "%d %d\n", I[i], J[i]);
 
427
    else if (mm_is_real(matcode))
 
428
        for (i = 0; i < nz; i++)
 
429
            fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
 
430
    else if (mm_is_complex(matcode))
 
431
        for (i = 0; i < nz; i++)
 
432
            fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2 * i],
 
433
                    val[2 * i + 1]);
 
434
    else {
 
435
        if (f != stdout)
 
436
            fclose(f);
 
437
        return MM_UNSUPPORTED_TYPE;
 
438
    }
 
439
 
 
440
    if (f != stdout)
 
441
        fclose(f);
 
442
 
 
443
    return 0;
 
444
}
 
445
 
 
446
 
 
447
/**
 
448
*  Create a new copy of a string s.  strdup() is a common routine, but
 
449
*  not part of ANSI C, so it is included here.  Used by mm_typecode_to_str().
 
450
*
 
451
*/
 
452
/* part of gcc
 
453
char *strdup(const char *s)
 
454
{
 
455
        int len = strlen(s);
 
456
        char *s2 = (char *) malloc((len+1)*sizeof(char));
 
457
        return strcpy(s2, s);
 
458
}
 
459
*/
 
460
 
 
461
char *mm_typecode_to_str(MM_typecode matcode)
 
462
{
 
463
    char buffer[MM_MAX_LINE_LENGTH];
 
464
    char *types[4];
 
465
    /*  char *strdup(const char *); */
 
466
    int error = 0;
 
467
 
 
468
    /* check for MTX type */
 
469
    if (mm_is_matrix(matcode))
 
470
        types[0] = MM_MTX_STR;
 
471
    else
 
472
        error = 1;
 
473
 
 
474
    /* check for CRD or ARR matrix */
 
475
    if (mm_is_sparse(matcode))
 
476
        types[1] = MM_SPARSE_STR;
 
477
    else if (mm_is_dense(matcode))
 
478
        types[1] = MM_DENSE_STR;
 
479
    else
 
480
        return NULL;
 
481
 
 
482
    /* check for element data type */
 
483
    if (mm_is_real(matcode))
 
484
        types[2] = MM_REAL_STR;
 
485
    else if (mm_is_complex(matcode))
 
486
        types[2] = MM_COMPLEX_STR;
 
487
    else if (mm_is_pattern(matcode))
 
488
        types[2] = MM_PATTERN_STR;
 
489
    else if (mm_is_integer(matcode))
 
490
        types[2] = MM_INT_STR;
 
491
    else
 
492
        return NULL;
 
493
 
 
494
 
 
495
    /* check for symmetry type */
 
496
    if (mm_is_general(matcode))
 
497
        types[3] = MM_GENERAL_STR;
 
498
    else if (mm_is_symmetric(matcode))
 
499
        types[3] = MM_SYMM_STR;
 
500
    else if (mm_is_hermitian(matcode))
 
501
        types[3] = MM_HERM_STR;
 
502
    else if (mm_is_skew(matcode))
 
503
        types[3] = MM_SKEW_STR;
 
504
    else
 
505
        return NULL;
 
506
 
 
507
    sprintf(buffer, "%s %s %s %s", types[0], types[1], types[2], types[3]);
 
508
    return strdup(buffer);
 
509
 
 
510
}