lttv and lib ltt new compiles
[lttv.git] / ltt / branches / poly / ltt / event.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Xiangxiu Yang
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <glib.h>
27
28 #include <asm/types.h>
29 #include <linux/byteorder/swab.h>
30
31 #include "parser.h"
32 #include <ltt/ltt.h>
33 #include "ltt-private.h"
34 #include <ltt/event.h>
35 #include <ltt/trace.h>
36 #include <ltt/ltt-types.h>
37
38 LttEvent *ltt_event_new()
39 {
40 return g_new(LttEvent, 1);
41 }
42
43 void ltt_event_destroy(LttEvent *event)
44 {
45 g_free(event);
46 }
47
48
49 #if 0
50 /* Use get_field_type_size instead */
51 /*****************************************************************************
52 *Function name
53 * ltt_event_refresh_fields : refresh fields of an event
54 *Input params
55 * offsetRoot : offset from the root
56 * offsetParent : offset from the parent
57 * fld : field
58 * evD : event data
59 * reverse_byte_order : 1 or 0
60 *Return value
61 * int : size of the field
62 ****************************************************************************/
63
64 int ltt_event_refresh_fields(int offsetRoot,int offsetParent,
65 LttField * fld, void *evD, gboolean reverse_byte_order)
66 {
67 int size, size1, element_number, i, offset1, offset2;
68 LttType * type = fld->field_type;
69
70 switch(type->type_class) {
71 case LTT_ARRAY:
72 element_number = (int) type->element_number;
73 if(fld->field_fixed == 0){// has string or sequence
74 size = 0;
75 for(i=0;i<element_number;i++){
76 size += ltt_event_refresh_fields(offsetRoot+size,size,
77 fld->child[0], evD+size, reverse_byte_order);
78 }
79 }else size = fld->field_size;
80 break;
81
82 case LTT_SEQUENCE:
83 size1 = fld->sequ_number_size;
84 element_number = getIntNumber(reverse_byte_order,size1,evD);
85 type->element_number = element_number;
86 if(fld->element_size > 0){
87 size = element_number * fld->element_size;
88 }else{//sequence has string or sequence
89 size = 0;
90 for(i=0;i<element_number;i++){
91 size += ltt_event_refresh_fields(offsetRoot+size+size1,size+size1,
92 fld->child[0], evD+size+size1, reverse_byte_order);
93 }
94 size += size1;
95 }
96 break;
97
98 case LTT_STRING:
99 size = strlen((gchar*)evD) + 1; //include end : '\0'
100 break;
101
102 case LTT_STRUCT:
103 element_number = (int) type->element_number;
104 if(fld->field_fixed == 0){
105 offset1 = offsetRoot;
106 offset2 = 0;
107 for(i=0;i<element_number;i++){
108 size=ltt_event_refresh_fields(offset1,offset2,
109 fld->child[i],evD+offset2, reverse_byte_order);
110 offset1 += size;
111 offset2 += size;
112 }
113 size = offset2;
114 }else size = fld->field_size;
115 break;
116
117 case LTT_UNION:
118 size = fld->field_size;
119 break;
120
121 default:
122 size = fld->field_size;
123 }
124
125 #if 0
126 if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY &&
127 type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){
128 size = fld->field_size;
129 }else if(type->type_class == LTT_ARRAY){
130 element_number = (int) type->element_number;
131 if(fld->field_fixed == 0){// has string or sequence
132 size = 0;
133 for(i=0;i<element_number;i++){
134 size += ltt_event_refresh_fields(offsetRoot+size,size,
135 fld->child[0], evD+size);
136 }
137 }else size = fld->field_size;
138 }else if(type->type_class == LTT_SEQUENCE){
139 size1 = fld->sequ_number_size;
140 element_number = getIntNumber(size1,evD);
141 type->element_number = element_number;
142 if(fld->element_size > 0){
143 size = element_number * fld->element_size;
144 }else{//sequence has string or sequence
145 size = 0;
146 for(i=0;i<element_number;i++){
147 size += ltt_event_refresh_fields(offsetRoot+size+size1,size+size1,
148 fld->child[0], evD+size+size1);
149 }
150 size += size1;
151 }
152 }else if(type->type_class == LTT_STRING){
153 size = strlen((char*)evD) + 1; //include end : '\0'
154 }else if(type->type_class == LTT_STRUCT){
155 element_number = (int) type->element_number;
156 if(fld->field_fixed == 0){
157 offset1 = offsetRoot;
158 offset2 = 0;
159 for(i=0;i<element_number;i++){
160 size=ltt_event_refresh_fields(offset1,offset2,
161 fld->child[i],evD+offset2);
162 offset1 += size;
163 offset2 += size;
164 }
165 size = offset2;
166 }else size = fld->field_size;
167 }
168 #endif //0
169 fld->offset_root = offsetRoot;
170 fld->offset_parent = offsetParent;
171 fld->fixed_root = (offsetRoot==-1) ? 0 : 1;
172 fld->fixed_parent = (offsetParent==-1) ? 0 : 1;
173 fld->field_size = size;
174
175 return size;
176 }
177 #endif //0
178
179
180 /*****************************************************************************
181 *Function name
182 * ltt_event_eventtype_id: get event type id
183 * (base id + position of the event)
184 *Input params
185 * e : an instance of an event type
186 *Return value
187 * unsigned : event type id
188 ****************************************************************************/
189
190 unsigned ltt_event_eventtype_id(const LttEvent *e)
191 {
192 return (unsigned) e->event_id;
193 }
194
195 /*****************************************************************************
196 *Function name
197 * ltt_event_facility : get the facility of the event
198 *Input params
199 * e : an instance of an event type
200 *Return value
201 * LttFacility * : the facility of the event
202 ****************************************************************************/
203
204 LttFacility *ltt_event_facility(const LttEvent *e)
205 {
206 LttTrace * trace = e->tracefile->trace;
207 unsigned id = e->event_id;
208 return ltt_trace_facility_by_id(trace,id);
209 }
210
211 /*****************************************************************************
212 *Function name
213 * ltt_event_facility_id : get the facility id of the event
214 *Input params
215 * e : an instance of an event type
216 *Return value
217 * unsigned : the facility of the event
218 ****************************************************************************/
219
220 unsigned ltt_event_facility_id(const LttEvent *e)
221 {
222 return e->facility_id;
223 }
224
225 /*****************************************************************************
226 *Function name
227 * ltt_event_eventtype : get the event type of the event
228 *Input params
229 * e : an instance of an event type
230 *Return value
231 * LttEventType * : the event type of the event
232 ****************************************************************************/
233
234 LttEventType *ltt_event_eventtype(const LttEvent *e)
235 {
236 LttFacility* facility = ltt_event_facility(e);
237 if(!facility) return NULL;
238 return &g_array_index(facility->events, LttEventType, e->event_id);
239 }
240
241 /*****************************************************************************
242 *Function name
243 * ltt_event_field : get the root field of the event
244 *Input params
245 * e : an instance of an event type
246 *Return value
247 * LttField * : the root field of the event
248 ****************************************************************************/
249
250 LttField *ltt_event_field(LttEvent *e)
251 {
252 LttField * field;
253 LttEventType * event_type = ltt_event_eventtype(e);
254 if(unlikely(!event_type)) return NULL;
255 field = event_type->root_field;
256 if(unlikely(!field)) return NULL;
257
258 get_field_type_size(e->tracefile, event_type, 0, 0,
259 field, e->data);
260
261 return field;
262 }
263
264 /*****************************************************************************
265 *Function name
266 * ltt_event_time : get the time of the event
267 *Input params
268 * e : an instance of an event type
269 *Return value
270 * LttTime : the time of the event
271 ****************************************************************************/
272
273 LttTime ltt_event_time(const LttEvent *e)
274 {
275 return e->event_time;
276 }
277
278 /*****************************************************************************
279 *Function name
280 * ltt_event_time : get the cycle count of the event
281 *Input params
282 * e : an instance of an event type
283 *Return value
284 * LttCycleCount : the cycle count of the event
285 ****************************************************************************/
286
287 LttCycleCount ltt_event_cycle_count(const LttEvent *e)
288 {
289 return e->tsc;
290 }
291
292
293
294 /*****************************************************************************
295 *Function name
296 * ltt_event_position_get : get the event position data
297 *Input params
298 * e : an instance of an event type
299 * ep : a pointer to event's position structure
300 * tf : tracefile pointer
301 * block : current block
302 * offset : current offset
303 * tsc : current tsc
304 ****************************************************************************/
305 void ltt_event_position_get(LttEventPosition *ep, LttTracefile **tf,
306 guint *block, guint *offset, guint64 *tsc)
307 {
308 *tf = ep->tracefile;
309 *block = ep->block;
310 *offset = ep->offset;
311 *tsc = ep->tsc;
312 }
313
314
315 /*****************************************************************************
316 *Function name
317 * ltt_event_position : get the event's position
318 *Input params
319 * e : an instance of an event type
320 * ep : a pointer to event's position structure
321 ****************************************************************************/
322
323 void ltt_event_position(LttEvent *e, LttEventPosition *ep)
324 {
325 ep->tracefile = e->tracefile;
326 ep->block = e->block;
327 ep->offset = e->offset;
328 ep->tsc = e->tsc;
329 }
330
331 LttEventPosition * ltt_event_position_new()
332 {
333 return g_new(LttEventPosition, 1);
334 }
335
336
337 /*****************************************************************************
338 * Function name
339 * ltt_event_position_compare : compare two positions
340 * A NULL value is infinite.
341 * Input params
342 * ep1 : a pointer to event's position structure
343 * ep2 : a pointer to event's position structure
344 * Return
345 * -1 is ep1 < ep2
346 * 1 if ep1 > ep2
347 * 0 if ep1 == ep2
348 ****************************************************************************/
349
350
351 gint ltt_event_position_compare(const LttEventPosition *ep1,
352 const LttEventPosition *ep2)
353 {
354 if(ep1 == NULL && ep2 == NULL)
355 return 0;
356 if(ep1 != NULL && ep2 == NULL)
357 return -1;
358 if(ep1 == NULL && ep2 != NULL)
359 return 1;
360
361 if(ep1->tracefile != ep2->tracefile)
362 g_error("ltt_event_position_compare on different tracefiles makes no sense");
363
364 if(ep1->block < ep2->block)
365 return -1;
366 if(ep1->block > ep2->block)
367 return 1;
368 if(ep1->offset < ep2->offset)
369 return -1;
370 if(ep1->offset > ep2->offset)
371 return 1;
372 return 0;
373 }
374
375 /*****************************************************************************
376 * Function name
377 * ltt_event_position_copy : copy position
378 * Input params
379 * src : a pointer to event's position structure source
380 * dest : a pointer to event's position structure dest
381 * Return
382 * void
383 ****************************************************************************/
384 void ltt_event_position_copy(LttEventPosition *dest,
385 const LttEventPosition *src)
386 {
387 if(src == NULL)
388 dest = NULL;
389 else
390 *dest = *src;
391 }
392
393
394 /*****************************************************************************
395 *Function name
396 * ltt_event_cpu_i: get the cpu id where the event happens
397 *Input params
398 * e : an instance of an event type
399 *Return value
400 * unsigned : the cpu id
401 ****************************************************************************/
402
403 unsigned ltt_event_cpu_id(LttEvent *e)
404 {
405 return e->tracefile->cpu_num;
406 }
407
408 /*****************************************************************************
409 *Function name
410 * ltt_event_data : get the raw data for the event
411 *Input params
412 * e : an instance of an event type
413 *Return value
414 * void * : pointer to the raw data for the event
415 ****************************************************************************/
416
417 void *ltt_event_data(LttEvent *e)
418 {
419 return e->data;
420 }
421
422 /*****************************************************************************
423 *Function name
424 * ltt_event_field_element_number
425 * : The number of elements in a sequence field is specific
426 * to each event. This function returns the number of
427 * elements for an array or sequence field in an event.
428 *Input params
429 * e : an instance of an event type
430 * f : a field of the instance
431 *Return value
432 * unsigned : the number of elements for an array/sequence field
433 ****************************************************************************/
434 guint64 ltt_event_field_element_number(LttEvent *e, LttField *f)
435 {
436 if(f->field_type->type_class != LTT_ARRAY &&
437 f->field_type->type_class != LTT_SEQUENCE)
438 return 0;
439
440 if(f->field_type->type_class == LTT_ARRAY)
441 return f->field_type->element_number;
442 return ltt_get_uint(LTT_GET_BO(e->tracefile), f->sequ_number_size,
443 e + f->offset_root);
444 }
445
446 /*****************************************************************************
447 *Function name
448 * ltt_event_field_element_select
449 * : Set the currently selected element for a sequence or
450 * array field
451 * O(1) if fields are of fixed size, else O(n) if fields are
452 * of variable size.
453 *Input params
454 * e : an instance of an event type
455 * f : a field of the instance
456 * i : the ith element (0, ...)
457 ****************************************************************************/
458 void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i)
459 {
460 unsigned element_number;
461 LttField *field;
462 unsigned int k;
463 size_t size;
464 LttEventType *event_type;
465
466 if(f->field_type->type_class != LTT_ARRAY &&
467 f->field_type->type_class != LTT_SEQUENCE)
468 return ;
469
470 element_number = ltt_event_field_element_number(e,f);
471 event_type = ltt_event_eventtype(e);
472 /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
473 */
474 if(i >= element_number) return;
475
476 field = f->child[0];
477
478 if(f->field_type->type_class == LTT_SEQUENCE)
479 size = f->sequ_number_size;
480 else
481 size = 0;
482
483 if(field->fixed_size == FIELD_FIXED) {
484 size += field->field_size * i;
485
486 get_field_type_size(e->tracefile, event_type,
487 f->offset_root+size, size, field, e->data);
488
489 } else {
490 for(k=0;k<=i;k++){
491 size += get_field_type_size(e->tracefile, event_type,
492 f->offset_root+size, size, field, e->data);
493 }
494 }
495 f->current_element = i;
496 }
497
498 /*****************************************************************************
499 * These functions extract data from an event after architecture specific
500 * conversions
501 ****************************************************************************/
502 guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f)
503 {
504 gboolean reverse_byte_order = LTT_GET_BO(e->tracefile);
505
506 LttTypeEnum t = f->field_type->type_class;
507
508 g_assert(t == LTT_UINT || t == LTT_ENUM);
509
510 if(f->field_size == 1){
511 guint8 x = *(guint8 *)(e->data + f->offset_root);
512 return (guint32) x;
513 }else if(f->field_size == 2){
514 return (guint32)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root);
515 }else if(f->field_size == 4){
516 return (guint32)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root);
517 }
518 #if 0
519 else if(f->field_size == 8){
520 guint64 x = *(guint64 *)(e->data + f->offset_root);
521 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
522 return (unsigned int) (revFlag ? GUINT64_FROM_BE(x): x);
523 else
524 return (unsigned int) (revFlag ? GUINT64_FROM_LE(x): x);
525 }
526 #endif //0
527 g_critical("ltt_event_get_unsigned : field size %i unknown", f->field_size);
528 return 0;
529 }
530
531 gint32 ltt_event_get_int(LttEvent *e, LttField *f)
532 {
533 gboolean reverse_byte_order = LTT_GET_BO(e->tracefile);
534
535 g_assert(f->field_type->type_class == LTT_INT);
536
537 if(f->field_size == 1){
538 gint8 x = *(gint8 *)(e->data + f->offset_root);
539 return (gint32) x;
540 }else if(f->field_size == 2){
541 return (gint32)ltt_get_int16(reverse_byte_order, e->data + f->offset_root);
542 }else if(f->field_size == 4){
543 return (gint32)ltt_get_int32(reverse_byte_order, e->data + f->offset_root);
544 }
545 #if 0
546 else if(f->field_size == 8){
547 gint64 x = *(gint64 *)(e->data + f->offset_root);
548 if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN)
549 return (int) (revFlag ? GINT64_FROM_BE(x): x);
550 else
551 return (int) (revFlag ? GINT64_FROM_LE(x): x);
552 }
553 #endif //0
554 g_critical("ltt_event_get_int : field size %i unknown", f->field_size);
555 return 0;
556 }
557
558 guint64 ltt_event_get_long_unsigned(LttEvent *e, LttField *f)
559 {
560 gboolean reverse_byte_order = LTT_GET_BO(e->tracefile);
561
562 LttTypeEnum t = f->field_type->type_class;
563
564 g_assert(t == LTT_UINT || t == LTT_ENUM);
565
566 if(f->field_size == 1){
567 guint8 x = *(guint8 *)(e->data + f->offset_root);
568 return (guint64) x;
569 }else if(f->field_size == 2){
570 return (guint64)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root);
571 }else if(f->field_size == 4){
572 return (guint64)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root);
573 }else if(f->field_size == 8){
574 return ltt_get_uint64(reverse_byte_order, e->data + f->offset_root);
575 }
576 g_critical("ltt_event_get_long_unsigned : field size %i unknown", f->field_size);
577 return 0;
578 }
579
580 gint64 ltt_event_get_long_int(LttEvent *e, LttField *f)
581 {
582 //int revFlag = e->tracefile->trace->my_arch_endian ==
583 // e->tracefile->trace->system_description->endian ? 0:1;
584 gboolean reverse_byte_order = LTT_GET_BO(e->tracefile);
585
586 g_assert( f->field_type->type_class == LTT_INT);
587
588 if(f->field_size == 1){
589 gint8 x = *(gint8 *)(e->data + f->offset_root);
590 return (gint64) x;
591 }else if(f->field_size == 2){
592 return (gint64)ltt_get_int16(reverse_byte_order, e->data + f->offset_root);
593 }else if(f->field_size == 4){
594 return (gint64)ltt_get_int32(reverse_byte_order, e->data + f->offset_root);
595 }else if(f->field_size == 8){
596 return ltt_get_int64(reverse_byte_order, e->data + f->offset_root);
597 }
598 g_critical("ltt_event_get_long_int : field size %i unknown", f->field_size);
599 return 0;
600 }
601
602 float ltt_event_get_float(LttEvent *e, LttField *f)
603 {
604 gboolean reverse_byte_order = LTT_GET_BO(e->tracefile);
605
606 g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 4);
607
608 if(reverse_byte_order == 0) return *(float *)(e->data + f->offset_root);
609 else{
610 guint32 aInt;
611 memcpy((void*)&aInt, e->data + f->offset_root, 4);
612 aInt = ___swab32(aInt);
613 return ((float)aInt);
614 }
615 }
616
617 double ltt_event_get_double(LttEvent *e, LttField *f)
618 {
619 gboolean reverse_byte_order = LTT_GET_BO(e->tracefile);
620
621 g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 8);
622
623 if(reverse_byte_order == 0) return *(double *)(e->data + f->offset_root);
624 else{
625 guint64 aInt;
626 memcpy((void*)&aInt, e->data + f->offset_root, 8);
627 aInt = ___swab64(aInt);
628 return ((double)aInt);
629 }
630 }
631
632 /*****************************************************************************
633 * The string obtained is only valid until the next read from
634 * the same tracefile.
635 ****************************************************************************/
636 char *ltt_event_get_string(LttEvent *e, LttField *f)
637 {
638 g_assert(f->field_type->type_class == LTT_STRING);
639
640 return (gchar*)g_strdup((gchar*)(e->data + f->offset_root));
641 }
642
643
644 /*****************************************************************************
645 *Function name
646 * get_field_type_size : set the fixed and dynamic sizes of the field type
647 * from the data read.
648 *Input params
649 * tf : tracefile
650 * event_type : event type
651 * offset_root : offset from the root
652 * offset_parent : offset from the parent
653 * field : field
654 * data : a pointer to the event data.
655 *Returns the field type size.
656 ****************************************************************************/
657 size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
658 off_t offset_root, off_t offset_parent,
659 LttField *field, void *data)
660 {
661 size_t size = 0;
662 guint i;
663 LttType *type;
664
665 g_assert(field->fixed_root != FIELD_UNKNOWN);
666 g_assert(field->fixed_parent != FIELD_UNKNOWN);
667 g_assert(field->fixed_size != FIELD_UNKNOWN);
668
669 field->offset_root = offset_root;
670 field->offset_parent = offset_parent;
671
672 type = field->field_type;
673
674 switch(type->type_class) {
675 case LTT_INT:
676 case LTT_UINT:
677 case LTT_FLOAT:
678 case LTT_ENUM:
679 case LTT_POINTER:
680 case LTT_LONG:
681 case LTT_ULONG:
682 case LTT_SIZE_T:
683 case LTT_SSIZE_T:
684 case LTT_OFF_T:
685 g_assert(field->fixed_size == FIELD_FIXED);
686 size = field->field_size;
687 break;
688 case LTT_SEQUENCE:
689 {
690 gint seqnum = ltt_get_uint(LTT_GET_BO(tf),
691 field->sequ_number_size,
692 data + offset_root);
693
694 if(field->child[0]->fixed_size == FIELD_FIXED) {
695 size = field->sequ_number_size +
696 (seqnum * get_field_type_size(tf, event_type,
697 offset_root, offset_parent,
698 field->child[0], data));
699 } else {
700 size += field->sequ_number_size;
701 for(i=0;i<seqnum;i++) {
702 size_t child_size;
703 child_size = get_field_type_size(tf, event_type,
704 offset_root, offset_parent,
705 field->child[0], data);
706 offset_root += child_size;
707 offset_parent += child_size;
708 size += child_size;
709 }
710 }
711 field->field_size = size;
712 }
713 break;
714 case LTT_STRING:
715 size = strlen((char*)(data+offset_root)) + 1;// length + \0
716 field->field_size = size;
717 break;
718 case LTT_ARRAY:
719 if(field->fixed_size == FIELD_FIXED)
720 size = field->field_size;
721 else {
722 for(i=0;i<field->field_type->element_number;i++) {
723 size_t child_size;
724 child_size = get_field_type_size(tf, event_type,
725 offset_root, offset_parent,
726 field->child[0], data);
727 offset_root += child_size;
728 offset_parent += child_size;
729 size += child_size;
730 }
731 field->field_size = size;
732 }
733 break;
734 case LTT_STRUCT:
735 if(field->fixed_size == FIELD_FIXED)
736 size = field->field_size;
737 else {
738 size_t current_root_offset = offset_root;
739 size_t current_offset = 0;
740 size_t child_size = 0;
741 for(i=0;i<type->element_number;i++) {
742 child_size = get_field_type_size(tf,
743 event_type, current_root_offset, current_offset,
744 field->child[i], data);
745 current_offset += child_size;
746 current_root_offset += child_size;
747
748 }
749 size = current_offset;
750 field->field_size = size;
751 }
752 break;
753 case LTT_UNION:
754 if(field->fixed_size == FIELD_FIXED)
755 size = field->field_size;
756 else {
757 size_t current_root_offset = field->offset_root;
758 size_t current_offset = 0;
759 for(i=0;i<type->element_number;i++) {
760 size = get_field_type_size(tf, event_type,
761 current_root_offset, current_offset,
762 field->child[i], data);
763 size = max(size, field->child[i]->field_size);
764 }
765 field->field_size = size;
766 }
767 break;
768 }
769
770 return size;
771 }
772
773
This page took 0.046024 seconds and 4 git commands to generate.