aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/traceevent
diff options
context:
space:
mode:
authorTzvetomir Stoyanov <tstoyanov@vmware.com>2018-10-05 12:22:25 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-10-08 14:05:37 -0400
commitbb3dd7e7c4d5e024d607c0ec06c2a2fb9408cc99 (patch)
treed2970356440791f3cd1ecaf8150e5b7786fa0e01 /tools/lib/traceevent
parentbbbab191c2c474d183e93799d008b412e97f5936 (diff)
tools lib traceevent, perf tools: Move struct tep_handler definition in a local header file
As traceevent is going to be transferred into a proper library, its local data should be protected from the library users. This patch encapsulates struct tep_handler into a local header, not visible outside of the library. It implements also a bunch of new APIs, which library users can use to access tep_handler members. Signed-off-by: Tzvetomir Stoyanov <tstoyanov@vmware.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: linux trace devel <linux-trace-devel@vger.kernel.org> Cc: tzvetomir stoyanov <tstoyanov@vmware.com> Link: http://lkml.kernel.org/r/20181005122225.522155df@gandalf.local.home Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib/traceevent')
-rw-r--r--tools/lib/traceevent/Build1
-rw-r--r--tools/lib/traceevent/event-parse-api.c275
-rw-r--r--tools/lib/traceevent/event-parse-local.h92
-rw-r--r--tools/lib/traceevent/event-parse.c2
-rw-r--r--tools/lib/traceevent/event-parse.h228
-rw-r--r--tools/lib/traceevent/event-plugin.c1
-rw-r--r--tools/lib/traceevent/parse-filter.c1
7 files changed, 400 insertions, 200 deletions
diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build
index 0050c145d806..ba54bfce0b0b 100644
--- a/tools/lib/traceevent/Build
+++ b/tools/lib/traceevent/Build
@@ -5,6 +5,7 @@ libtraceevent-y += parse-filter.o
5libtraceevent-y += parse-utils.o 5libtraceevent-y += parse-utils.o
6libtraceevent-y += kbuffer-parse.o 6libtraceevent-y += kbuffer-parse.o
7libtraceevent-y += tep_strerror.o 7libtraceevent-y += tep_strerror.o
8libtraceevent-y += event-parse-api.o
8 9
9plugin_jbd2-y += plugin_jbd2.o 10plugin_jbd2-y += plugin_jbd2.o
10plugin_hrtimer-y += plugin_hrtimer.o 11plugin_hrtimer-y += plugin_hrtimer.o
diff --git a/tools/lib/traceevent/event-parse-api.c b/tools/lib/traceevent/event-parse-api.c
new file mode 100644
index 000000000000..61f7149085ee
--- /dev/null
+++ b/tools/lib/traceevent/event-parse-api.c
@@ -0,0 +1,275 @@
1// SPDX-License-Identifier: LGPL-2.1
2/*
3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 */
6
7#include "event-parse.h"
8#include "event-parse-local.h"
9#include "event-utils.h"
10
11/**
12 * tep_get_first_event - returns the first event in the events array
13 * @tep: a handle to the tep_handle
14 *
15 * This returns pointer to the first element of the events array
16 * If @tep is NULL, NULL is returned.
17 */
18struct tep_event_format *tep_get_first_event(struct tep_handle *tep)
19{
20 if (tep && tep->events)
21 return tep->events[0];
22
23 return NULL;
24}
25
26/**
27 * tep_get_events_count - get the number of defined events
28 * @tep: a handle to the tep_handle
29 *
30 * This returns number of elements in event array
31 * If @tep is NULL, 0 is returned.
32 */
33int tep_get_events_count(struct tep_handle *tep)
34{
35 if(tep)
36 return tep->nr_events;
37 return 0;
38}
39
40/**
41 * tep_set_flag - set event parser flag
42 * @tep: a handle to the tep_handle
43 * @flag: flag, or combination of flags to be set
44 * can be any combination from enum tep_flag
45 *
46 * This sets a flag or mbination of flags from enum tep_flag
47 */
48void tep_set_flag(struct tep_handle *tep, int flag)
49{
50 if(tep)
51 tep->flags |= flag;
52}
53
54unsigned short __tep_data2host2(struct tep_handle *pevent, unsigned short data)
55{
56 unsigned short swap;
57
58 if (!pevent || pevent->host_bigendian == pevent->file_bigendian)
59 return data;
60
61 swap = ((data & 0xffULL) << 8) |
62 ((data & (0xffULL << 8)) >> 8);
63
64 return swap;
65}
66
67unsigned int __tep_data2host4(struct tep_handle *pevent, unsigned int data)
68{
69 unsigned int swap;
70
71 if (!pevent || pevent->host_bigendian == pevent->file_bigendian)
72 return data;
73
74 swap = ((data & 0xffULL) << 24) |
75 ((data & (0xffULL << 8)) << 8) |
76 ((data & (0xffULL << 16)) >> 8) |
77 ((data & (0xffULL << 24)) >> 24);
78
79 return swap;
80}
81
82unsigned long long
83__tep_data2host8(struct tep_handle *pevent, unsigned long long data)
84{
85 unsigned long long swap;
86
87 if (!pevent || pevent->host_bigendian == pevent->file_bigendian)
88 return data;
89
90 swap = ((data & 0xffULL) << 56) |
91 ((data & (0xffULL << 8)) << 40) |
92 ((data & (0xffULL << 16)) << 24) |
93 ((data & (0xffULL << 24)) << 8) |
94 ((data & (0xffULL << 32)) >> 8) |
95 ((data & (0xffULL << 40)) >> 24) |
96 ((data & (0xffULL << 48)) >> 40) |
97 ((data & (0xffULL << 56)) >> 56);
98
99 return swap;
100}
101
102/**
103 * tep_get_header_page_size - get size of the header page
104 * @pevent: a handle to the tep_handle
105 *
106 * This returns size of the header page
107 * If @pevent is NULL, 0 is returned.
108 */
109int tep_get_header_page_size(struct tep_handle *pevent)
110{
111 if(pevent)
112 return pevent->header_page_size_size;
113 return 0;
114}
115
116/**
117 * tep_get_cpus - get the number of CPUs
118 * @pevent: a handle to the tep_handle
119 *
120 * This returns the number of CPUs
121 * If @pevent is NULL, 0 is returned.
122 */
123int tep_get_cpus(struct tep_handle *pevent)
124{
125 if(pevent)
126 return pevent->cpus;
127 return 0;
128}
129
130/**
131 * tep_set_cpus - set the number of CPUs
132 * @pevent: a handle to the tep_handle
133 *
134 * This sets the number of CPUs
135 */
136void tep_set_cpus(struct tep_handle *pevent, int cpus)
137{
138 if(pevent)
139 pevent->cpus = cpus;
140}
141
142/**
143 * tep_get_long_size - get the size of a long integer on the current machine
144 * @pevent: a handle to the tep_handle
145 *
146 * This returns the size of a long integer on the current machine
147 * If @pevent is NULL, 0 is returned.
148 */
149int tep_get_long_size(struct tep_handle *pevent)
150{
151 if(pevent)
152 return pevent->long_size;
153 return 0;
154}
155
156/**
157 * tep_set_long_size - set the size of a long integer on the current machine
158 * @pevent: a handle to the tep_handle
159 * @size: size, in bytes, of a long integer
160 *
161 * This sets the size of a long integer on the current machine
162 */
163void tep_set_long_size(struct tep_handle *pevent, int long_size)
164{
165 if(pevent)
166 pevent->long_size = long_size;
167}
168
169/**
170 * tep_get_page_size - get the size of a memory page on the current machine
171 * @pevent: a handle to the tep_handle
172 *
173 * This returns the size of a memory page on the current machine
174 * If @pevent is NULL, 0 is returned.
175 */
176int tep_get_page_size(struct tep_handle *pevent)
177{
178 if(pevent)
179 return pevent->page_size;
180 return 0;
181}
182
183/**
184 * tep_set_page_size - set the size of a memory page on the current machine
185 * @pevent: a handle to the tep_handle
186 * @_page_size: size of a memory page, in bytes
187 *
188 * This sets the size of a memory page on the current machine
189 */
190void tep_set_page_size(struct tep_handle *pevent, int _page_size)
191{
192 if(pevent)
193 pevent->page_size = _page_size;
194}
195
196/**
197 * tep_is_file_bigendian - get if the file is in big endian order
198 * @pevent: a handle to the tep_handle
199 *
200 * This returns if the file is in big endian order
201 * If @pevent is NULL, 0 is returned.
202 */
203int tep_is_file_bigendian(struct tep_handle *pevent)
204{
205 if(pevent)
206 return pevent->file_bigendian;
207 return 0;
208}
209
210/**
211 * tep_set_file_bigendian - set if the file is in big endian order
212 * @pevent: a handle to the tep_handle
213 * @endian: non zero, if the file is in big endian order
214 *
215 * This sets if the file is in big endian order
216 */
217void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian)
218{
219 if(pevent)
220 pevent->file_bigendian = endian;
221}
222
223/**
224 * tep_is_host_bigendian - get if the order of the current host is big endian
225 * @pevent: a handle to the tep_handle
226 *
227 * This gets if the order of the current host is big endian
228 * If @pevent is NULL, 0 is returned.
229 */
230int tep_is_host_bigendian(struct tep_handle *pevent)
231{
232 if(pevent)
233 return pevent->host_bigendian;
234 return 0;
235}
236
237/**
238 * tep_set_host_bigendian - set the order of the local host
239 * @pevent: a handle to the tep_handle
240 * @endian: non zero, if the local host has big endian order
241 *
242 * This sets the order of the local host
243 */
244void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian)
245{
246 if(pevent)
247 pevent->host_bigendian = endian;
248}
249
250/**
251 * tep_is_latency_format - get if the latency output format is configured
252 * @pevent: a handle to the tep_handle
253 *
254 * This gets if the latency output format is configured
255 * If @pevent is NULL, 0 is returned.
256 */
257int tep_is_latency_format(struct tep_handle *pevent)
258{
259 if(pevent)
260 return pevent->latency_format;
261 return 0;
262}
263
264/**
265 * tep_set_latency_format - set the latency output format
266 * @pevent: a handle to the tep_handle
267 * @lat: non zero for latency output format
268 *
269 * This sets the latency output format
270 */
271void tep_set_latency_format(struct tep_handle *pevent, int lat)
272{
273 if(pevent)
274 pevent->latency_format = lat;
275}
diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h
new file mode 100644
index 000000000000..b9bddde577f8
--- /dev/null
+++ b/tools/lib/traceevent/event-parse-local.h
@@ -0,0 +1,92 @@
1// SPDX-License-Identifier: LGPL-2.1
2/*
3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 */
6
7#ifndef _PARSE_EVENTS_INT_H
8#define _PARSE_EVENTS_INT_H
9
10struct cmdline;
11struct cmdline_list;
12struct func_map;
13struct func_list;
14struct event_handler;
15struct func_resolver;
16
17struct tep_handle {
18 int ref_count;
19
20 int header_page_ts_offset;
21 int header_page_ts_size;
22 int header_page_size_offset;
23 int header_page_size_size;
24 int header_page_data_offset;
25 int header_page_data_size;
26 int header_page_overwrite;
27
28 enum tep_endian file_bigendian;
29 enum tep_endian host_bigendian;
30
31 int latency_format;
32
33 int old_format;
34
35 int cpus;
36 int long_size;
37 int page_size;
38
39 struct cmdline *cmdlines;
40 struct cmdline_list *cmdlist;
41 int cmdline_count;
42
43 struct func_map *func_map;
44 struct func_resolver *func_resolver;
45 struct func_list *funclist;
46 unsigned int func_count;
47
48 struct printk_map *printk_map;
49 struct printk_list *printklist;
50 unsigned int printk_count;
51
52
53 struct tep_event_format **events;
54 int nr_events;
55 struct tep_event_format **sort_events;
56 enum tep_event_sort_type last_type;
57
58 int type_offset;
59 int type_size;
60
61 int pid_offset;
62 int pid_size;
63
64 int pc_offset;
65 int pc_size;
66
67 int flags_offset;
68 int flags_size;
69
70 int ld_offset;
71 int ld_size;
72
73 int print_raw;
74
75 int test_filters;
76
77 int flags;
78
79 struct tep_format_field *bprint_ip_field;
80 struct tep_format_field *bprint_fmt_field;
81 struct tep_format_field *bprint_buf_field;
82
83 struct event_handler *handlers;
84 struct tep_function_handler *func_handlers;
85
86 /* cache */
87 struct tep_event_format *last_event;
88
89 char *trace_clock;
90};
91
92#endif /* _PARSE_EVENTS_INT_H */
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 233179a712d6..3692f29fee46 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -22,6 +22,8 @@
22 22
23#include <netinet/in.h> 23#include <netinet/in.h>
24#include "event-parse.h" 24#include "event-parse.h"
25
26#include "event-parse-local.h"
25#include "event-utils.h" 27#include "event-utils.h"
26#include "trace-seq.h" 28#include "trace-seq.h"
27 29
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 9c29a5f7aa39..16bf4c890b6f 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -405,149 +405,18 @@ void tep_print_plugins(struct trace_seq *s,
405 const char *prefix, const char *suffix, 405 const char *prefix, const char *suffix,
406 const struct tep_plugin_list *list); 406 const struct tep_plugin_list *list);
407 407
408struct cmdline; 408/* tep_handle */
409struct cmdline_list;
410struct func_map;
411struct func_list;
412struct event_handler;
413struct func_resolver;
414
415typedef char *(tep_func_resolver_t)(void *priv, 409typedef char *(tep_func_resolver_t)(void *priv,
416 unsigned long long *addrp, char **modp); 410 unsigned long long *addrp, char **modp);
411void tep_set_flag(struct tep_handle *tep, int flag);
412unsigned short __tep_data2host2(struct tep_handle *pevent, unsigned short data);
413unsigned int __tep_data2host4(struct tep_handle *pevent, unsigned int data);
414unsigned long long
415__tep_data2host8(struct tep_handle *pevent, unsigned long long data);
417 416
418struct tep_handle { 417#define tep_data2host2(pevent, ptr) __tep_data2host2(pevent, *(unsigned short *)(ptr))
419 int ref_count; 418#define tep_data2host4(pevent, ptr) __tep_data2host4(pevent, *(unsigned int *)(ptr))
420 419#define tep_data2host8(pevent, ptr) \
421 int header_page_ts_offset;
422 int header_page_ts_size;
423 int header_page_size_offset;
424 int header_page_size_size;
425 int header_page_data_offset;
426 int header_page_data_size;
427 int header_page_overwrite;
428
429 int file_bigendian;
430 int host_bigendian;
431
432 int latency_format;
433
434 int old_format;
435
436 int cpus;
437 int long_size;
438 int page_size;
439
440 struct cmdline *cmdlines;
441 struct cmdline_list *cmdlist;
442 int cmdline_count;
443
444 struct func_map *func_map;
445 struct func_resolver *func_resolver;
446 struct func_list *funclist;
447 unsigned int func_count;
448
449 struct printk_map *printk_map;
450 struct printk_list *printklist;
451 unsigned int printk_count;
452
453
454 struct tep_event_format **events;
455 int nr_events;
456 struct tep_event_format **sort_events;
457 enum tep_event_sort_type last_type;
458
459 int type_offset;
460 int type_size;
461
462 int pid_offset;
463 int pid_size;
464
465 int pc_offset;
466 int pc_size;
467
468 int flags_offset;
469 int flags_size;
470
471 int ld_offset;
472 int ld_size;
473
474 int print_raw;
475
476 int test_filters;
477
478 int flags;
479
480 struct tep_format_field *bprint_ip_field;
481 struct tep_format_field *bprint_fmt_field;
482 struct tep_format_field *bprint_buf_field;
483
484 struct event_handler *handlers;
485 struct tep_function_handler *func_handlers;
486
487 /* cache */
488 struct tep_event_format *last_event;
489
490 char *trace_clock;
491};
492
493static inline void tep_set_flag(struct tep_handle *pevent, int flag)
494{
495 pevent->flags |= flag;
496}
497
498static inline unsigned short
499__tep_data2host2(struct tep_handle *pevent, unsigned short data)
500{
501 unsigned short swap;
502
503 if (pevent->host_bigendian == pevent->file_bigendian)
504 return data;
505
506 swap = ((data & 0xffULL) << 8) |
507 ((data & (0xffULL << 8)) >> 8);
508
509 return swap;
510}
511
512static inline unsigned int
513__tep_data2host4(struct tep_handle *pevent, unsigned int data)
514{
515 unsigned int swap;
516
517 if (pevent->host_bigendian == pevent->file_bigendian)
518 return data;
519
520 swap = ((data & 0xffULL) << 24) |
521 ((data & (0xffULL << 8)) << 8) |
522 ((data & (0xffULL << 16)) >> 8) |
523 ((data & (0xffULL << 24)) >> 24);
524
525 return swap;
526}
527
528static inline unsigned long long
529__tep_data2host8(struct tep_handle *pevent, unsigned long long data)
530{
531 unsigned long long swap;
532
533 if (pevent->host_bigendian == pevent->file_bigendian)
534 return data;
535
536 swap = ((data & 0xffULL) << 56) |
537 ((data & (0xffULL << 8)) << 40) |
538 ((data & (0xffULL << 16)) << 24) |
539 ((data & (0xffULL << 24)) << 8) |
540 ((data & (0xffULL << 32)) >> 8) |
541 ((data & (0xffULL << 40)) >> 24) |
542 ((data & (0xffULL << 48)) >> 40) |
543 ((data & (0xffULL << 56)) >> 56);
544
545 return swap;
546}
547
548#define tep_data2host2(pevent, ptr) __tep_data2host2(pevent, *(unsigned short *)(ptr))
549#define tep_data2host4(pevent, ptr) __tep_data2host4(pevent, *(unsigned int *)(ptr))
550#define tep_data2host8(pevent, ptr) \
551({ \ 420({ \
552 unsigned long long __val; \ 421 unsigned long long __val; \
553 \ 422 \
@@ -655,11 +524,12 @@ unsigned long long tep_read_number(struct tep_handle *pevent, const void *ptr, i
655int tep_read_number_field(struct tep_format_field *field, const void *data, 524int tep_read_number_field(struct tep_format_field *field, const void *data,
656 unsigned long long *value); 525 unsigned long long *value);
657 526
527struct tep_event_format *tep_get_first_event(struct tep_handle *tep);
528int tep_get_events_count(struct tep_handle *tep);
658struct tep_event_format *tep_find_event(struct tep_handle *pevent, int id); 529struct tep_event_format *tep_find_event(struct tep_handle *pevent, int id);
659 530
660struct tep_event_format * 531struct tep_event_format *
661tep_find_event_by_name(struct tep_handle *pevent, const char *sys, const char *name); 532tep_find_event_by_name(struct tep_handle *pevent, const char *sys, const char *name);
662
663struct tep_event_format * 533struct tep_event_format *
664tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record); 534tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record);
665 535
@@ -689,65 +559,23 @@ struct tep_event_format **tep_list_events(struct tep_handle *pevent, enum tep_ev
689struct tep_format_field **tep_event_common_fields(struct tep_event_format *event); 559struct tep_format_field **tep_event_common_fields(struct tep_event_format *event);
690struct tep_format_field **tep_event_fields(struct tep_event_format *event); 560struct tep_format_field **tep_event_fields(struct tep_event_format *event);
691 561
692static inline int tep_get_cpus(struct tep_handle *pevent) 562enum tep_endian {
693{ 563 TEP_LITTLE_ENDIAN = 0,
694 return pevent->cpus; 564 TEP_BIG_ENDIAN
695} 565};
696 566int tep_get_cpus(struct tep_handle *pevent);
697static inline void tep_set_cpus(struct tep_handle *pevent, int cpus) 567void tep_set_cpus(struct tep_handle *pevent, int cpus);
698{ 568int tep_get_long_size(struct tep_handle *pevent);
699 pevent->cpus = cpus; 569void tep_set_long_size(struct tep_handle *pevent, int long_size);
700} 570int tep_get_page_size(struct tep_handle *pevent);
701 571void tep_set_page_size(struct tep_handle *pevent, int _page_size);
702static inline int tep_get_long_size(struct tep_handle *pevent) 572int tep_is_file_bigendian(struct tep_handle *pevent);
703{ 573void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian);
704 return pevent->long_size; 574int tep_is_host_bigendian(struct tep_handle *pevent);
705} 575void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian);
706 576int tep_is_latency_format(struct tep_handle *pevent);
707static inline void tep_set_long_size(struct tep_handle *pevent, int long_size) 577void tep_set_latency_format(struct tep_handle *pevent, int lat);
708{ 578int tep_get_header_page_size(struct tep_handle *pevent);
709 pevent->long_size = long_size;
710}
711
712static inline int tep_get_page_size(struct tep_handle *pevent)
713{
714 return pevent->page_size;
715}
716
717static inline void tep_set_page_size(struct tep_handle *pevent, int _page_size)
718{
719 pevent->page_size = _page_size;
720}
721
722static inline int tep_is_file_bigendian(struct tep_handle *pevent)
723{
724 return pevent->file_bigendian;
725}
726
727static inline void tep_set_file_bigendian(struct tep_handle *pevent, int endian)
728{
729 pevent->file_bigendian = endian;
730}
731
732static inline int tep_is_host_bigendian(struct tep_handle *pevent)
733{
734 return pevent->host_bigendian;
735}
736
737static inline void tep_set_host_bigendian(struct tep_handle *pevent, int endian)
738{
739 pevent->host_bigendian = endian;
740}
741
742static inline int tep_is_latency_format(struct tep_handle *pevent)
743{
744 return pevent->latency_format;
745}
746
747static inline void tep_set_latency_format(struct tep_handle *pevent, int lat)
748{
749 pevent->latency_format = lat;
750}
751 579
752struct tep_handle *tep_alloc(void); 580struct tep_handle *tep_alloc(void);
753void tep_free(struct tep_handle *pevent); 581void tep_free(struct tep_handle *pevent);
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 46eb64eb0c2e..e74f16c88398 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -14,6 +14,7 @@
14#include <unistd.h> 14#include <unistd.h>
15#include <dirent.h> 15#include <dirent.h>
16#include "event-parse.h" 16#include "event-parse.h"
17#include "event-parse-local.h"
17#include "event-utils.h" 18#include "event-utils.h"
18#include "trace-seq.h" 19#include "trace-seq.h"
19 20
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index d64b6128fa7d..ed87cb56713d 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -11,6 +11,7 @@
11#include <sys/types.h> 11#include <sys/types.h>
12 12
13#include "event-parse.h" 13#include "event-parse.h"
14#include "event-parse-local.h"
14#include "event-utils.h" 15#include "event-utils.h"
15 16
16#define COMM "COMM" 17#define COMM "COMM"