Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
ingraphs.c
Go to the documentation of this file.
1
6/*************************************************************************
7 * Copyright (c) 2011 AT&T Intellectual Property
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the Eclipse Public License v1.0
10 * which accompanies this distribution, and is available at
11 * https://www.eclipse.org/legal/epl-v10.html
12 *
13 * Contributors: Details at https://graphviz.org
14 *************************************************************************/
15
16
17/*
18 * Written by Emden Gansner
19 */
20
21#include <cgraph/cgraph.h>
22#include <cgraph/ingraphs.h>
23#include <stdbool.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <util/gv_fopen.h>
27
28/* Set next available file.
29 * If Files is NULL, we just read from stdin.
30 */
31static void nextFile(ingraph_state * sp)
32{
33 void *rv = NULL;
34 char *fname;
35
36 if (sp->u.Files == NULL) {
37 if (sp->ctr++ == 0) {
38 rv = stdin;
39 }
40 } else {
41 while ((fname = sp->u.Files[sp->ctr++])) {
42 if (*fname == '-') {
43 rv = stdin;
44 break;
45 } else if ((rv = gv_fopen(fname, "r")) != 0)
46 break;
47 else {
48 fprintf(stderr, "Can't open %s\n", sp->u.Files[sp->ctr - 1]);
49 sp->errors++;
50 }
51 }
52 }
53 if (rv)
55 sp->fp = rv;
56}
57
58/* Read and return next graph; return NULL if done.
59 * Read graph from currently open file. If none, open next file.
60 */
62{
63 Agraph_t *g;
64
65 if (sp->ingraphs) {
66 g = sp->u.Graphs[sp->ctr];
67 if (g) sp->ctr++;
68 return g;
69 }
70 if (sp->fp == NULL)
71 nextFile(sp);
72 g = NULL;
73
74 while (sp->fp != NULL) {
75 if ((g = sp->readf(sp->fp)) != 0)
76 break;
77 if (sp->u.Files) /* Only close if not using stdin */
78 (void)fclose(sp->fp);
79 nextFile(sp);
80 }
81 return g;
82}
83
84/* Create new ingraph state. If sp is non-NULL, we
85 * assume user is supplying memory.
86 */
87static ingraph_state*
88new_ing(ingraph_state * sp, char **files, Agraph_t** graphs, Agraph_t *(*readf)(void*))
89{
90 if (!sp) {
91 sp = malloc(sizeof(ingraph_state));
92 if (!sp) {
93 fprintf(stderr, "ingraphs: out of memory\n");
94 return 0;
95 }
96 sp->heap = true;
97 } else
98 sp->heap = false;
99 if (graphs) {
100 sp->ingraphs = 1;
101 sp->u.Graphs = graphs;
102 }
103 else {
104 sp->ingraphs = 0;
105 sp->u.Files = files;
106 }
107 sp->ctr = 0;
108 sp->errors = 0;
109 sp->fp = NULL;
110 if (!readf) {
111 if (sp->heap)
112 free(sp);
113 fprintf(stderr, "ingraphs: NULL read function\n");
114 return 0;
115 }
116 sp->readf = readf;
117 return sp;
118}
119
121 Agraph_t *(*readf)(void *)) {
122 return new_ing(sp, files, 0, readf);
123}
124
125/* Create new ingraph state using supplied graphs. If sp is non-NULL, we
126 * assume user is supplying memory.
127 */
129 Agraph_t *(*readf)(void *)) {
130 return new_ing(sp, 0, graphs, readf);
131}
132
133static Agraph_t *dflt_read(void *fp) {
134 return agread(fp, NULL);
135}
136
137/* At present, we require opf to be non-NULL. In
138 * theory, we could assume a function agread(FILE*,void*)
139 */
141 return newIng(sp, files, dflt_read);
142}
143
144/* Close any open files and free discipline
145 * Free sp if necessary.
146 */
148{
149 if (!sp->ingraphs && sp->u.Files && sp->fp)
150 (void)fclose(sp->fp);
151 if (sp->heap)
152 free(sp);
153}
154
157{
158 char *fname;
159
160 if (sp->ingraphs) {
161 return "<>";
162 }
163 else if (sp->u.Files) {
164 if (sp->ctr) {
165 fname = sp->u.Files[sp->ctr - 1];
166 if (*fname == '-')
167 return "<stdin>";
168 else
169 return fname;
170 } else
171 return "<>";
172 } else
173 return "<stdin>";
174}
abstract graph C library, Cgraph API
static char * fname
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:163
void agsetfile(const char *)
sets the current file name for subsequent error reporting
Definition scan.c:2415
Agraph_t * agread(void *chan, Agdisc_t *disc)
constructs a new graph
Definition grammar.c:2292
FILE * gv_fopen(const char *filename, const char *mode)
Definition gv_fopen.c:32
wrapper around fopen for internal library usage
char * fileName(ingraph_state *sp)
Return name of current file being processed.
Definition ingraphs.c:156
void closeIngraph(ingraph_state *sp)
Definition ingraphs.c:147
Agraph_t * nextGraph(ingraph_state *sp)
Definition ingraphs.c:61
static ingraph_state * new_ing(ingraph_state *sp, char **files, Agraph_t **graphs, Agraph_t *(*readf)(void *))
Definition ingraphs.c:88
ingraph_state * newIng(ingraph_state *sp, char **files, Agraph_t *(*readf)(void *))
Definition ingraphs.c:120
ingraph_state * newIngraph(ingraph_state *sp, char **files)
Definition ingraphs.c:140
static Agraph_t * dflt_read(void *fp)
Definition ingraphs.c:133
ingraph_state * newIngGraphs(ingraph_state *sp, Agraph_t **graphs, Agraph_t *(*readf)(void *))
Definition ingraphs.c:128
static void nextFile(ingraph_state *sp)
Definition ingraphs.c:31
supports user-supplied data
graph or subgraph
Definition cgraph.h:425
union ingraph_state::@65 u
char ** Files
Definition ingraphs.h:45
Agraph_t *(* readf)(void *)
Definition ingraphs.h:51
Agraph_t ** Graphs
Definition ingraphs.h:46
unsigned errors
Definition ingraphs.h:53
void * fp
Definition ingraphs.h:50