]> Git Repo - binutils.git/blob - libctf/ctf-dump.c
libctf, dump: migrate towards dumping errors rather than truncation
[binutils.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   ctf_err_warn (fp, 1, "Cannot format name dumping type 0x%lx: %s", id,
173                 ctf_errmsg (ctf_errno (fp)));
174   free (buf);
175   free (str);
176   free (bit);
177   return NULL;
178 }
179
180 /* Dump one string field from the file header into the cds_items.  */
181 static int
182 ctf_dump_header_strfield (ctf_file_t *fp, ctf_dump_state_t *state,
183                           const char *name, uint32_t value)
184 {
185   char *str;
186   if (value)
187     {
188       if (asprintf (&str, "%s: %s\n", name, ctf_strptr (fp, value)) < 0)
189         goto err;
190       ctf_dump_append (state, str);
191     }
192   return 0;
193
194  err:
195   return (ctf_set_errno (fp, errno));
196 }
197
198 /* Dump one section-offset field from the file header into the cds_items.  */
199 static int
200 ctf_dump_header_sectfield (ctf_file_t *fp, ctf_dump_state_t *state,
201                            const char *sect, uint32_t off, uint32_t nextoff)
202 {
203   char *str;
204   if (nextoff - off)
205     {
206       if (asprintf (&str, "%s:\t0x%lx -- 0x%lx (0x%lx bytes)\n", sect,
207                     (unsigned long) off, (unsigned long) (nextoff - 1),
208                     (unsigned long) (nextoff - off)) < 0)
209         goto err;
210       ctf_dump_append (state, str);
211     }
212   return 0;
213
214  err:
215   return (ctf_set_errno (fp, errno));
216 }
217
218 /* Dump the file header into the cds_items.  */
219 static int
220 ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state)
221 {
222   char *str;
223   const ctf_header_t *hp = fp->ctf_header;
224   const char *vertab[] =
225     {
226      NULL, "CTF_VERSION_1",
227      "CTF_VERSION_1_UPGRADED_3 (latest format, version 1 type "
228      "boundaries)",
229      "CTF_VERSION_2",
230      "CTF_VERSION_3", NULL
231     };
232   const char *verstr = NULL;
233
234   if (asprintf (&str, "Magic number: %x\n", hp->cth_magic) < 0)
235       goto err;
236   ctf_dump_append (state, str);
237
238   if (hp->cth_version <= CTF_VERSION)
239     verstr = vertab[hp->cth_version];
240
241   if (verstr == NULL)
242     verstr = "(not a valid version)";
243
244   if (asprintf (&str, "Version: %i (%s)\n", hp->cth_version,
245                 verstr) < 0)
246     goto err;
247   ctf_dump_append (state, str);
248
249   /* Everything else is only printed if present.  */
250
251   /* The flags are unusual in that they represent the ctf_file_t *in memory*:
252      flags representing compression, etc, are turned off as the file is
253      decompressed.  So we store a copy of the flags before they are changed, for
254      the dumper.  */
255
256   if (fp->ctf_openflags > 0)
257     {
258       if (fp->ctf_openflags)
259         if (asprintf (&str, "Flags: 0x%x (%s)", fp->ctf_openflags,
260                       fp->ctf_openflags & CTF_F_COMPRESS ? "CTF_F_COMPRESS"
261                                                          : "") < 0)
262         goto err;
263       ctf_dump_append (state, str);
264     }
265
266   if (ctf_dump_header_strfield (fp, state, "Parent label",
267                                 hp->cth_parlabel) < 0)
268     goto err;
269
270   if (ctf_dump_header_strfield (fp, state, "Parent name", hp->cth_parname) < 0)
271     goto err;
272
273   if (ctf_dump_header_strfield (fp, state, "Compilation unit name",
274                                 hp->cth_cuname) < 0)
275     goto err;
276
277   if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
278                                  hp->cth_objtoff) < 0)
279     goto err;
280
281   if (ctf_dump_header_sectfield (fp, state, "Data object section",
282                                  hp->cth_objtoff, hp->cth_funcoff) < 0)
283     goto err;
284
285   if (ctf_dump_header_sectfield (fp, state, "Function info section",
286                                  hp->cth_funcoff, hp->cth_varoff) < 0)
287     goto err;
288
289   if (ctf_dump_header_sectfield (fp, state, "Variable section",
290                                  hp->cth_varoff, hp->cth_typeoff) < 0)
291     goto err;
292
293   if (ctf_dump_header_sectfield (fp, state, "Type section",
294                                  hp->cth_typeoff, hp->cth_stroff) < 0)
295     goto err;
296
297   if (ctf_dump_header_sectfield (fp, state, "String section", hp->cth_stroff,
298                                  hp->cth_stroff + hp->cth_strlen + 1) < 0)
299     goto err;
300
301   return 0;
302  err:
303   return (ctf_set_errno (fp, errno));
304 }
305
306 /* Dump a single label into the cds_items.  */
307
308 static int
309 ctf_dump_label (const char *name, const ctf_lblinfo_t *info,
310                 void *arg)
311 {
312   char *str;
313   char *typestr;
314   ctf_dump_state_t *state = arg;
315
316   if (asprintf (&str, "%s -> ", name) < 0)
317     return (ctf_set_errno (state->cds_fp, errno));
318
319   if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type,
320                                        CTF_ADD_ROOT)) == NULL)
321     {
322       free (str);
323       return 0;                         /* Swallow the error.  */
324     }
325
326   str = str_append (str, typestr);
327   free (typestr);
328
329   ctf_dump_append (state, str);
330   return 0;
331 }
332
333 /* Dump all the object entries into the cds_items.  (There is no iterator for
334    this section, so we just do it in a loop, and this function handles all of
335    them, rather than only one.  */
336
337 static int
338 ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state)
339 {
340   size_t i;
341
342   for (i = 0; i < fp->ctf_nsyms; i++)
343     {
344       char *str;
345       char *typestr;
346       const char *sym_name;
347       ctf_id_t type;
348
349       if ((type = ctf_lookup_by_symbol (state->cds_fp, i)) == CTF_ERR)
350         switch (ctf_errno (state->cds_fp))
351           {
352             /* Most errors are just an indication that this symbol is not a data
353                symbol, but this one indicates that we were called wrong, on a
354                CTF file with no associated symbol table.  */
355           case ECTF_NOSYMTAB:
356             return -1;
357           case ECTF_NOTDATA:
358           case ECTF_NOTYPEDAT:
359             continue;
360           }
361
362       /* Variable name.  */
363       sym_name = ctf_lookup_symbol_name (fp, i);
364       if (sym_name[0] == '\0')
365         {
366           if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0)
367             return (ctf_set_errno (fp, errno));
368         }
369       else
370         {
371           if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0)
372             return (ctf_set_errno (fp, errno));
373         }
374
375       /* Variable type.  */
376       if ((typestr = ctf_dump_format_type (state->cds_fp, type,
377                                            CTF_ADD_ROOT)) == NULL)
378         {
379           free (str);
380           return 0;                     /* Swallow the error.  */
381         }
382
383       str = str_append (str, typestr);
384       free (typestr);
385
386       ctf_dump_append (state, str);
387     }
388   return 0;
389 }
390
391 /* Dump all the function entries into the cds_items.  (As above, there is no
392    iterator for this section.)  */
393
394 static int
395 ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
396 {
397   size_t i;
398
399   for (i = 0; i < fp->ctf_nsyms; i++)
400     {
401       char *str;
402       char *bit = NULL;
403       const char *err;
404       const char *sym_name;
405       ctf_funcinfo_t fi;
406       ctf_id_t type;
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
422       /* Return type and all args.  */
423       if ((bit = ctf_type_aname (state->cds_fp, type)) == NULL)
424         {
425           err = "look up return type";
426           goto err;
427         }
428
429       /* Replace in the returned string, dropping in the function name.  */
430
431       sym_name = ctf_lookup_symbol_name (fp, i);
432       if (sym_name[0] != '\0')
433         {
434           char *retstar;
435           char *new_bit;
436           char *walk;
437
438           new_bit = malloc (strlen (bit) + 1 + strlen (sym_name));
439           if (!new_bit)
440             goto oom;
441
442           /* See ctf_type_aname.  */
443           retstar = strstr (bit, "(*) (");
444           if (!ctf_assert (fp, retstar))
445             goto assert_err;
446           retstar += 2;                 /* After the '*' */
447
448           /* C is not good at search-and-replace.  */
449           walk = new_bit;
450           memcpy (walk, bit, retstar - bit);
451           walk += (retstar - bit);
452           strcpy (walk, sym_name);
453           walk += strlen (sym_name);
454           strcpy (walk, retstar);
455
456           free (bit);
457           bit = new_bit;
458         }
459
460       if (asprintf (&str, "Symbol 0x%lx: %s", (unsigned long) i, bit) < 0)
461         goto oom;
462       free (bit);
463
464       ctf_dump_append (state, str);
465       continue;
466
467     err:
468       ctf_err_warn (fp, 1, "Cannot %s dumping function type for "
469                     "symbol 0x%li: %s", err, (unsigned long) i,
470                     ctf_errmsg (ctf_errno (state->cds_fp)));
471       free (bit);
472       return -1;                /* errno is set for us.  */
473
474     oom:
475       free (bit);
476       return (ctf_set_errno (fp, errno));
477
478     assert_err:
479       free (bit);
480       return -1;                /* errno is set for us.  */
481     }
482   return 0;
483 }
484
485 /* Dump a single variable into the cds_items.  */
486 static int
487 ctf_dump_var (const char *name, ctf_id_t type, void *arg)
488 {
489   char *str;
490   char *typestr;
491   ctf_dump_state_t *state = arg;
492
493   if (asprintf (&str, "%s -> ", name) < 0)
494     return (ctf_set_errno (state->cds_fp, errno));
495
496   if ((typestr = ctf_dump_format_type (state->cds_fp, type,
497                                        CTF_ADD_ROOT)) == NULL)
498     {
499       free (str);
500       return 0;                 /* Swallow the error.  */
501     }
502
503   str = str_append (str, typestr);
504   free (typestr);
505
506   ctf_dump_append (state, str);
507   return 0;
508 }
509
510 /* Dump a single member into the string in the membstate.  */
511 static int
512 ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset,
513                   int depth, void *arg)
514 {
515   ctf_dump_membstate_t *state = arg;
516   char *typestr = NULL;
517   char *bit = NULL;
518   ctf_encoding_t ep;
519   ssize_t i;
520
521   for (i = 0; i < depth; i++)
522     *state->cdm_str = str_append (*state->cdm_str, "    ");
523
524   if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL)
525     {
526       if (id == 0 || ctf_errno (state->cdm_fp) == ECTF_NONREPRESENTABLE)
527         {
528           if (asprintf (&bit, "    [0x%lx] (type not represented in CTF)",
529                         offset) < 0)
530             goto oom;
531
532           *state->cdm_str = str_append (*state->cdm_str, bit);
533           free (typestr);
534           free (bit);
535           return 0;
536         }
537
538       goto oom;
539     }
540
541   if (asprintf (&bit, "    [0x%lx] (ID 0x%lx) (kind %i) %s %s (aligned at 0x%lx",
542                 offset, id, ctf_type_kind (state->cdm_fp, id), typestr, name,
543                 (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0)
544     goto oom;
545   *state->cdm_str = str_append (*state->cdm_str, bit);
546   free (typestr);
547   free (bit);
548   typestr = NULL;
549   bit = NULL;
550
551   if ((ctf_type_kind (state->cdm_fp, id) == CTF_K_INTEGER)
552       || (ctf_type_kind (state->cdm_fp, id) == CTF_K_FLOAT)
553       || (ctf_is_slice (state->cdm_fp, id, &ep) == CTF_K_ENUM))
554     {
555       ctf_type_encoding (state->cdm_fp, id, &ep);
556       if (asprintf (&bit, ", format 0x%x, offset:bits 0x%x:0x%x", ep.cte_format,
557                     ep.cte_offset, ep.cte_bits) < 0)
558         goto oom;
559       *state->cdm_str = str_append (*state->cdm_str, bit);
560       free (bit);
561       bit = NULL;
562     }
563
564   *state->cdm_str = str_append (*state->cdm_str, ")\n");
565   return 0;
566
567  oom:
568   free (typestr);
569   free (bit);
570   return (ctf_set_errno (state->cdm_fp, errno));
571 }
572
573 /* Dump a single type into the cds_items.  */
574 static int
575 ctf_dump_type (ctf_id_t id, int flag, void *arg)
576 {
577   char *str;
578   const char *err;
579   ctf_dump_state_t *state = arg;
580   ctf_dump_membstate_t membstate = { &str, state->cds_fp };
581   size_t len;
582
583   if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL)
584     goto err_nomsg;             /* Error already logged for us.  */
585
586   str = str_append (str, "\n");
587   if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0)
588     {
589       if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE)
590         {
591           ctf_dump_append (state, str);
592           return 0;
593         }
594       err = "visit members";
595       goto err;
596     }
597
598   /* Trim off the last linefeed added by ctf_dump_member().  */
599   len = strlen (str);
600   if (str[len-1] == '\n')
601     str[len-1] = '\0';
602
603   ctf_dump_append (state, str);
604   return 0;
605
606  err:
607   ctf_err_warn (state->cds_fp, 1, "Cannot %s dumping type 0x%lx: %s",
608                 err, id, ctf_errmsg (ctf_errno (state->cds_fp)));
609  err_nomsg:
610   free (str);
611   return 0;                             /* Swallow the error.  */
612 }
613
614 /* Dump the string table into the cds_items.  */
615
616 static int
617 ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state)
618 {
619   const char *s = fp->ctf_str[CTF_STRTAB_0].cts_strs;
620
621   for (; s < fp->ctf_str[CTF_STRTAB_0].cts_strs +
622          fp->ctf_str[CTF_STRTAB_0].cts_len;)
623     {
624       char *str;
625       if (asprintf (&str, "%lx: %s",
626                     (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs),
627                     s) < 0)
628         return (ctf_set_errno (fp, errno));
629       ctf_dump_append (state, str);
630       s += strlen (s) + 1;
631     }
632
633   return 0;
634 }
635
636 /* Dump a particular section of a CTF file, in textual form.  Call with a
637    pointer to a NULL STATE: each call emits a dynamically allocated string
638    containing a description of one entity in the specified section, in order.
639    Only the first call (with a NULL state) may vary SECT.  Once the CTF section
640    has been entirely dumped, the call returns NULL and frees and annuls the
641    STATE, ready for another section to be dumped.  The returned textual content
642    may span multiple lines: between each call the FUNC is called with one
643    textual line at a time, and should return a suitably decorated line (it can
644    allocate a new one and return it if it likes).  */
645
646 char *
647 ctf_dump (ctf_file_t *fp, ctf_dump_state_t **statep, ctf_sect_names_t sect,
648           ctf_dump_decorate_f *func, void *arg)
649 {
650   char *str;
651   char *line;
652   ctf_dump_state_t *state = NULL;
653
654   if (*statep == NULL)
655     {
656       /* Data collection.  Transforming a call-at-a-time iterator into a
657          return-at-a-time iterator in a language without call/cc is annoying. It
658          is easiest to simply collect everything at once and then return it bit
659          by bit.  The first call will take (much) longer than otherwise, but the
660          amortized time needed is the same.  */
661
662       if ((*statep = malloc (sizeof (struct ctf_dump_state))) == NULL)
663         {
664           ctf_set_errno (fp, ENOMEM);
665           goto end;
666         }
667       state = *statep;
668
669       memset (state, 0, sizeof (struct ctf_dump_state));
670       state->cds_fp = fp;
671       state->cds_sect = sect;
672
673       switch (sect)
674         {
675         case CTF_SECT_HEADER:
676           ctf_dump_header (fp, state);
677           break;
678         case CTF_SECT_LABEL:
679           if (ctf_label_iter (fp, ctf_dump_label, state) < 0)
680             {
681               if (ctf_errno (fp) != ECTF_NOLABELDATA)
682                 goto end;               /* errno is set for us.  */
683               ctf_set_errno (fp, 0);
684             }
685           break;
686         case CTF_SECT_OBJT:
687           if (ctf_dump_objts (fp, state) < 0)
688             goto end;                   /* errno is set for us.  */
689           break;
690         case CTF_SECT_FUNC:
691           if (ctf_dump_funcs (fp, state) < 0)
692             goto end;                   /* errno is set for us.  */
693           break;
694         case CTF_SECT_VAR:
695           if (ctf_variable_iter (fp, ctf_dump_var, state) < 0)
696             goto end;                   /* errno is set for us.  */
697           break;
698         case CTF_SECT_TYPE:
699           if (ctf_type_iter_all (fp, ctf_dump_type, state) < 0)
700             goto end;                   /* errno is set for us.  */
701           break;
702         case CTF_SECT_STR:
703           ctf_dump_str (fp, state);
704           break;
705         default:
706           ctf_set_errno (fp, ECTF_DUMPSECTUNKNOWN);
707           goto end;
708         }
709     }
710   else
711     {
712       state = *statep;
713
714       if (state->cds_sect != sect)
715         {
716           ctf_set_errno (fp, ECTF_DUMPSECTCHANGED);
717           goto end;
718         }
719     }
720
721   if (state->cds_current == NULL)
722     state->cds_current = ctf_list_next (&state->cds_items);
723   else
724     state->cds_current = ctf_list_next (state->cds_current);
725
726   if (state->cds_current == NULL)
727     goto end;
728
729   /* Hookery.  There is some extra complexity to preserve linefeeds within each
730      item while removing linefeeds at the end.  */
731   if (func)
732     {
733       size_t len;
734
735       str = NULL;
736       for (line = state->cds_current->cdi_item; line && *line; )
737         {
738           char *nline = line;
739           char *ret;
740
741           nline = strchr (line, '\n');
742           if (nline)
743             nline[0] = '\0';
744
745           ret = func (sect, line, arg);
746           str = str_append (str, ret);
747           str = str_append (str, "\n");
748           if (ret != line)
749             free (ret);
750
751           if (nline)
752             {
753               nline[0] = '\n';
754               nline++;
755             }
756
757           line = nline;
758         }
759
760       len = strlen (str);
761
762       if (str[len-1] == '\n')
763         str[len-1] = '\0';
764     }
765   else
766     {
767       str = strdup (state->cds_current->cdi_item);
768       if (!str)
769         {
770           ctf_set_errno (fp, ENOMEM);
771           return str;
772         }
773     }
774
775   ctf_set_errno (fp, 0);
776   return str;
777
778  end:
779   ctf_dump_free (state);
780   free (state);
781   ctf_set_errno (fp, 0);
782   *statep = NULL;
783   return NULL;
784 }
This page took 0.066497 seconds and 4 git commands to generate.