Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
agerror.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#include <cgraph/cghdr.h>
17#include <stdarg.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <util/agxbuf.h>
21#include <util/gv_ctype.h>
22#include <util/gv_math.h>
23#include <util/streq.h>
24
25static agerrlevel_t agerrno; /* Last error level */
26static agerrlevel_t agerrlevel = AGWARN; /* Report errors >= agerrlevel */
27static int agmaxerr;
28
29static agxbuf last;
30static agusererrf usererrf; /* User-set error function */
31
33 agusererrf oldf = usererrf;
34 usererrf = newf;
35 return oldf;
36}
37
40 agerrlevel = lvl;
41 return oldv;
42}
43
44char *aglasterr(void) {
45 // Extract a heap-allocated copy of the last message. Note that this resets
46 // `last` to an empty buffer ready to be written to again.
47 char *buf = agxbdisown(&last);
48
49 // store the message back again so multiple calls to `aglasterr` can be made
50 // without losing the last error
51 agxbput(&last, buf);
52
53 // was there no last message?
54 if (streq(buf, "")) {
55 free(buf);
56 return NULL;
57 }
58
59 return buf;
60}
61
63static int default_usererrf(char *message) {
64 // `fputs`, escaping characters that may interfere with a terminal
65 for (const char *p = message; *p != '\0'; ++p) {
66
67 if (gv_iscntrl(*p) && !gv_isspace(*p)) {
68 const int rc = fprintf(stderr, "\\%03o", (unsigned)*p);
69 if (rc < 0) {
70 return rc;
71 }
72 continue;
73 }
74
75 const int rc = putc(*p, stderr);
76 if (rc < 0) {
77 return rc;
78 }
79 }
80 return 0;
81}
82
84static void out(agerrlevel_t level, const char *fmt, va_list args) {
85 // find out how much space we need to construct this string
86 size_t bufsz;
87 {
88 va_list args2;
89 va_copy(args2, args);
90 int rc = vsnprintf(NULL, 0, fmt, args2);
91 va_end(args2);
92 if (rc < 0) {
93 fprintf(stderr, "%s: vsnprintf failure\n", __func__);
94 return;
95 }
96 bufsz = (size_t)rc + 1; // account for NUL terminator
97 }
98
99 // allocate a buffer for the string
100 char *buf = malloc(bufsz);
101 if (buf == NULL) {
102 fprintf(stderr, "%s: could not allocate memory\n", __func__);
103 return;
104 }
105
106 // determine how errors are to be reported
108
109 if (level != AGPREV) {
110 (void)errf(level == AGERR ? "Error" : "Warning");
111 (void)errf(": ");
112 }
113
114 // construct the full error in our buffer
115 int rc = vsnprintf(buf, bufsz, fmt, args);
116 if (rc < 0) {
117 free(buf);
118 fprintf(stderr, "%s: vsnprintf failure\n", __func__);
119 return;
120 }
121
122 // yield our constructed error
123 (void)errf(buf);
124
125 free(buf);
126}
127
128static int agerr_va(agerrlevel_t level, const char *fmt, va_list args) {
129 agerrlevel_t lvl;
130
131 /* Use previous error level if continuation message;
132 * Convert AGMAX to AGERROR;
133 * else use input level
134 */
135 lvl = (level == AGPREV ? agerrno : (level == AGMAX) ? AGERR : level);
136
137 /* store this error level */
138 agerrno = lvl;
139 agmaxerr = imax(agmaxerr, (int)agerrno);
140
141 /* We report all messages whose level is bigger than the user set agerrlevel
142 * Setting agerrlevel to AGMAX turns off immediate error reporting.
143 */
144 if (lvl >= agerrlevel) {
145 out(level, fmt, args);
146 return 0;
147 }
148
149 if (level != AGPREV)
150 agxbclear(&last);
151 vagxbprint(&last, fmt, args);
152 return 0;
153}
154
155int agerr(agerrlevel_t level, const char *fmt, ...) {
156 va_list args;
157 int ret;
158
159 va_start(args, fmt);
160 ret = agerr_va(level, fmt, args);
161 va_end(args);
162 return ret;
163}
164
165void agerrorf(const char *fmt, ...) {
166 va_list args;
167
168 va_start(args, fmt);
169 agerr_va(AGERR, fmt, args);
170 va_end(args);
171}
172
173void agwarningf(const char *fmt, ...) {
174 va_list args;
175
176 va_start(args, fmt);
177 agerr_va(AGWARN, fmt, args);
178 va_end(args);
179}
180
181int agerrors(void) { return agmaxerr; }
182
183int agreseterrors(void) {
184 int rc = agmaxerr;
185 agmaxerr = 0;
186 return rc;
187}
static agusererrf usererrf
Definition agerror.c:30
static void out(agerrlevel_t level, const char *fmt, va_list args)
Report messages using a user-supplied or default write function.
Definition agerror.c:84
static agerrlevel_t agerrlevel
Definition agerror.c:26
static int default_usererrf(char *message)
default error reporting implementation
Definition agerror.c:63
static int agmaxerr
Definition agerror.c:27
static agerrlevel_t agerrno
Definition agerror.c:25
static agxbuf last
last message
Definition agerror.c:29
static int agerr_va(agerrlevel_t level, const char *fmt, va_list args)
Definition agerror.c:128
static void agxbclear(agxbuf *xb)
resets pointer to data
Definition agxbuf.h:294
static int vagxbprint(agxbuf *xb, const char *fmt, va_list ap)
vprintf-style output to an agxbuf
Definition agxbuf.h:162
static char * agxbdisown(agxbuf *xb)
Definition agxbuf.h:327
cgraph.h additions
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:163
agerrlevel_t
Definition cgraph.h:849
int agreseterrors(void)
Definition agerror.c:183
void agwarningf(const char *fmt,...)
Definition agerror.c:173
void agerrorf(const char *fmt,...)
Definition agerror.c:165
agerrlevel_t agseterr(agerrlevel_t lvl)
Definition agerror.c:38
char * aglasterr(void)
Definition agerror.c:44
agusererrf agseterrf(agusererrf newf)
Definition agerror.c:32
int agerr(agerrlevel_t level, const char *fmt,...)
Definition agerror.c:155
int agerrors(void)
Definition agerror.c:181
int(* agusererrf)(char *)
Definition cgraph.h:850
@ AGWARN
Definition cgraph.h:849
@ AGMAX
Definition cgraph.h:849
@ AGERR
Definition cgraph.h:849
@ AGPREV
Definition cgraph.h:849
replacements for ctype.h functions
static bool gv_iscntrl(int c)
Definition gv_ctype.h:33
static bool gv_isspace(int c)
Definition gv_ctype.h:55
Arithmetic helper functions.
static int imax(int a, int b)
maximum of two integers
Definition gv_math.h:24
agxbput(xb, staging)
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11