gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / libctf / ctf-dump.c
1 /* Textual dumping of CTF data.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
3
4 This file is part of libctf.
5
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include <ctf-impl.h>
21 #include <string.h>
22
23 #define str_append(s, a) ctf_str_append_noerr (s, a)
24
25 /* One item to be dumped, in string form. */
26
27 typedef struct ctf_dump_item
28 {
29 ctf_list_t cdi_list;
30 char *cdi_item;
31 } ctf_dump_item_t;
32
33 /* Cross-call state for dumping. Basically just enough to track the section in
34 use and a list of return strings. */
35
36 struct ctf_dump_state
37 {
38 ctf_sect_names_t cds_sect;
39 ctf_file_t *cds_fp;
40 ctf_dump_item_t *cds_current;
41 ctf_list_t cds_items;
42 };
43
44 /* Cross-call state for ctf_dump_member. */
45
46 typedef struct ctf_dump_membstate
47 {
48 char **cdm_str;
49 ctf_file_t *cdm_fp;
50 } ctf_dump_membstate_t;
51
52 static int
53 ctf_dump_append (ctf_dump_state_t *state, char *str)
54 {
55 ctf_dump_item_t *cdi;
56
57 if ((cdi = malloc (sizeof (struct ctf_dump_item))) == NULL)
58 return (ctf_set_errno (state->cds_fp, ENOMEM));
59
60 cdi->cdi_item = str;
61 ctf_list_append (&state->cds_items, cdi);
62 return 0;
63 }
64
65 static void
66 ctf_dump_free (ctf_dump_state_t *state)
67 {
68 ctf_dump_item_t *cdi, *next_cdi;
69
70 if (state == NULL)
71 return;
72
73 for (cdi = ctf_list_next (&state->cds_items); cdi != NULL;
74 cdi = next_cdi)
75 {
76 free (cdi->cdi_item);
77 next_cdi = ctf_list_next (cdi);
78 free (cdi);
79 }
80 }
81
82 /* Slices need special handling to distinguish them from their referenced
83 type. */
84
85 static int
86 ctf_is_slice (ctf_file_t *fp, ctf_id_t id, ctf_encoding_t *enc)
87 {
88 int kind = ctf_type_kind (fp, id);
89
90 return (((kind == CTF_K_INTEGER) || (kind == CTF_K_ENUM)
91 || (kind == CTF_K_FLOAT))
92 && ctf_type_reference (fp, id) != CTF_ERR
93 && ctf_type_encoding (fp, id, enc) == 0);
94 }
95
96 /* Return a dump for a single type, without member info: but do show the
97 type's references. */
98
99 static char *
100 ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id, int flag)
101 {
102 ctf_id_t new_id;
103 char *str = NULL, *bit = NULL, *buf = NULL;
104
105 new_id = id;
106 do
107 {
108 ctf_encoding_t enc;
109 const char *nonroot_leader = "";
110 const char *nonroot_trailer = "";
111
112 id = new_id;
113 if (flag == CTF_ADD_NONROOT)
114 {
115 nonroot_leader = "{";
116 nonroot_trailer = "}";
117 }
118
119 buf = ctf_type_aname (fp, id);
120 if (!buf)
121 {
122 if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE)
123 {
124 str = str_append (str, " (type not represented in CTF)");
125 ctf_set_errno (fp, ECTF_NOTREF);
126 break;
127 }
128
129 goto err;
130 }
131
132 /* Slices get a different print representation. */
133
134 if (ctf_is_slice (fp, id, &enc))
135 {
136 ctf_type_encoding (fp, id, &enc);
137 if (asprintf (&bit, " %s%lx: [slice 0x%x:0x%x]%s",
138 nonroot_leader, id, enc.cte_offset, enc.cte_bits,
139 nonroot_trailer) < 0)
140 goto oom;
141 }
142 else
143 {
144 if (asprintf (&bit, " %s%lx: %s (size 0x%lx)%s", nonroot_leader,
145 id, buf[0] == '\0' ? "(nameless)" : buf,
146 (unsigned long) ctf_type_size (fp, id),
147 nonroot_trailer) < 0)
148 goto oom;
149 }
150 free (buf);
151 buf = NULL;
152 str = str_append (str, bit);
153 free (bit);
154 bit = NULL;
155
156 new_id = ctf_type_reference (fp, id);
157 if (new_id != CTF_ERR)
158 str = str_append (str, " ->");
159 } while (new_id != CTF_ERR);
160
161 if (ctf_errno (fp) != ECTF_NOTREF)
162 {
163 free (str);
164 return NULL;
165 }
166
167 return str;
168
169 oom:
170 ctf_set_errno (fp, errno);
171 err:
172 free (buf);
173 free (str);
174 free (bit);
175 return NULL;
176 }
177
178 /* Dump one string field from the file header into the cds_items. */
179 static int
180 ctf_dump_header_strfield (ctf_file_t *fp, ctf_dump_state_t *state,
181 const char *name, uint32_t value)
182 {
183 char *str;
184 if (value)
185 {
186 if (asprintf (&str, "%s: %s\n", name, ctf_strptr (fp, value)) < 0)
187 goto err;
188 ctf_dump_append (state, str);
189 }
190 return 0;
191
192 err:
193 return (ctf_set_errno (fp, errno));
194 }
195
196 /* Dump one section-offset field from the file header into the cds_items. */
197 static int
198 ctf_dump_header_sectfield (ctf_file_t *fp, ctf_dump_state_t *state,
199 const char *sect, uint32_t off, uint32_t nextoff)
200 {
201 char *str;
202 if (nextoff - off)
203 {
204 if (asprintf (&str, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect,
205 (unsigned long) off, (unsigned long) (nextoff - 1),
206 (unsigned long) (nextoff - off)) < 0)
207 goto err;
208 ctf_dump_append (state, str);
209 }
210 return 0;
211
212 err:
213 return (ctf_set_errno (fp, errno));
214 }
215
216 /* Dump the file header into the cds_items. */
217 static int
218 ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state)
219 {
220 char *str;
221 const ctf_header_t *hp = fp->ctf_header;
222 const char *vertab[] =
223 {
224 NULL, "CTF_VERSION_1",
225 "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
226 "boundaries)",
227 "CTF_VERSION_2",
228 "CTF_VERSION_3", NULL
229 };
230 const char *verstr = NULL;
231
232 if (asprintf (&str, "Magic number: %x\n", hp->cth_magic) < 0)
233 goto err;
234 ctf_dump_append (state, str);
235
236 if (hp->cth_version <= CTF_VERSION)
237 verstr = vertab[hp->cth_version];
238
239 if (verstr == NULL)
240 verstr = "(not a valid version)";
241
242 if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,
243 verstr) < 0)
244 goto err;
245 ctf_dump_append (state, str);
246
247 /* Everything else is only printed if present. */
248
249 /* The flags are unusual in that they represent the ctf_file_t *in memory*:
250 flags representing compression, etc, are turned off as the file is
251 decompressed. So we store a copy of the flags before they are changed, for
252 the dumper. */
253
254 if (fp->ctf_openflags > 0)
255 {
256 if (fp->ctf_openflags)
257 if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags,
258 fp->ctf_openflags & CTF_F_COMPRESS ? "CTF_F_COMPRESS"
259 : "") < 0)
260 goto err;
261 ctf_dump_append (state, str);
262 }
263
264 if (ctf_dump_header_strfield (fp, state, "Parent label",
265 hp->cth_parlabel) < 0)
266 goto err;
267
268 if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)
269 goto err;
270
271 if (ctf_dump_header_strfield (fp, state, "Compilation unit name",
272 hp->cth_cuname) < 0)
273 goto err;
274
275 if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
276 hp->cth_objtoff) < 0)
277 goto err;
278
279 if (ctf_dump_header_sectfield (fp, state, "Data object section",
280 hp->cth_objtoff, hp->cth_funcoff) < 0)
281 goto err;
282
283 if (ctf_dump_header_sectfield (fp, state, "Function info section",
284 hp->cth_funcoff, hp->cth_varoff) < 0)
285 goto err;
286
287 if (ctf_dump_header_sectfield (fp, state, "Variable section",
288 hp->cth_varoff, hp->cth_typeoff) < 0)
289 goto err;
290
291 if (ctf_dump_header_sectfield (fp, state, "Type section",
292 hp->cth_typeoff, hp->cth_stroff) < 0)
293 goto err;
294
295 if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,
296 hp->cth_stroff + hp->cth_strlen + 1) < 0)
297 goto err;
298
299 return 0;
300 err:
301 return (ctf_set_errno (fp, errno));
302 }
303
304 /* Dump a single label into the cds_items. */
305
306 static int
307 ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
308 void *arg)
309 {
310 char *str;
311 char *typestr;
312 ctf_dump_state_t *state = arg;
313
314 if (asprintf (&str, "%s -> ", name) < 0)
315 return (ctf_set_errno (state->cds_fp, errno));
316
317 if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
318 CTF_ADD_ROOT)) == NULL)
319 {
320 free (str);
321 return -1; /* errno is set for us. */
322 }
323
324 str = str_append (str, typestr);
325 free (typestr);
326
327 ctf_dump_append (state, str);
328 return 0;
329 }
330
331 /* Dump all the object entries into the cds_items. (There is no iterator for
332 this section, so we just do it in a loop, and this function handles all of
333 them, rather than only one. */
334
335 static int
336 ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state)
337 {
338 size_t i;
339
340 for (i = 0; i < fp->ctf_nsyms; i++)
341 {
342 char *str;
343 char *typestr;
344 const char *sym_name;
345 ctf_id_t type;
346
347 if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) == CTF_ERR)
348 switch (ctf_errno (state->cds_fp))
349 {
350 /* Most errors are just an indication that this symbol is not a data
351 symbol, but this one indicates that we were called wrong, on a
352 CTF file with no associated symbol table. */
353 case ECTF_NOSYMTAB:
354 return -1;
355 case ECTF_NOTDATA:
356 case ECTF_NOTYPEDAT:
357 continue;
358 }
359
360 /* Variable name. */
361 sym_name = ctf_lookup_symbol_name (fp, i);
362 if (sym_name[0] == '\0')
363 {
364 if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0)
365 return (ctf_set_errno (fp, errno));
366 }
367 else
368 {
369 if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0)
370 return (ctf_set_errno (fp, errno));
371 }
372
373 /* Variable type. */
374 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
375 CTF_ADD_ROOT)) == NULL)
376 {
377 free (str);
378 return -1; /* errno is set for us. */
379 }
380
381 str = str_append (str, typestr);
382 free (typestr);
383
384 ctf_dump_append (state, str);
385 }
386 return 0;
387 }
388
389 /* Dump all the function entries into the cds_items. (As above, there is no
390 iterator for this section.) */
391
392 static int
393 ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
394 {
395 size_t i;
396
397 for (i = 0; i < fp->ctf_nsyms; i++)
398 {
399 char *str;
400 char *bit;
401 const char *err;
402 const char *sym_name;
403 ctf_funcinfo_t fi;
404 ctf_id_t type;
405 size_t j;
406 ctf_id_t *args;
407
408 if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
409 switch (ctf_errno (state->cds_fp))
410 {
411 /* Most errors are just an indication that this symbol is not a data
412 symbol, but this one indicates that we were called wrong, on a
413 CTF file with no associated symbol table. */
414 case ECTF_NOSYMTAB:
415 return -1;
416 case ECTF_NOTDATA:
417 case ECTF_NOTFUNC:
418 case ECTF_NOFUNCDAT:
419 continue;
420 }
421 if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
422 return (ctf_set_errno (fp, ENOMEM));
423
424 /* Return type. */
425 if ((str = ctf_type_aname (state->cds_fp, type)) == NULL)
426 {
427 err = "look up return type";
428 goto err;
429 }
430
431 str = str_append (str, " ");
432
433 /* Function name. */
434
435 sym_name = ctf_lookup_symbol_name (fp, i);
436 if (sym_name[0] == '\0')
437 {
438 if (asprintf (&bit, "0x%lx ", (unsigned long) i) < 0)
439 goto oom;
440 }
441 else
442 {
443 if (asprintf (&bit, "%s (0x%lx) ", sym_name, (unsigned long) i) < 0)
444 goto oom;
445 }
446 str = str_append (str, bit);
447 str = str_append (str, " (");
448 free (bit);
449
450 /* Function arguments. */
451
452 if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0)
453 {
454 err = "look up argument type";
455 goto err;
456 }
457
458 for (j = 0; j < fi.ctc_argc; j++)
459 {
460 if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL)
461 {
462 err = "look up argument type name";
463 goto err;
464 }
465 str = str_append (str, bit);
466 if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG))
467 str = str_append (str, ", ");
468 free (bit);
469 }
470
471 if (fi.ctc_flags & CTF_FUNC_VARARG)
472 str = str_append (str, "...");
473 str = str_append (str, ")");
474
475 free (args);
476 ctf_dump_append (state, str);
477 continue;
478
479 oom:
480 free (args);
481 free (str);
482 return (ctf_set_errno (fp, errno));
483 err:
484 ctf_dprintf ("Cannot %s dumping function type for symbol 0x%li: %s\n",
485 err, (unsigned long) i,
486 ctf_errmsg (ctf_errno (state->cds_fp)));
487 free (args);
488 free (str);
489 return -1; /* errno is set for us. */
490 }
491 return 0;
492 }
493
494 /* Dump a single variable into the cds_items. */
495 static int
496 ctf_dump_var (const char *name, ctf_id_t type, void *arg)
497 {
498 char *str;
499 char *typestr;
500 ctf_dump_state_t *state = arg;
501
502 if (asprintf (&str, "%s -> ", name) < 0)
503 return (ctf_set_errno (state->cds_fp, errno));
504
505 if ((typestr = ctf_dump_format_type (state->cds_fp, type,
506 CTF_ADD_ROOT)) == NULL)
507 {
508 free (str);
509 return -1; /* errno is set for us. */
510 }
511
512 str = str_append (str, typestr);
513 free (typestr);
514
515 ctf_dump_append (state, str);
516 return 0;
517 }
518
519 /* Dump a single member into the string in the membstate. */
520 static int
521 ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
522 int depth, void *arg)
523 {
524 ctf_dump_membstate_t *state = arg;
525 char *typestr = NULL;
526 char *bit = NULL;
527 ctf_encoding_t ep;
528 ssize_t i;
529
530 for (i = 0; i < depth; i++)
531 *state->cdm_str = str_append (*state->cdm_str, " ");
532
533 if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
534 {
535 if (id == 0 || ctf_errno (state->cdm_fp) == ECTF_NONREPRESENTABLE)
536 {
537 if (asprintf (&bit, " [0x%lx] (type not represented in CTF)",
538 offset) < 0)
539 goto oom;
540
541 *state->cdm_str = str_append (*state->cdm_str, bit);
542 free (typestr);
543 free (bit);
544 return 0;
545 }
546
547 goto oom;
548 }
549
550 if (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s %s (aligned at 0x%lx",
551 offset, id, ctf_type_kind (state->cdm_fp, id), typestr, name,
552 (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0)
553 goto oom;
554 *state->cdm_str = str_append (*state->cdm_str, bit);
555 free (typestr);
556 free (bit);
557 typestr = NULL;
558 bit = NULL;
559
560 if ((ctf_type_kind (state->cdm_fp, id) == CTF_K_INTEGER)
561 || (ctf_type_kind (state->cdm_fp, id) == CTF_K_FLOAT)
562 || (ctf_is_slice (state->cdm_fp, id, &ep) == CTF_K_ENUM))
563 {
564 ctf_type_encoding (state->cdm_fp, id, &ep);
565 if (asprintf (&bit, ", format 0x%x, offset:bits 0x%x:0x%x", ep.cte_format,
566 ep.cte_offset, ep.cte_bits) < 0)
567 goto oom;
568 *state->cdm_str = str_append (*state->cdm_str, bit);
569 free (bit);
570 bit = NULL;
571 }
572
573 *state->cdm_str = str_append (*state->cdm_str, ")\n");
574 return 0;
575
576 oom:
577 free (typestr);
578 free (bit);
579 return (ctf_set_errno (state->cdm_fp, errno));
580 }
581
582 /* Dump a single type into the cds_items. */
583 static int
584 ctf_dump_type (ctf_id_t id, int flag, void *arg)
585 {
586 char *str;
587 const char *err;
588 ctf_dump_state_t *state = arg;
589 ctf_dump_membstate_t membstate = { &str, state->cds_fp };
590 size_t len;
591
592 if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL)
593 {
594 err = "format type";
595 goto err;
596 }
597
598 str = str_append (str, "\n");
599 if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
600 {
601 if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
602 {
603 ctf_dump_append (state, str);
604 return 0;
605 }
606 err = "visit members";
607 goto err;
608 }
609
610 /* Trim off the last linefeed added by ctf_dump_member(). */
611 len = strlen (str);
612 if (str[len-1] == '\n')
613 str[len-1] = '\0';
614
615 ctf_dump_append (state, str);
616 return 0;
617
618 err:
619 ctf_dprintf ("Cannot %s dumping type 0x%lx: %s\n", err, id,
620 ctf_errmsg (ctf_errno (state->cds_fp)));
621 free (str);
622 return -1; /* errno is set for us. */
623 }
624
625 /* Dump the string table into the cds_items. */
626
627 static int
628 ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state)
629 {
630 const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs;
631
632 for (; s < fp->ctf_str[CTF_STRTAB_0].cts_strs +
633 fp->ctf_str[CTF_STRTAB_0].cts_len;)
634 {
635 char *str;
636 if (asprintf (&str, "%lx: %s",
637 (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs),
638 s) < 0)
639 return (ctf_set_errno (fp, errno));
640 ctf_dump_append (state, str);
641 s += strlen (s) + 1;
642 }
643
644 return 0;
645 }
646
647 /* Dump a particular section of a CTF file, in textual form. Call with a
648 pointer to a NULL STATE: each call emits a dynamically allocated string
649 containing a description of one entity in the specified section, in order.
650 Only the first call (with a NULL state) may vary SECT. Once the CTF section
651 has been entirely dumped, the call returns NULL and frees and annuls the
652 STATE, ready for another section to be dumped. The returned textual content
653 may span multiple lines: between each call the FUNC is called with one
654 textual line at a time, and should return a suitably decorated line (it can
655 allocate a new one and return it if it likes). */
656
657 char *
658 ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
659 ctf_dump_decorate_f *func, void *arg)
660 {
661 char *str;
662 char *line;
663 ctf_dump_state_t *state = NULL;
664
665 if (*statep == NULL)
666 {
667 /* Data collection. Transforming a call-at-a-time iterator into a
668 return-at-a-time iterator in a language without call/cc is annoying. It
669 is easiest to simply collect everything at once and then return it bit
670 by bit. The first call will take (much) longer than otherwise, but the
671 amortized time needed is the same. */
672
673 if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL)
674 {
675 ctf_set_errno (fp, ENOMEM);
676 goto end;
677 }
678 state = *statep;
679
680 memset (state, 0, sizeof (struct ctf_dump_state));
681 state->cds_fp = fp;
682 state->cds_sect = sect;
683
684 switch (sect)
685 {
686 case CTF_SECT_HEADER:
687 ctf_dump_header (fp, state);
688 break;
689 case CTF_SECT_LABEL:
690 if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
691 {
692 if (ctf_errno (fp) != ECTF_NOLABELDATA)
693 goto end; /* errno is set for us. */
694 ctf_set_errno (fp, 0);
695 }
696 break;
697 case CTF_SECT_OBJT:
698 if (ctf_dump_objts (fp, state) < 0)
699 goto end; /* errno is set for us. */
700 break;
701 case CTF_SECT_FUNC:
702 if (ctf_dump_funcs (fp, state) < 0)
703 goto end; /* errno is set for us. */
704 break;
705 case CTF_SECT_VAR:
706 if (ctf_variable_iter (fp, ctf_dump_var, state) < 0)
707 goto end; /* errno is set for us. */
708 break;
709 case CTF_SECT_TYPE:
710 if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0)
711 goto end; /* errno is set for us. */
712 break;
713 case CTF_SECT_STR:
714 ctf_dump_str (fp, state);
715 break;
716 default:
717 ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN);
718 goto end;
719 }
720 }
721 else
722 {
723 state = *statep;
724
725 if (state->cds_sect != sect)
726 {
727 ctf_set_errno (fp, ECTF_DUMPSECTCHANGED);
728 goto end;
729 }
730 }
731
732 if (state->cds_current == NULL)
733 state->cds_current = ctf_list_next (&state->cds_items);
734 else
735 state->cds_current = ctf_list_next (state->cds_current);
736
737 if (state->cds_current == NULL)
738 goto end;
739
740 /* Hookery. There is some extra complexity to preserve linefeeds within each
741 item while removing linefeeds at the end. */
742 if (func)
743 {
744 size_t len;
745
746 str = NULL;
747 for (line = state->cds_current->cdi_item; line && *line; )
748 {
749 char *nline = line;
750 char *ret;
751
752 nline = strchr (line, '\n');
753 if (nline)
754 nline[0] = '\0';
755
756 ret = func (sect, line, arg);
757 str = str_append (str, ret);
758 str = str_append (str, "\n");
759 if (ret != line)
760 free (ret);
761
762 if (nline)
763 {
764 nline[0] = '\n';
765 nline++;
766 }
767
768 line = nline;
769 }
770
771 len = strlen (str);
772
773 if (str[len-1] == '\n')
774 str[len-1] = '\0';
775 }
776 else
777 {
778 str = strdup (state->cds_current->cdi_item);
779 if (!str)
780 {
781 ctf_set_errno (fp, ENOMEM);
782 return str;
783 }
784 }
785
786 ctf_set_errno (fp, 0);
787 return str;
788
789 end:
790 ctf_dump_free (state);
791 free (state);
792 ctf_set_errno (fp, 0);
793 *statep = NULL;
794 return NULL;
795 }
This page took 0.04945 seconds and 4 git commands to generate.