Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
trace-seq.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <[email protected]>
3  *
4  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation;
8  * version 2.1 of the License (not later!)
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20  */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 
26 #include "event-parse.h"
27 #include "event-utils.h"
28 
29 /*
30  * The TRACE_SEQ_POISON is to catch the use of using
31  * a trace_seq structure after it was destroyed.
32  */
33 #define TRACE_SEQ_POISON ((void *)0xdeadbeef)
34 #define TRACE_SEQ_CHECK(s) \
35 do { \
36  if ((s)->buffer == TRACE_SEQ_POISON) \
37  die("Usage of trace_seq after it was destroyed"); \
38 } while (0)
39 
44 void trace_seq_init(struct trace_seq *s)
45 {
46  s->len = 0;
47  s->readpos = 0;
50 }
51 
59 {
60  if (!s)
61  return;
62  TRACE_SEQ_CHECK(s);
63  free(s->buffer);
65 }
66 
67 static void expand_buffer(struct trace_seq *s)
68 {
70  s->buffer = realloc(s->buffer, s->buffer_size);
71  if (!s->buffer)
72  die("Can't allocate trace_seq buffer memory");
73 }
74 
89 int
90 trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
91 {
92  va_list ap;
93  int len;
94  int ret;
95 
96  TRACE_SEQ_CHECK(s);
97 
98  try_again:
99  len = (s->buffer_size - 1) - s->len;
100 
101  va_start(ap, fmt);
102  ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
103  va_end(ap);
104 
105  if (ret >= len) {
106  expand_buffer(s);
107  goto try_again;
108  }
109 
110  s->len += ret;
111 
112  return 1;
113 }
114 
126 int
127 trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
128 {
129  int len;
130  int ret;
131 
132  TRACE_SEQ_CHECK(s);
133 
134  try_again:
135  len = (s->buffer_size - 1) - s->len;
136 
137  ret = vsnprintf(s->buffer + s->len, len, fmt, args);
138 
139  if (ret >= len) {
140  expand_buffer(s);
141  goto try_again;
142  }
143 
144  s->len += ret;
145 
146  return len;
147 }
148 
159 int trace_seq_puts(struct trace_seq *s, const char *str)
160 {
161  int len;
162 
163  TRACE_SEQ_CHECK(s);
164 
165  len = strlen(str);
166 
167  while (len > ((s->buffer_size - 1) - s->len))
168  expand_buffer(s);
169 
170  memcpy(s->buffer + s->len, str, len);
171  s->len += len;
172 
173  return len;
174 }
175 
176 int trace_seq_putc(struct trace_seq *s, unsigned char c)
177 {
178  TRACE_SEQ_CHECK(s);
179 
180  while (s->len >= (s->buffer_size - 1))
181  expand_buffer(s);
182 
183  s->buffer[s->len++] = c;
184 
185  return 1;
186 }
187 
189 {
190  TRACE_SEQ_CHECK(s);
191 
192  /* There's always one character left on the buffer */
193  s->buffer[s->len] = 0;
194 }
195 
197 {
198  TRACE_SEQ_CHECK(s);
199  return printf("%.*s", s->len, s->buffer);
200 }