blob: 018dc2139e6506725722a56041bace4e6231338e [file] [log] [blame]
Dave Barach52642c32016-02-11 19:28:19 -05001/*
2 *------------------------------------------------------------------
3 * Copyright (c) 2005-2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <strings.h>
20#include <ctype.h>
21#include <string.h>
22#include <gtk/gtk.h>
23#include "g2.h"
24
25/*
26 * globals
27 */
28event_def_t g_eventdefs[NEVENTS];
29
30/*
31 * locals
32 */
33static GtkWidget *s_pointselbox;
34static FILE *s_hfp;
35static FILE *s_elog_hfp;
36static int s_basenum;
37static GtkWidget *s_event_buttons[NEVENTS];
38static int s_min_shown_pointsel;
39static int s_max_shown_pointsel;
40static GtkWidget *s_allbutton;
41static GtkWidget *s_nonebutton;
42static GtkWidget *s_pointselbuttons;
43static GtkWidget *s_ps_vscroll;
44static GtkObject *s_ps_vsadj;
45static int g_neventdefs;
46
47enum button_click {
48 ALL_BUTTON=1,
49 NONE_BUTTON,
50};
51
52/*
53 * config params
54 */
55int c_maxpointsel;
56
57/****************************************************************************
58* recompute_vscrollbar
59****************************************************************************/
60
61static void recompute_ps_vscrollbar (void)
62{
63 GtkAdjustment *adj;
64 ulong limit;
65
66 adj = GTK_ADJUSTMENT(s_ps_vsadj);
67
68#ifdef NOTDEF
69 /* This seems like the right calculation, but seems not to work */
70 if (g_neventdefs > c_maxpointsel)
71 limit = g_neventdefs - c_maxpointsel;
72 else
73 limit = g_neventdefs;
74#else
75 limit = g_neventdefs-1;
76#endif
77
78 adj->lower = (gfloat)0.00;
79 adj->upper = (gfloat)limit;
80 adj->value = (gfloat)0.00;
81 adj->step_increment = (gfloat)1.00;
82 adj->page_increment = (gfloat)(c_maxpointsel / 3);
83 adj->page_size = (gfloat)c_maxpointsel;
84 gtk_adjustment_changed(adj);
85 gtk_adjustment_value_changed(adj);
86 gtk_widget_show(s_ps_vscroll);
87}
88
89/****************************************************************************
90* point_select_callback
91****************************************************************************/
92
93static void point_select_callback(GtkToggleButton *item, gpointer data)
94{
95 int i = (int) (unsigned long long) data;
96
97 g_eventdefs[i].selected = gtk_toggle_button_get_active(
98 GTK_TOGGLE_BUTTON(s_event_buttons[i]));
99 view1_display_when_idle();
100}
101
102/****************************************************************************
103* up_button
104****************************************************************************/
105
106static void up_button(void)
107{
108 int i;
109 int increment = c_maxpointsel/4;
110
111 if (s_min_shown_pointsel == 0)
112 return;
113
114 s_min_shown_pointsel -= increment;
115
116 if (s_min_shown_pointsel < 0)
117 s_min_shown_pointsel = 0;
118
119 s_max_shown_pointsel = s_min_shown_pointsel + c_maxpointsel;
120
121 for (i = 0; i < g_neventdefs; i++) {
122 if (i >= s_min_shown_pointsel &&
123 i <= s_max_shown_pointsel)
124 gtk_widget_show(s_event_buttons[i]);
125 else
126 gtk_widget_hide(s_event_buttons[i]);
127 }
128
129}
130
131#ifdef NOTDEF
132/****************************************************************************
133* down_button
134****************************************************************************/
135
136static void down_button(void)
137{
138 int i;
139 int increment = c_maxpointsel/4;
140
141 if (s_max_shown_pointsel == g_neventdefs)
142 return;
143
144 s_max_shown_pointsel += increment;
145
146 if (s_max_shown_pointsel >= g_neventdefs)
147 s_max_shown_pointsel = (g_neventdefs-1);
148
149 s_min_shown_pointsel = s_max_shown_pointsel - c_maxpointsel;
150
151 if (s_min_shown_pointsel < 0)
152 s_min_shown_pointsel = 0;
153
154 for (i = 0; i < g_neventdefs; i++) {
155 if (i >= s_min_shown_pointsel &&
156 i <= s_max_shown_pointsel)
157 gtk_widget_show(s_event_buttons[i]);
158 else
159 gtk_widget_hide(s_event_buttons[i]);
160 }
161
162}
163#endif
164
165/****************************************************************************
166* button_click_callback
167****************************************************************************/
168
169static void button_click_callback(GtkButton *item, gpointer data)
170{
171 int i;
172 enum button_click click = (enum button_click)data;
173
174 switch (click) {
175 case ALL_BUTTON:
176 for (i = 0; i < g_neventdefs; i++) {
177 gtk_toggle_button_set_active (
178 GTK_TOGGLE_BUTTON(s_event_buttons[i]), TRUE);
179 g_eventdefs[i].selected = TRUE;
180 }
181 break;
182
183 case NONE_BUTTON:
184 for (i = 0; i < g_neventdefs; i++) {
185 gtk_toggle_button_set_active (
186 GTK_TOGGLE_BUTTON(s_event_buttons[i]), FALSE);
187 g_eventdefs[i].selected = FALSE;
188 }
189 break;
190 }
191}
192
193/****************************************************************************
194* scroll_callback
195****************************************************************************/
196
197static void scroll_callback (GtkAdjustment *adj, GtkWidget *notused)
198{
199 int i;
200
201 s_min_shown_pointsel = (int)adj->value;
202 s_max_shown_pointsel = s_min_shown_pointsel + c_maxpointsel;
203
204 for (i = 0; i < g_neventdefs; i++) {
205 if (i >= s_min_shown_pointsel &&
206 i <= s_max_shown_pointsel)
207 gtk_widget_show(s_event_buttons[i]);
208 else
209 gtk_widget_hide(s_event_buttons[i]);
210 }
211}
212
213/****************************************************************************
214* point_selector_init
215****************************************************************************/
216
217void point_selector_init(void)
218{
219
220 c_maxpointsel = atol(getprop_default("event_selector_lines", "20"));
221
222 s_pointselbox = gtk_vbox_new(FALSE,5);
223
224 s_pointselbuttons = gtk_hbox_new(FALSE,5);
225
226 s_allbutton = gtk_button_new_with_label("ALL");
227 gtk_widget_show(s_allbutton);
228 s_nonebutton = gtk_button_new_with_label("NONE");
229 gtk_widget_show(s_nonebutton);
230
231 gtk_signal_connect (GTK_OBJECT(s_allbutton), "clicked",
232 GTK_SIGNAL_FUNC(button_click_callback),
233 (gpointer) ALL_BUTTON);
234
235 gtk_signal_connect (GTK_OBJECT(s_nonebutton), "clicked",
236 GTK_SIGNAL_FUNC(button_click_callback),
237 (gpointer) NONE_BUTTON);
238
239 gtk_box_pack_start(GTK_BOX(s_pointselbuttons), s_allbutton, FALSE,
240 FALSE, 0);
241 gtk_box_pack_start(GTK_BOX(s_pointselbuttons), s_nonebutton, FALSE,
242 FALSE, 0);
243
244 gtk_widget_show(s_pointselbuttons);
245 gtk_widget_ref(s_pointselbuttons);
246
247 gtk_box_pack_start(GTK_BOX(s_pointselbox), s_pointselbuttons, FALSE,
248 FALSE, 0);
249
250 gtk_box_pack_end (GTK_BOX(g_mainhbox), s_pointselbox,
251 FALSE, FALSE, 0);
252
253 s_ps_vsadj = gtk_adjustment_new(0.0 /* initial value */,
254 0.0 /* minimum value */,
255 2000.0 /* maximum value */,
256 0.1 /* step increment */,
257 10.0/* page increment */,
258 10.0/* page size */);
259
260 s_ps_vscroll = gtk_vscrollbar_new (GTK_ADJUSTMENT(s_ps_vsadj));
261 gtk_signal_connect (GTK_OBJECT (s_ps_vsadj), "value-changed",
262 GTK_SIGNAL_FUNC (scroll_callback),
263 (gpointer)s_ps_vscroll);
264 gtk_box_pack_end(GTK_BOX(g_mainhbox), s_ps_vscroll, FALSE, FALSE, 0);
265}
266
267/****************************************************************************
268* sxerox
269****************************************************************************/
270
271char *sxerox (char *s)
272{
273 char *rv;
274
275 /* Note: g_malloc does or dies... */
276 rv = (char *)g_malloc(strlen(s)+1);
277 strcpy (rv, s);
278 return (rv);
279}
280
281/****************************************************************************
282* reset_point_selector
283****************************************************************************/
284
285static void reset_point_selector(void)
286{
287 int i;
288
289 gtk_widget_hide(s_pointselbox);
290 gtk_widget_hide(s_pointselbuttons);
291 gtk_widget_hide(s_ps_vscroll);
292 gtk_container_remove(GTK_CONTAINER(s_pointselbox),
293 s_pointselbuttons);
294
295 for (i = 0; i < g_neventdefs; i++) {
296 if (s_event_buttons[i]) {
297 gtk_container_remove(GTK_CONTAINER(s_pointselbox),
298 s_event_buttons[i]);
299 s_event_buttons[i] = 0;
300 }
301 }
302}
303
304/****************************************************************************
305* create_point_selector
306****************************************************************************/
307
308static void create_point_selector(void)
309{
310 int i;
311 char tmpbuf [1024];
312 event_def_t *ep;
313 GtkWidget *wp;
314
315 for (i = 0; i < g_neventdefs; i++) {
316 ep = &g_eventdefs[i];
317 sprintf(tmpbuf, "[%lu] %s", ep->event,
318 ep->name ? ep->name : "(none)");
319 /* Hack to reduce width of point selectors */
320 if (strlen(tmpbuf) > 50) {
321 tmpbuf[50] = 0;
322 }
323
324 wp = gtk_check_button_new_with_label (tmpbuf);
325 s_event_buttons[i] = wp;
326 gtk_signal_connect (GTK_OBJECT(wp), "toggled",
327 GTK_SIGNAL_FUNC(point_select_callback),
328 (gpointer) (unsigned long long) i);
329 gtk_toggle_button_set_active (
330 GTK_TOGGLE_BUTTON(wp), TRUE);
331 gtk_box_pack_start(GTK_BOX(s_pointselbox), wp, FALSE, FALSE, 0);
332 }
333
334 /* set up scroll parameters by faking an up-button */
335 s_min_shown_pointsel = 1;
336 up_button();
337
338 gtk_box_pack_start(GTK_BOX(s_pointselbox), s_pointselbuttons, FALSE,
339 FALSE, 0);
340 gtk_widget_show(s_pointselbuttons);
341 gtk_widget_show(s_pointselbox);
342 gtk_widget_show(s_ps_vscroll);
343}
344
345/****************************************************************************
346* remove_all_events
347****************************************************************************/
348
349static void remove_all_events(void)
350{
351 event_def_t *ep;
352 int i;
353
354 for (i = 0; i < g_neventdefs; i++) {
355 ep = &g_eventdefs[i];
356 if (!ep->is_clib) {
357 if (ep->name)
358 g_free(ep->name);
359 if(ep->format)
360 g_free(ep->format);
361 }
362 }
363 g_neventdefs = 0;
364}
365
366/****************************************************************************
367* add_event
368****************************************************************************/
369
370static void add_event(ulong event, char *name, char *format)
371{
372 int i;
373 event_def_t *ep;
374
375 if (g_neventdefs >= NEVENTS) {
376 g_error("Too many event definitions, increase NEVENTS!");
377 /*NOTREACHED*/
378 }
379
380 /* Simple dup check, probably not needed very often */
381 for (i = 0; i < g_neventdefs; i++) {
382 if (g_eventdefs[i].event == event) {
383 g_warning("Duplicate def event %lu: first definition retained\n",
384 event);
385 return;
386 }
387 }
388
389 ep = &g_eventdefs[g_neventdefs++];
390
391 ep->event = event;
392 ep->name = sxerox(name);
393 ep->format = sxerox(format);
394 ep->selected = TRUE;
395}
396
397/****************************************************************************
398* add_event_from_cpel_file
399****************************************************************************/
400
401void add_event_from_cpel_file(ulong event, char *event_format,
402 char *datum_format)
403{
404 event_def_t *ep;
405
406 if (g_neventdefs >= NEVENTS) {
407 g_error("Too many event definitions, increase NEVENTS!");
408 /*NOTREACHED*/
409 }
410
411 ep = &g_eventdefs[g_neventdefs++];
412
413 ep->event = event;
414 /*
415 * Duplicate the strings for backward compatibility. Otherwise,
416 * the g_free above will barf because the name/format strings are
417 * actually in mmap'ed memory
418 */
419 ep->name = sxerox(event_format);
420 ep->format = sxerox(datum_format);
421 ep->selected = TRUE;
422}
423
424/****************************************************************************
425* add_event_from_clib_file
426****************************************************************************/
427
428void add_event_from_clib_file(unsigned int event, char *name,
429 unsigned int vec_index)
430{
431 event_def_t *ep;
432
433 if (g_neventdefs >= NEVENTS) {
434 g_error("Too many event definitions, increase NEVENTS!");
435 /*NOTREACHED*/
436 }
437
438 ep = &g_eventdefs[g_neventdefs++];
439
440 ep->event = event;
441
442 ep->name = sxerox(name);
443 ep->format = (void *)(unsigned long long) vec_index;
444 ep->selected = TRUE;
445 ep->is_clib = TRUE;
446}
447
448/****************************************************************************
449* read_header_file - eats header file lines of the form
450*
451* #define EVENT_FOO 123 / * name: %d * /
452*
453****************************************************************************/
454
455static void read_header_file (void)
456{
457 char tmpbuf [1024];
458 char *name, *format;
459 char *cp;
460 unsigned long event;
461 int ev_num_flag;
462
463 while (fgets (tmpbuf, sizeof (tmpbuf), s_hfp))
464 {
465 cp = tmpbuf;
466 ev_num_flag = 0;
467
468 if (strncmp (cp, "#define", 7))
469 continue;
470
471 /* skip #define */
472 while (*cp && !(isspace ((int)*cp)))
473 cp++;
474
475 if (*cp == 0)
476 continue;
477
478 /* skip ws after #define */
479 while (*cp && isspace ((int)*cp))
480 cp++;
481
482 if (*cp == 0)
483 continue;
484
485 /* skip symbolic name */
486 while (*cp && !(isspace ((int)*cp)))
487 cp++;
488
489 if (*cp == 0)
490 continue;
491
492 /* skip ws after symbolic name */
493 while (*cp && isspace ((int)*cp))
494 cp++;
495
496 if (*cp == 0)
497 continue;
498
499 event = 0;
500
501 if (!strncmp(cp, "EV_NUM", 6)) {
502 cp += 6;
503 ev_num_flag = 1;
504
505 while (*cp && *cp != '(')
506 cp++;
507
508 if (*cp == 0)
509 continue;
510
511 cp++;
512
513 while (*cp && isspace ((int)*cp))
514 cp++;
515
516 }
517
518 /* eat event code. */
519 while (*cp && isdigit ((int)*cp))
520 {
521 event = event * 10 + (*cp - '0');
522 cp++;
523 }
524
525 if (*cp == 0)
526 continue;
527
528 if (ev_num_flag) {
529 while (*cp && *cp != ')')
530 cp++;
531 if (*cp == 0)
532 continue;
533 cp++;
534 event += s_basenum;
535 }
536
537 /* skip ws after event code */
538 while (*cp && isspace ((int)*cp))
539 cp++;
540
541 if (*cp != '/')
542 continue;
543
544 cp++;
545
546 if (*cp != '*')
547 continue;
548
549 cp++;
550
551 /* skip ws after comment start */
552 while (*cp && isspace ((int)*cp))
553 cp++;
554
555 if (*cp == 0)
556 continue;
557
558 name = cp;
559
560 /* accumulate name */
561 while (*cp && *cp != ':' && *cp != '*')
562 cp++;
563
564 if (*cp == 0)
565 continue;
566
567 *cp++ = 0;
568
569 /* skip ws after name: */
570 while (*cp && isspace ((int)*cp))
571 cp++;
572
573 if (*cp == 0 || *cp == '/')
574 {
575 format = " ";
576 goto write_it;
577 }
578
579 format = cp;
580
581 /* accumulate format string */
582 while (*cp && !isspace ((int)*cp))
583 cp++;
584
585 *cp = 0;
586
587 write_it:
588
589 add_event (event, name, format);
590 }
591}
592
593/****************************************************************************
594* read_header_files - eats header file lines of the form
595*
596* #define FILE1_BASE 100 / * pointdefs: ../vpn/vpn_points.h * /
597*
598****************************************************************************/
599
600static boolean read_header_files (void)
601{
602 char *cp, *name;
603 char tmpbuf [1024];
604 int basenum;
605 boolean rv=FALSE;
606
607 while (fgets (tmpbuf, sizeof (tmpbuf), s_elog_hfp))
608 {
609 cp = tmpbuf;
610
611 if (strncmp (cp, "#define", 7))
612 continue;
613
614 cp += 7;
615
616 /* skip ws after #define */
617 while (*cp && isspace ((int)*cp))
618 cp++;
619
620 if (*cp == 0)
621 continue;
622
623 /* skip EV_COMPxxx_START */
624 while (*cp && !isspace((int)*cp))
625 cp++;
626
627 if (*cp == 0)
628 continue;
629
630 /* skip ws after EV_COMPxxx_START */
631 while (*cp && isspace ((int)*cp))
632 cp++;
633
634 if (*cp == 0)
635 continue;
636
637 basenum = atol (cp);
638
639 /* skip #define */
640 while (*cp && (*cp != '/'))
641 cp++;
642
643 if (*cp == 0)
644 continue;
645
646 cp++;
647 if (*cp != '*')
648 continue;
649
650 cp++;
651
652 /* skip ws after comment start */
653 while (*cp && isspace ((int)*cp))
654 cp++;
655
656 if (*cp == 0)
657 continue;
658
659 if (strncmp (cp, "pointdefs:", 10))
660 continue;
661
662 cp += 10;
663
664 /* skip ws after comment start */
665 while (*cp && isspace ((int)*cp))
666 cp++;
667
668 name = cp;
669
670 while (*cp && !isspace ((int)*cp))
671 cp++;
672
673 *cp = 0;
674
675 s_hfp = fopen (name, "rt");
676
677 if (s_hfp == NULL) {
678 g_warning ("Couldn't open header file %s\n", name);
679 continue;
680 }
681 rv = TRUE;
682
683 s_basenum = basenum;
684
685 read_header_file();
686
687 fclose (s_hfp);
688 }
689 return(rv);
690}
691
692/****************************************************************************
693* event_def_cmp
694****************************************************************************/
695
696int event_def_cmp(const void *a1, const void *a2)
697{
698 event_def_t *e1 = (event_def_t *)a1;
699 event_def_t *e2 = (event_def_t *)a2;
700
701 if (e1->event < e2->event)
702 return(-1);
703 else if (e1->event == e2->event)
704 return(0);
705 else
706 return(1);
707}
708
709/****************************************************************************
710* sort_event_definitions
711****************************************************************************/
712
713void sort_event_definitions(void)
714{
715 qsort(&g_eventdefs[0], g_neventdefs, sizeof(event_def_t), event_def_cmp);
716}
717
718static boolean remove_needed=TRUE;
719
720void finalize_events(void)
721{
722 sort_event_definitions();
723 create_point_selector();
724 recompute_ps_vscrollbar();
725 view1_display_when_idle();
726 remove_needed = TRUE;
727}
728
729void initialize_events(void)
730{
731 if (remove_needed) {
732 reset_point_selector();
733 remove_all_events();
734 remove_needed = FALSE;
735 }
736}
737
738/****************************************************************************
739* read_event_definitions
740****************************************************************************/
741
742boolean read_event_definitions (char *filename)
743{
744 char tmpbuf [128];
745
746 initialize_events();
747
748 s_elog_hfp = fopen (filename, "rt");
749 if (s_elog_hfp == NULL) {
750 sprintf (tmpbuf, "Couldn't open %s\n", filename);
751 infobox ("Open Failed", tmpbuf);
752 return(FALSE);
753 }
754 /* Presume "elog.h". Note fallthrough... */
755 if (read_header_files()) {
756 sort_event_definitions();
757 create_point_selector();
758 recompute_ps_vscrollbar();
759 fclose(s_elog_hfp);
760 view1_display_when_idle();
761 remove_needed = TRUE;
762 return(TRUE);
763 }
764 fclose(s_elog_hfp);
765
766 s_hfp = fopen (filename, "rt");
767 if (s_hfp == NULL) {
768 sprintf (tmpbuf, "Couldn't open %s\n", filename);
769 infobox ("Read Event Definition Failure", tmpbuf);
770 return(FALSE);
771 }
772
773 read_header_file();
774
775 /* Happens if the user feeds us the wrong file, for example */
776 if (g_neventdefs == 0) {
777 sprintf (tmpbuf, "No event definitions found in %s\n", filename);
778 infobox ("No Event Definitions?", tmpbuf);
779 return(FALSE);
780 }
781 finalize_events();
782 return(TRUE);
783}
784
785static event_def_t dummy_event;
786static char dummy_string[32];
787
788/****************************************************************************
789* find_event_definition
790* Binary search for first event whose time is >= t
791****************************************************************************/
792
793event_def_t *find_event_definition (ulong code)
794{
795 int index, bottom, top;
796 event_def_t *edp;
797
798 if (g_neventdefs == 0)
799 goto use_dummy;
800
801 bottom = g_neventdefs-1;
802 top = 0;
803
804 while (1) {
805 index = (bottom + top) / 2;
806
807 edp = (g_eventdefs + index);
808
809 if (edp->event == code)
810 return(edp);
811
812 if (top >= bottom) {
813 use_dummy:
814 edp = &dummy_event;
815 edp->selected = TRUE;
816 edp->event = code;
817 edp->format = "0x%x";
818 sprintf (dummy_string, "E%lu", code);
819 edp->name = &dummy_string[0];
820 return(edp);
821 }
822
823 if (edp->event < code)
824 top = index + 1;
825 else
826 bottom = index - 1;
827 }
828}
829
830/****************************************************************************
831* pointsel_next_snapshot
832* Set dialog buttons from snapshot
833****************************************************************************/
834
835void pointsel_next_snapshot(void)
836{
837 int i;
838
839 for (i = 0; i < g_neventdefs; i++) {
840 gtk_toggle_button_set_active (
841 GTK_TOGGLE_BUTTON(s_event_buttons[i]),
842 g_eventdefs[i].selected);
843 }
844}
845
846/****************************************************************************
847* pointsel_about
848****************************************************************************/
849
850void pointsel_about (char *tmpbuf)
851{
852 sprintf (tmpbuf+strlen(tmpbuf), "%d event definitions\n",
853 g_neventdefs);
854}