File Coverage

lib/PDL/Core/pdlutil.c
Criterion Covered Total %
statement 183 329 55.6
branch 82 214 38.3
condition n/a
subroutine n/a
pod n/a
total 265 543 48.8


line stmt bran cond sub pod time code
1             #include "pdl.h" /* Data structure declarations */
2             #define PDL_IN_CORE
3             #include "pdlcore.h" /* Core declarations */
4             #include
5              
6             extern Core PDL; /* for PDL_TYPENAME */
7              
8             #define msgptr_advance() \
9             do { \
10             int N = strlen(msgptr); \
11             msgptr += N; \
12             remaining -= N; \
13             } while(0)
14             #define SET_SPACE(s, nspac) char spaces[PDL_MAXSPACE]; do { \
15             int i; \
16             if (nspac >= PDL_MAXSPACE) { \
17             printf("too many spaces requested: %d" \
18             " (increase PDL_MAXSPACE in pdlapi.c), returning\n",nspac); \
19             return; \
20             } \
21             for(i=0; i
22             spaces[i] = '\0'; \
23             } while (0)
24             #define psp printf("%s",spaces)
25              
26             /* modified from glibc printf(3) */
27 115           pdl_error pdl_make_error(pdl_error_type e, const char *fmt, ...) {
28 115           pdl_error PDL_err = {PDL_EFATAL, "make_error problem", 0};
29 115 50         PDLDEBUG_f(printf("pdl_make_error called: "));
30             va_list ap;
31             /* Determine required size */
32 115           va_start(ap, fmt);
33 115           int size = vsnprintf(NULL, 0, fmt, ap);
34 115           va_end(ap);
35 115 50         if (size < 0) return PDL_err;
36 115           char needs_free = 1;
37 115           char *p = NULL;
38 115 100         if (pdl_pthread_main_thread()) {
39 114           size++; /* For '\0' */
40 114           p = malloc(size);
41 114 50         if (p == NULL) return PDL_err;
42 114           va_start(ap, fmt);
43 114           size = vsnprintf(p, size, fmt, ap);
44 114           va_end(ap);
45 114 50         if (size < 0) {
46 0           free(p);
47 0           return PDL_err;
48             }
49             } else {
50 1           size_t len = 0;
51 1           va_start(ap, fmt);
52 1           pdl_pthread_realloc_vsnprintf(&p, &len, size, fmt, &ap, 0);
53 1           va_end(ap);
54 1           needs_free = 2;
55             }
56 115 50         PDLDEBUG_f(printf("%s\n", p));
57 115           return (pdl_error){e, p, needs_free};
58             }
59              
60 2           pdl_error pdl_make_error_simple(pdl_error_type e, const char *msg) {
61 2           pdl_error PDL_err = {e, msg, 0};
62 2           return PDL_err;
63             }
64              
65 30           pdl_error pdl_param_error(
66             pdl_transvtable *vtable, int paramIndex,
67             pdl **pdls, PDL_Indx nimpl, PDL_Indx *creating,
68             char *pat, ...
69             ) {
70             // I make a pdl_error with a string such as "function(a,b,c): parameter 'b': errormessage"
71 30           char message [4096] = {'\0'};
72             int i,j,maxrealdims;
73             va_list args;
74 30           char* msgptr = message;
75 30           int remaining = sizeof(message);
76 30 50         if(paramIndex < 0 || paramIndex >= vtable->npdls) {
    50          
77 0           strcat(msgptr, "ERROR: UNKNOWN PARAMETER");
78 0           msgptr_advance();
79             } else {
80 30           snprintf(msgptr, remaining, "%s(", vtable->name);
81 30           msgptr_advance();
82 120 100         for(i=0; inpdls; i++) {
83 90           snprintf(msgptr, remaining, "%s", vtable->par_names[i]);
84 90           msgptr_advance();
85 90 100         if(i < vtable->npdls-1) {
86 60           snprintf(msgptr, remaining, ",");
87 60           msgptr_advance();
88             }
89             }
90 30           snprintf(msgptr, remaining, "): parameter '%s': ",
91 30           vtable->par_names[paramIndex]);
92 30           msgptr_advance();
93             }
94 30           va_start(args,pat);
95 30           vsnprintf(msgptr, remaining, pat, args);
96 30           va_end(args);
97 30           msgptr_advance();
98 30 100         snprintf(msgptr, remaining,
99             "\nThere are %"IND_FLAG" PDLs in the expression; %"IND_FLAG" broadcast dim%s.\n",
100             vtable->npdls,nimpl,(nimpl==1)?"":"s"
101             );
102 30           msgptr_advance();
103 120 100         for(i=maxrealdims=0; inpdls; i++)
104 90 100         if(vtable->par_realdims[i]>maxrealdims)
105 30           maxrealdims=vtable->par_realdims[i];
106 30           snprintf(msgptr, remaining, " PDL IN EXPR. ");
107 30           msgptr_advance();
108 30 100         if(maxrealdims > 0) {
109             char format[80];
110 28           snprintf(format, sizeof(format)-1, "%%%ds", 8 * maxrealdims + 3);
111 28           snprintf(msgptr,remaining,format,"ACTIVE DIMS | ");
112 28           msgptr_advance();
113             }
114 30           snprintf(msgptr, remaining,"BROADCAST DIMS\n");
115 30           msgptr_advance();
116 120 100         for(i=0; inpdls; i++) {
117 90 100         snprintf(msgptr,remaining," #%3d (%s",i,creating[i]?"null)\n":"normal): ");
118 90           msgptr_advance();
119 90 100         if(creating[i])
120 4           continue;
121 86 100         if(maxrealdims == 1) {
122 72           snprintf(msgptr,remaining," ");
123 72           msgptr_advance();
124             }
125 90 100         for(j=0; j< maxrealdims - vtable->par_realdims[i]; j++) {
126 4           snprintf(msgptr,remaining,"%8s"," ");
127 4           msgptr_advance();
128             }
129 174 100         for(j=0; j< vtable->par_realdims[i]; j++) {
130 88           snprintf(msgptr,remaining,"%8"IND_FLAG,pdls[i]->dims[j]);
131 88           msgptr_advance();
132             }
133 86 100         if(maxrealdims) {
134 82           snprintf(msgptr,remaining," | ");
135 82           msgptr_advance();
136             }
137 124 100         for(j=0; jpar_realdims[i] < pdls[i]->ndims; j++) {
    100          
138 38           snprintf(msgptr,remaining,"%8"IND_FLAG,pdls[i]->dims[j+vtable->par_realdims[i]]);
139 38           msgptr_advance();
140             }
141 86           snprintf(msgptr,remaining,"\n");
142 86           msgptr_advance();
143             }
144 30           return pdl_make_error(PDL_EUSERERROR, "%s", message);
145             }
146              
147 5           void pdl_print_iarr(PDL_Indx *iarr, int n) {
148             int i;
149 5           printf("(");
150 8 50         for (i=0;i
    100          
151 5           printf(")");
152 5           }
153              
154 0           void pdl_dump_transvtable(pdl_transvtable *vtable, int nspac) {
155 0           int i, j, found=0, sz=0;
156 0 0         SET_SPACE(spaces, nspac);
    0          
157 0           int paramflagval[] = {
158             #define X(f) f,
159             PDL_LIST_FLAGS_PARAMS(X)
160             #undef X
161             0
162             };
163 0           char *paramflagchar[] = {
164             #define X(f) #f,
165             PDL_LIST_FLAGS_PARAMS(X)
166             #undef X
167             NULL
168             };
169 0           char *typechar[] = {
170             #define X(sym, ...) #sym,
171             PDL_TYPELIST_ALL(X)
172             #undef X
173             NULL
174             };
175 0           psp; printf("Funcname: %s\n",vtable->name);
176 0           psp; printf("Types: ");
177 0           found=0; sz=0;
178 0 0         for (i=0;vtable->gentypes[i]!=-1; i++) {
179 0           char *this_str = typechar[vtable->gentypes[i]] + 4; /* "PDL_" */
180 0           size_t thislen = strlen(this_str);
181 0 0         if ((sz+thislen)>PDL_MAXLIN) {sz=nspac+4; printf("\n%s ",spaces);}
182 0 0         printf("%s%s",found ? ",":"",this_str); found = 1;
183 0           sz += thislen;
184             }
185 0           printf("\n");
186 0           psp; printf("Parameters:\n");
187 0 0         for (i=0;inpdls;i++) {
188 0           psp; sz = nspac + printf(" %s(",vtable->par_names[i]);
189 0           found=0;
190 0 0         for (j=0;jpar_realdims[i];j++) {
191 0 0         if (found) sz += printf(","); found=1;
192 0           sz += printf("%s",vtable->ind_names[PDL_IND_ID(vtable, i, j)]);
193             }
194 0 0         if (vtable->par_flags[i] & PDL_PARAM_ISTYPED)
195 0 0         sz += printf(") (%s", PDL_TYPENAME(vtable->par_types[i]));
    0          
    0          
196 0           sz += printf("): ");
197 0           found=0;
198 0 0         for (j=0;paramflagval[j]!=0; j++)
199 0 0         if (vtable->par_flags[i] & paramflagval[j]) {
200 0           char *this_str = paramflagchar[j];
201 0           size_t thislen = strlen(this_str);
202 0 0         if ((sz+thislen)>PDL_MAXLIN) {sz=nspac+8; printf("\n%s ",spaces);}
203 0 0         sz += printf("%s%s",found ? "|":"",this_str); found = 1;
204             }
205 0 0         if (!found) printf("(no flags set)");
206 0           printf("\n");
207             }
208 0           psp; printf("Indices:");
209 0 0         for (i=0;ininds;i++)
210 0           printf(" %s",vtable->ind_names[i]);
211 0           printf("\n");
212             }
213              
214 0           void pdl_dump_broadcast(pdl_broadcast *broadcast) {
215 0           int i, found=0, sz=0, nspac=4;
216 0 0         SET_SPACE(spaces, nspac);
    0          
217 0           int flagval[] = {
218             #define X(f) f,
219             PDL_LIST_FLAGS_PDLBROADCAST(X)
220             #undef X
221             0
222             };
223 0           char *flagchar[] = {
224             #define X(f) #f,
225             PDL_LIST_FLAGS_PDLBROADCAST(X)
226             #undef X
227             NULL
228             };
229 0           printf("DUMPBROADCAST %p\n",broadcast);
230 0 0         if (broadcast->transvtable)
231 0           pdl_dump_transvtable(broadcast->transvtable, 4);
232 0           psp; printf("Flags: ");
233 0           found=0; sz=0;
234 0 0         for (i=0;flagval[i]!=0; i++)
235 0 0         if (broadcast->gflags & flagval[i]) {
236 0           char *this_str = flagchar[i];
237 0           size_t thislen = strlen(this_str);
238 0 0         if ((sz+thislen)>PDL_MAXLIN) {sz=nspac; printf("\n%s",spaces);}
239 0 0         printf("%s%s",found ? "|":"",this_str); found = 1;
240 0           sz += thislen;
241             }
242 0           printf("\n");
243 0           psp; printf("Ndims: %"IND_FLAG", Nimplicit: %"IND_FLAG", Npdls: %"IND_FLAG", Nextra: %"IND_FLAG"\n",
244             broadcast->ndims,broadcast->nimpl,broadcast->npdls,broadcast->nextra);
245 0           psp; printf("Mag_nth: %"IND_FLAG", Mag_nthpdl: %"IND_FLAG", Mag_nthr: %"IND_FLAG", Mag_skip: %"IND_FLAG", Mag_stride: %"IND_FLAG"\n",
246             broadcast->mag_nth,broadcast->mag_nthpdl,broadcast->mag_nthr,broadcast->mag_skip,broadcast->mag_stride);
247 0 0         if (broadcast->mag_nthr <= 0) {
248 0           psp; printf("Dims: "); pdl_print_iarr(broadcast->dims,broadcast->ndims); printf("\n");
249 0           psp; printf("Inds: "); pdl_print_iarr(broadcast->inds,broadcast->ndims); printf("\n");
250 0           psp; printf("Offs: "); pdl_print_iarr(broadcast->offs,broadcast->npdls); printf("\n");
251             } else {
252 0           psp; printf("Dims (per thread):\n");
253 0 0         for (i=0;imag_nthr;i++) {
254 0           psp; psp; pdl_print_iarr(broadcast->dims + i*broadcast->ndims,broadcast->ndims);
255 0           printf("\n");
256             }
257 0           psp; printf("Inds (per thread):\n");
258 0 0         for (i=0;imag_nthr;i++) {
259 0           psp; psp; pdl_print_iarr(broadcast->inds + i*broadcast->ndims,broadcast->ndims);
260 0           printf("\n");
261             }
262 0           psp; printf("Offs (per thread):\n");
263 0 0         for (i=0;imag_nthr;i++) {
264 0           psp; psp; pdl_print_iarr(broadcast->offs + i*broadcast->npdls,broadcast->npdls);
265 0           printf("\n");
266             }
267             }
268 0           psp; printf("Incs (per dim):\n");
269 0 0         for (i=0;indims;i++) {
270 0           psp; psp; pdl_print_iarr(&PDL_BRC_INC(broadcast->incs, broadcast->npdls, 0, i),broadcast->npdls);
271 0           printf("\n");
272             }
273 0           psp; printf("Realdims: "); pdl_print_iarr(broadcast->realdims,broadcast->npdls); printf("\n");
274 0           psp; printf("Pdls: (");
275 0 0         for (i=0;inpdls;i++)
276 0 0         printf("%s%p",(i?" ":""),(broadcast->pdls[i]));
277 0           printf(")\n");
278 0           psp; printf("Per pdl flags: (");
279 0 0         for (i=0;inpdls;i++)
280 0 0         printf("%s%d",(i?" ":""),broadcast->flags[i]);
281 0           printf(")\n");
282             }
283              
284 0           void pdl_dump_broadcasting_info(
285             int npdls, PDL_Indx* creating, int target_pthread,
286             PDL_Indx *nbroadcastedDims, PDL_Indx **broadcastedDims, PDL_Indx **broadcastedDimSizes,
287             int maxPthreadPDL, int maxPthreadDim, int maxPthread
288             ) {
289             PDL_Indx j, k;
290 0 0         for(j=0; j
291 0 0         if(creating[j]) continue;
292 0           printf("PDL %"IND_FLAG":\n", j);
293 0 0         for( k=0; k < nbroadcastedDims[j]; k++){
294 0           printf("Broadcast dim %"IND_FLAG", Dim No %"IND_FLAG", Size %"IND_FLAG"\n",
295 0           k, broadcastedDims[j][k], broadcastedDimSizes[j][k]);
296             }
297             }
298 0           printf("\nTarget Pthread = %d\n"
299             "maxPthread = %d, maxPthreadPDL = %d, maxPthreadDim = %d\n",
300             target_pthread, maxPthread, maxPthreadPDL, maxPthreadDim);
301 0           }
302              
303 3           void pdl_dump_flags_fixspace(int flags, int nspac, pdl_flags type)
304             {
305             int i;
306 3           int found = 0;
307 3           size_t sz = 0;
308 3           int pdlflagval[] = {
309             #define X(f) f,
310             PDL_LIST_FLAGS_PDLSTATE(X)
311             #undef X
312             0
313             };
314 3           char *pdlflagchar[] = {
315             #define X(f) #f,
316             PDL_LIST_FLAGS_PDLSTATE(X)
317             #undef X
318             NULL
319             };
320 3           int transflagval[] = {
321             #define X(f) f,
322             PDL_LIST_FLAGS_PDLTRANS(X)
323             #undef X
324             0
325             };
326 3           char *transflagchar[] = {
327             #define X(f) #f,
328             PDL_LIST_FLAGS_PDLTRANS(X)
329             #undef X
330             NULL
331             };
332 3           int vtableflagval[] = {
333             #define X(f) f,
334             PDL_LIST_FLAGS_PDLVTABLE(X)
335             #undef X
336             0
337             };
338 3           char *vtableflagchar[] = {
339             #define X(f) #f,
340             PDL_LIST_FLAGS_PDLVTABLE(X)
341             #undef X
342             NULL
343             };
344             int *flagval;
345             char **flagchar;
346 18 50         SET_SPACE(spaces, nspac);
    100          
347 3           switch (type) {
348 1           case PDL_FLAGS_PDL: {
349 1           flagval = pdlflagval;
350 1           flagchar = pdlflagchar;
351 1           break; }
352 1           case PDL_FLAGS_VTABLE: {
353 1           flagval = vtableflagval;
354 1           flagchar = vtableflagchar;
355 1           break; }
356 1           default: {
357 1           flagval = transflagval;
358 1           flagchar = transflagchar;
359             }
360             }
361 3           printf("(%d) ",flags);
362 3           found = 0; sz = 0;
363 26 100         for (i=0;flagval[i]!=0; i++)
364 23 100         if (flags & flagval[i]) {
365 7           char *this_str = flagchar[i];
366 7           size_t thislen = strlen(this_str);
367 7 50         if ((sz+thislen)>PDL_MAXLIN) {sz=7+nspac; printf("\n %s",spaces);}
368 7 100         printf("%s%s",found ? "|":"",this_str); found = 1;
369 7           sz += thislen;
370             }
371 3           printf("\n");
372             }
373              
374             /* Dump a transformation (don't dump the pdls, just pointers to them */
375 1           void pdl_dump_trans_fixspace (pdl_trans *it, int nspac) {
376             PDL_Indx i;
377 4 50         SET_SPACE(spaces, nspac);
    100          
378 1           printf("%sDUMPTRANS %p (%s)\n%s Flags: ",spaces,it,it->vtable->name,spaces);
379 1           pdl_dump_flags_fixspace(it->flags,nspac+3, PDL_FLAGS_TRANS);
380 1           printf("%s bvalflag: %d\n",spaces,it->bvalflag);
381 1           printf("%s vtable flags ",spaces);
382 1           pdl_dump_flags_fixspace(it->vtable->flags,nspac+3,PDL_FLAGS_VTABLE);
383 1 50         if(it->flags & PDL_ITRANS_ISAFFINE) {
384 0 0         if(it->pdls[1]->state & PDL_PARENTDIMSCHANGED) {
385 0           printf("%s AFFINE, BUT DIMSCHANGED\n",spaces);
386             } else {
387 0           printf("%s AFFINE: o:%"IND_FLAG", i:",spaces,it->offs);
388 0 0         if (it->incs)
389 0           pdl_print_iarr(it->incs, it->pdls[1]->ndims);
390 0           printf(" d:");
391 0           pdl_print_iarr(it->pdls[1]->dims, it->pdls[1]->ndims);
392 0           printf("\n");
393             }
394             }
395             /* if(it->vtable->dump) {it->vtable->dump(it);} */
396 1           printf("%s ind_sizes: ",spaces);
397 1           pdl_print_iarr(it->ind_sizes, it->vtable->ninds); printf("\n");
398 1           printf("%s inc_sizes: ",spaces);
399 1           pdl_print_iarr(it->inc_sizes, it->vtable->nind_ids); printf("\n");
400 1           printf("%s input trans_children_indices: ",spaces); /* CORE21 hook up to own data */
401 1           pdl_print_iarr(it->ind_sizes+it->vtable->ninds, it->vtable->nparents); printf("\n");
402 1           printf("%s INPUTS: (",spaces);
403 2 100         for(i=0; ivtable->nparents; i++)
404 1 50         printf("%s%p",(i?" ":""),(it->pdls[i]));
405 1           printf(") OUTPUTS: (");
406 2 100         for(;ivtable->npdls; i++)
407 1 50         printf("%s%p",(i>it->vtable->nparents?" ":""),(it->pdls[i]));
408 1           printf(")\n");
409             }
410              
411 1           void pdl_dump_fixspace(pdl *it,int nspac) {
412             PDL_Indx i;
413 1 50         SET_SPACE(spaces, nspac);
    50          
414 1           printf("%sDUMPING %p datatype: %d\n%s State: ",spaces,it,it->datatype,spaces);
415 1           pdl_dump_flags_fixspace(it->state,nspac+3,PDL_FLAGS_PDL);
416 1           printf("%s transvtable: %p, trans: %p, sv: %p\n",spaces,
417 1 50         it->trans_parent?it->trans_parent->vtable:0, it->trans_parent, it->sv);
418 1 50         if (it->datasv)
419 0           printf("%s datasv: %p, Svlen: %lld, refcnt: %lld\n", spaces,
420 0           it->datasv, (long long)SvCUR((SV*)it->datasv), (long long)SvREFCNT((SV*)it->datasv));
421 1 50         if (it->data)
422 0           printf("%s data: %p, nbytes: %"IND_FLAG", nvals: %"IND_FLAG"\n", spaces,
423             it->data, it->nbytes, it->nvals);
424 1 50         if (it->hdrsv)
425 0           printf("%s hdrsv: %p, reftype %s\n", spaces,
426 0           it->hdrsv, sv_reftype((SV*)it->hdrsv, TRUE));
427 1           printf("%s Dims: %p ",spaces,it->dims);
428 1           pdl_print_iarr(it->dims, it->ndims);
429 1           printf("\n%s BroadcastIds: %p ",spaces,it->broadcastids);
430 1           pdl_print_iarr(it->broadcastids, it->nbroadcastids);
431 1 50         if (it->vafftrans) {
432 0           printf("\n%s Vafftrans: %p (parent), o:%"IND_FLAG", i:",
433 0           spaces,it->vafftrans->from,it->vafftrans->offs);
434 0 0         pdl_print_iarr(PDL_REPRINCS(it), it->vafftrans->ndims);
435             }
436 1 50         if (it->state & PDL_BADVAL) {
437 0 0         printf("\n%s Badvalue (%s): ",spaces, it->has_badvalue ? "bespoke" : "orig");
438 0           PDL_Anyval result = { PDL_INVALID, {0} };
439 0 0         if (!(it->has_badvalue && it->badvalue.type != it->datatype)) {
    0          
440 0 0         if (it->has_badvalue)
441 0           result = it->badvalue;
442             else {
443             #define X(datatype, ctype, ppsym, shortctype, defbval, ...) \
444             result.type = datatype; result.value.ppsym = defbval;
445 0           PDL_GENERICSWITCH(PDL_TYPELIST_ALL, it->datatype, X, )
446             #undef X
447             }
448             }
449 0 0         if (result.type < 0)
450 0           printf("ERROR getting badval");
451             else
452 0           pdl_dump_anyval(result);
453             }
454 1 50         if (it->state & PDL_ALLOCATED) {
455 0           printf("\n%s First values: (",spaces);
456 0 0         for (i=0; invals && i<10; i++) {
    0          
457 0 0         if (i) printf(" ");
458 0           PDL_Anyval result = { PDL_INVALID, {0} };
459 0           ANYVAL_FROM_CTYPE_OFFSET(result, it->datatype, it->data, i);
460 0           pdl_dump_anyval(result);
461             }
462             } else {
463 1           printf("\n%s (not allocated",spaces);
464             }
465 1           printf(")\n");
466 1 50         if (it->trans_parent) {
467 1           pdl_dump_trans_fixspace(it->trans_parent,nspac+3);
468             }
469 1 50         if (it->ntrans_children) {
470 0           printf("%s CHILDREN:\n",spaces);
471 0 0         for (i = 0; i < it->ntrans_children_allocated; i++) {
472 0           pdl_trans *t = it->trans_children[i];
473 0 0         if (!t) continue;
474 0           pdl_dump_trans_fixspace(t, nspac+4);
475             }
476             }
477             }
478              
479 1           void pdl_dump (pdl *it) {
480 1           pdl_dump_fixspace(it,0);
481 1           fflush(stdout);
482 1           }
483              
484 0           void pdl_dump_anyval(PDL_Anyval v) {
485 0 0         if (v.type < PDL_CF) {
486             #define X(datatype, ctype, ppsym, ...) \
487             printf("%Lg", (long double)v.value.ppsym);
488 0           PDL_GENERICSWITCH(PDL_TYPELIST_REAL, v.type, X, printf("(UNKNOWN PDL_Anyval type=%d)", v.type))
489             #undef X
490             } else {
491             #define X(datatype, ctype, ppsym, ...) \
492             printf("%Lg%+Lgi", creall((complex long double)v.value.ppsym), cimagl((complex long double)v.value.ppsym));
493 0           PDL_GENERICSWITCH(PDL_TYPELIST_COMPLEX, v.type, X, printf("(UNKNOWN PDL_Anyval type=%d)", v.type))
494             #undef X
495             }
496 0           }
497              
498 115           void pdl_error_free(pdl_error e) {
499 115 100         if (e.needs_free == 1) {
500 114           free((void *)e.message);
501             } else {
502             /* needs mutex-protected and de-Perl-ified */
503 1           pdl_pthread_free((void *)e.message);
504             }
505 115           }
506              
507 302427           void pdl_barf_if_error(pdl_error err) {
508 302427 100         if (!err.error) return;
509 117           const char *msg = err.message;
510 117 100         if (err.needs_free) {
511 115           char *cpy = pdl_smalloc(strlen(msg) + 1);
512 115           strcpy(cpy, err.message);
513 115           pdl_error_free(err);
514 115           msg = cpy;
515             }
516 117           pdl_pdl_barf(msg);
517             }
518              
519 623           pdl_error pdl_error_accumulate(pdl_error err_current, pdl_error err_new) {
520 623 100         if (!err_new.error) return err_current;
521 52 50         if (!err_current.error) return err_new;
522 0           pdl_error PDL_err = pdl_make_error(
523             PDLMAX(err_current.error, err_current.error),
524             "%s\n%s", err_current.message, err_new.message
525             );
526 0 0         if (err_current.needs_free) pdl_error_free(err_current);
527 0 0         if (err_new.needs_free) pdl_error_free(err_new);
528 0           return PDL_err;
529             }