Graphviz 13.0.0~dev.20250607.1528
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 sp->fp = rv;
54}
55
56/* Read and return next graph; return NULL if done.
57 * Read graph from currently open file. If none, open next file.
58 */
60{
61 Agraph_t *g;
62
63 if (sp->ingraphs) {
64 g = sp->u.Graphs[sp->ctr];
65 if (g) sp->ctr++;
66 return g;
67 }
68 if (sp->fp == NULL)
69 nextFile(sp);
70 g = NULL;
71
72 while (sp->fp != NULL) {
73 if ((g = sp->readf(fileName(sp), sp->fp)) != 0)
74 break;
75 if (sp->u.Files) /* Only close if not using stdin */
76 (void)fclose(sp->fp);
77 nextFile(sp);
78 }
79 return g;
80}
81
82/* Create new ingraph state. If sp is non-NULL, we
83 * assume user is supplying memory.
84 */
85static ingraph_state *new_ing(ingraph_state *sp, char **files,
86 Agraph_t **graphs,
87 Agraph_t *(*readf)(const char *, void *)) {
88 if (!sp) {
89 sp = malloc(sizeof(ingraph_state));
90 if (!sp) {
91 fprintf(stderr, "ingraphs: out of memory\n");
92 return 0;
93 }
94 sp->heap = true;
95 } else
96 sp->heap = false;
97 if (graphs) {
98 sp->ingraphs = 1;
99 sp->u.Graphs = graphs;
100 }
101 else {
102 sp->ingraphs = 0;
103 sp->u.Files = files;
104 }
105 sp->ctr = 0;
106 sp->errors = 0;
107 sp->fp = NULL;
108 if (!readf) {
109 if (sp->heap)
110 free(sp);
111 fprintf(stderr, "ingraphs: NULL read function\n");
112 return 0;
113 }
114 sp->readf = readf;
115 return sp;
116}
117
119 Agraph_t *(*readf)(const char *, void *)) {
120 return new_ing(sp, files, 0, readf);
121}
122
123/* Create new ingraph state using supplied graphs. If sp is non-NULL, we
124 * assume user is supplying memory.
125 */
127 Agraph_t *(*readf)(const char *, void *)) {
128 return new_ing(sp, 0, graphs, readf);
129}
130
131static Agraph_t *dflt_read(const char *filename, void *fp) {
132 return agconcat(NULL, filename, fp, NULL);
133}
134
135/* At present, we require opf to be non-NULL. In
136 * theory, we could assume a function agread(FILE*,void*)
137 */
139 return newIng(sp, files, dflt_read);
140}
141
142/* Close any open files and free discipline
143 * Free sp if necessary.
144 */
146{
147 if (!sp->ingraphs && sp->u.Files && sp->fp)
148 (void)fclose(sp->fp);
149 if (sp->heap)
150 free(sp);
151}
152
155{
156 char *fname;
157
158 if (sp->ingraphs) {
159 return "<>";
160 }
161 else if (sp->u.Files) {
162 if (sp->ctr) {
163 fname = sp->u.Files[sp->ctr - 1];
164 if (*fname == '-')
165 return "<stdin>";
166 else
167 return fname;
168 } else
169 return "<>";
170 } else
171 return "<stdin>";
172}
abstract graph C library, Cgraph API
static char * fname
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:180
Agraph_t * agconcat(Agraph_t *g, const char *filename, void *chan, Agdisc_t *disc)
merges the file contents with a pre-existing graph
Definition grammar.c:2036
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:154
static ingraph_state * new_ing(ingraph_state *sp, char **files, Agraph_t **graphs, Agraph_t *(*readf)(const char *, void *))
Definition ingraphs.c:85
void closeIngraph(ingraph_state *sp)
Definition ingraphs.c:145
Agraph_t * nextGraph(ingraph_state *sp)
Definition ingraphs.c:59
ingraph_state * newIng(ingraph_state *sp, char **files, Agraph_t *(*readf)(const char *, void *))
Definition ingraphs.c:118
static Agraph_t * dflt_read(const char *filename, void *fp)
Definition ingraphs.c:131
ingraph_state * newIngraph(ingraph_state *sp, char **files)
Definition ingraphs.c:138
ingraph_state * newIngGraphs(ingraph_state *sp, Agraph_t **graphs, Agraph_t *(*readf)(const char *, void *))
Definition ingraphs.c:126
static void nextFile(ingraph_state *sp)
Definition ingraphs.c:31
supports user-supplied data
graph or subgraph
Definition cgraph.h:424
char ** Files
Definition ingraphs.h:45
Agraph_t ** Graphs
Definition ingraphs.h:46
Agraph_t *(* readf)(const char *, void *)
Definition ingraphs.h:51
unsigned errors
Definition ingraphs.h:53
union ingraph_state::@68 u
void * fp
Definition ingraphs.h:50