Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / tools / fscope / interact.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* Hypervisor Software File: interact.c
5*
6* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
7*
8* - Do no alter or remove copyright notices
9*
10* - Redistribution and use of this software in source and binary forms, with
11* or without modification, are permitted provided that the following
12* conditions are met:
13*
14* - Redistribution of source code must retain the above copyright notice,
15* this list of conditions and the following disclaimer.
16*
17* - Redistribution in binary form must reproduce the above copyright notice,
18* this list of conditions and the following disclaimer in the
19* documentation and/or other materials provided with the distribution.
20*
21* Neither the name of Sun Microsystems, Inc. or the names of contributors
22* may be used to endorse or promote products derived from this software
23* without specific prior written permission.
24*
25* This software is provided "AS IS," without a warranty of any kind.
26* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
27* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
28* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
29* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
30* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
31* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
32* OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
33* FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
34* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
35* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
36* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
37*
38* You acknowledge that this software is not designed, licensed or
39* intended for use in the design, construction, operation or maintenance of
40* any nuclear facility.
41*
42* ========== Copyright Header End ============================================
43*/
44/*
45 * @(#)interact.c 1.1 02/05/02
46 * Copyright 2001-2002 Sun Microsystems, Inc. All Rights Reserved
47 * Copyright Use is subject to license terms.
48 */
49#include <stdio.h>
50#include <stdlib.h>
51#include <unistd.h>
52#include <string.h>
53#include <curses.h>
54
55#include "fscope.h"
56
57typedef struct ISTRUCT_T {
58 WINDOW *win; /* main screen */
59 int info_line; /* line# for information text */
60 int cmdnum; /* command selected */
61 int lmargin; /* left margin of selected command */
62 int col; /* cursor position on cmd line */
63 int line; /* which line we are on */
64 int error; /* error status, status string contains msg */
65 char *status; /* status message */
66 char *input_line; /* input buffer, at least as wide as screen */
67 int ipoint; /* insertion point */
68 int ilen; /* current command length */
69 int matches; /* number of matches found */
70 int start; /* offset within matches */
71 int tag_mode; /* tag_mode status */
72 int tagged; /* number of things tagged */
73 search_t *tags; /* list of tagged matches */
74 search_t *items[9]; /* the 1-9 items on the screen */
75 search_t *list; /* current match list */
76 search_t *displaying; /* where we are displaying in the above list */
77} istruct_t;
78
79#define NUM_COMMANDS (sizeof (commands) / sizeof (command_t))
80
81typedef struct COMMAND_T {
82 char *id;
83 int cursor;
84 int line;
85 void (*finder)(extract_t *info, istruct_t *w);
86} command_t;
87
88#define DEBUG
89#define CONTROL -('A'-1) +
90
91#ifdef DEBUG
92#define DEBUGL(y, x) move(y, 0); clrtoeol(); printw x; refresh();
93#else
94#define DEBUGL(y, x)
95#endif
96
97static void
98free_tag(istruct_t *w, search_t *item)
99{
100 search_t *tag = item->private;
101 search_t *next, *prev;
102
103 if (tag == NULL)
104 return;
105 next = tag->next;
106 prev = tag->prev;
107 if (tag->next != NULL) {
108 tag->next->prev = prev;
109 }
110 if (prev != NULL) {
111 prev->next = next;
112 } else {
113 w->tags = tag->next;
114 }
115 free(tag);
116 w->tagged--;
117 item->private = NULL;
118}
119
120static void
121tag_item(istruct_t *w, search_t *item)
122{
123 search_t *new;
124
125 if (item->private == NULL) {
126 new = new_search_t();
127 new->xref = item->xref;
128 new->next = w->tags;
129 new->prev = NULL;
130 new->private = item;
131 if (w->tags != NULL) {
132 w->tags->prev = new;
133 }
134 w->tags = new;
135 w->tagged++;
136 item->private = new;
137 } else {
138 free_tag(w, item);
139 item->private = NULL;
140 }
141}
142
143static void
144cancel_tags(istruct_t *w)
145{
146 search_t *ptr, *next;
147
148 w->tag_mode = 0;
149 w->tagged = 0;
150 ptr = w->tags;
151 while (ptr) {
152 next = ptr->next;
153 free_tag(w, ptr->private);
154 ptr = next;
155 }
156 w->tags = NULL;
157}
158
159static void
160find_exact_definition(extract_t *info, istruct_t *w)
161{
162 search_t *list;
163
164 info->symbol = w->input_line;
165 info->flags &= ~FLAG_REGEXP;
166 w->list = build_searchlist(info, NULL,
167 (XREF_DEFINITION | XREF_FORWARD));
168}
169
170static void
171find_regexp_definition(extract_t *info, istruct_t *w)
172{
173 info->symbol = w->input_line;
174 info->flags |= FLAG_REGEXP;
175 w->list = build_searchlist(info, NULL,
176 (XREF_DEFINITION | XREF_FORWARD));
177}
178
179static void
180find_file(extract_t *info, istruct_t *w)
181{
182 xref_file_t *fptr = info->state->sources;
183 search_t *new, *list = NULL;
184 xref_t *xref;
185
186 info->symbol = w->input_line;
187
188 while (fptr != NULL) {
189 if (strstr(fptr->name, info->symbol) != NULL) {
190 int i, j;
191
192 xref = NULL;
193 for (i = 0; ((i < 128) && (xref == NULL)); i++) {
194 xref = fptr->defs[i];
195 }
196 new = new_search_t();
197 new->xref = xref;
198 new->next = list;
199 list = new;
200 }
201 fptr = fptr->next;
202 }
203 w->list = list;
204}
205
206static void
207find_callers_of(extract_t *info, istruct_t *w)
208{
209 search_t *list, *item;
210 search_t *callers;
211 int j;
212 xref_t *xref;
213 ref_t *rref;
214
215 info->symbol = w->input_line;
216 info->flags &= ~FLAG_REGEXP;
217 if (w->tag_mode) {
218 item = w->tags;
219 } else {
220 item = build_searchlist(info, NULL, XREF_DEFINITION);
221 if (item == NULL) {
222 return;
223 }
224 if (item->next != NULL) {
225 w->status = "more than one defintion, "
226 "refine your search using a tag";
227 w->error = 1;
228 free_searchlist(item);
229 w->list = NULL;
230 return;
231 }
232 }
233 ASSERT((item != NULL), "tagged with item NULL??");
234 list = NULL;
235 while (item != NULL) {
236 xref = item->xref;
237 rref = &xref->called_by;
238 for (j = 0; j < rref->insert; j++) {
239 callers = new_search_t();
240 callers->xref = rref->ptr[j];
241 callers->next = list;
242 list = callers;
243 }
244 item = item->next;
245 }
246 if (w->tag_mode) {
247 cancel_tags(w);
248 } else {
249 free_searchlist(item);
250 }
251 w->list = list;
252}
253
254static void
255find_text_string(extract_t *info, istruct_t *w)
256{
257 search_t *list;
258
259 info->symbol = w->input_line;
260 info->flags |= FLAG_REGEXP;
261 w->list = build_searchlist(info, NULL,
262 (XREF_STRING | XREF_DEFINITION));
263}
264
265command_t commands[] = {
266 { "Find definition:", 0, 0, find_exact_definition },
267 { "Find fuzzy definition:", 0, 1, find_regexp_definition },
268 { "Find callers of routine:", 0, 2, find_callers_of },
269 { "Find text string:", 0, 3, find_text_string },
270 { "Change text string:", 0, 4, NULL },
271 { "Change definition name:", 0, 5, NULL },
272 { "Find file:", 0, 6, find_file },
273};
274
275static void
276draw_command(extract_t *info, istruct_t *w)
277{
278 static int computed_pos = 0;
279 int i;
280 command_t *cptr;
281
282 if (!computed_pos) {
283 for (i = 0; i < NUM_COMMANDS; i++) {
284 cptr = &commands[i];
285 if (cptr->cursor == 0) {
286 cptr->cursor = strlen(cptr->id)+1;
287 cptr->line += (LINES - NUM_COMMANDS);
288 }
289 }
290 w->info_line = commands[0].line -1;
291 computed_pos = 1;
292 }
293 move(commands[0].line, 0);
294 clrtobot();
295
296 for (i = 0; i < NUM_COMMANDS; i++) {
297 cptr = &commands[i];
298 mvprintw(cptr->line, 0, cptr->id);
299 }
300 w->col = commands[w->cmdnum].cursor;
301 w->line = commands[w->cmdnum].line;
302 w->lmargin = w->col;
303 move(w->line, w->col);
304 refresh();
305}
306
307static void
308hit_counter(extract_t *info, search_t *item)
309{
310 int *iptr = info->private;
311 (*iptr)++;
312}
313
314static char *
315run_search(extract_t *info, istruct_t *w)
316{
317 if ((w->ilen == 0) && !w->tag_mode) {
318 return ("Nothing to Do");
319 }
320 if (commands[w->cmdnum].finder != NULL) {
321 w->matches = 0;
322 w->start = 0;
323 w->error = 0;
324 commands[w->cmdnum].finder(info, w);
325 if (w->error == 0) {
326 info->private = &w->matches;
327 w->displaying = w->list;
328 iterate_list(info, w->list, hit_counter);
329 if (w->matches == 0) {
330 return ("Nothing Found");
331 }
332 return ("");
333 }
334 return (w->status);
335 }
336 return ("<unimplemented command>");
337}
338
339static void
340match_mode(extract_t *info, istruct_t *w, int c)
341{
342 int i;
343 search_t *this;
344 search_t *selected;
345
346redraw:
347 selected = NULL;
348 for (i = 0; i < 9; i++) {
349 move(i, 0);
350 clrtoeol();
351 w->items[i] = NULL;
352 }
353 i = 0;
354 this = w->displaying;
355 while ((i < 9) && (this != NULL)) {
356 w->items[i] = this;
357 mvprintw(i, 0, " %d%c[%c%c%c] %s:%d .. %s ..\n",
358 ((i+1)%10),
359 ((this->private == NULL) ? ' ' : '>'),
360 ((this->xref->flags & XREF_FORWARD) ? 'F' : '.'),
361 ((this->xref->flags & XREF_DEFINITION) ? 'D' : '.'),
362 ((this->xref->flags & XREF_STRING) ? 'S' : '.'),
363 expand_filename(info, this->xref),
364 this->xref->linenum,
365 this->xref->name);
366 this = this->next;
367 i++;
368 }
369 refresh();
370 if (c == 't') {
371 if (w->tag_mode) {
372 w->tag_mode = 0;
373 } else {
374 w->tag_mode = 1;
375 }
376 return;
377 }
378 if (c == ' ') {
379 if (w->matches > 9) {
380 if ((w->start + i) == w->matches) {
381 w->start = 0;
382 w->displaying = w->list;
383 } else {
384 w->displaying = this;
385 w->start += i;
386 }
387 }
388 c = 0;
389 goto redraw;
390 }
391 if ((c > '0') && (c <= '9')) {
392 selected = w->items[c-'1'];
393 if (w->tag_mode) {
394 tag_item(w, selected);
395 c = 0;
396 goto redraw;
397 } else
398 goto selected;
399 }
400 if (((c == '*') || (c == '&')) && (w->tag_mode)) {
401 int i;
402 search_t *this;
403 for (i = 0; i < 9; i++) {
404 this = w->items[i];
405 if (this != NULL) {
406 if (c == '&') {
407 free_tag(w, this);
408 } else {
409 tag_item(w, this);
410 }
411 }
412 }
413 c = 0;
414 goto redraw;
415 }
416 if ((c == 0x4)) {
417 /* Control D */
418 free_searchlist(w->list);
419 w->list = NULL;
420 w->displaying = NULL;
421 w->start = 0;
422 w->matches = 0;
423 if (w->tagged == 0) {
424 w->tag_mode = 0;
425 }
426 return;
427 }
428 if (c == 0x1b) {
429 /* Escape. */
430 cancel_tags(w);
431 free_searchlist(w->list);
432 w->list = NULL;
433 w->displaying = NULL;
434 w->start = 0;
435 w->matches = 0;
436 return;
437 }
438selected:
439 if (selected && !w->tag_mode) {
440 char *syscommand;
441 int bytes;
442 char *file;
443 char *editor;
444
445 editor = getenv("EDITOR");
446 if (editor == NULL) {
447 editor = "/bin/vi";
448 }
449 bytes = strlen(editor);
450 file = expand_filename(info, selected->xref);
451 bytes += strlen(file);
452 bytes += 20;
453 syscommand = malloc(bytes);
454 snprintf(syscommand, bytes, "%s +%d %s",
455 editor, selected->xref->linenum,
456 file);
457 endwin();
458 system(syscommand);
459 refresh();
460 free(syscommand);
461 }
462}
463
464static char *
465select_mode(extract_t *info, istruct_t *w, int c)
466{
467 char *tstatus;
468
469 tstatus = "";
470
471 switch (c) {
472 case CONTROL 'B':
473 case KEY_LEFT:
474 if (w->ipoint) {
475 w->ipoint--;
476 w->col--;
477 }
478 if (0) move(w->line, w->col);
479 break;
480
481 case CONTROL 'F':
482 case KEY_RIGHT:
483 if (w->ipoint < w->ilen) {
484 w->ipoint++;
485 w->col++;
486 }
487 if (0) move(w->line, w->col);
488 break;
489
490 case CONTROL 'P':
491 case KEY_UP:
492 if (w->cmdnum)
493 w->cmdnum--;
494 else
495 w->cmdnum = NUM_COMMANDS-1;
496 w->ipoint = 0;
497 w->ilen = 0;
498 draw_command(info, w);
499 break;
500
501 case CONTROL 'N':
502 case CONTROL 'I':
503 case KEY_DOWN:
504 if (w->cmdnum < (NUM_COMMANDS-1))
505 w->cmdnum++;
506 else
507 w->cmdnum = 0;
508 w->ipoint = 0;
509 w->ilen = 0;
510 draw_command(info, w);
511 break;
512
513 case CONTROL 'M':
514 case CONTROL 'J':
515 w->status = run_search(info, w);
516 if (w->matches) {
517 match_mode(info, w, 0);
518 }
519 break;
520
521 case CONTROL 'A':
522 w->ipoint = 0;
523 w->col = w->lmargin;
524 if (0) move(w->line, w->col);
525 break;
526
527 case 127:
528 case CONTROL 'H':
529 if (w->ipoint > 0) {
530 char *here = w->input_line + w->ipoint;
531 memcpy(here-1, here, (w->ilen - w->ipoint)+1);
532 w->ilen--;
533 w->col--;
534 w->ipoint--;
535 }
536 move(w->line, w->col);
537 clrtoeol();
538 mvprintw(w->line, w->lmargin, w->input_line);
539 if (0) move(w->line, w->col);
540 break;
541
542 case CONTROL 'D':
543 if (w->ipoint < w->ilen) {
544 char *here = w->input_line + w->ipoint;
545 memcpy(here, here+1, (w->ilen - w->ipoint));
546 w->ilen--;
547 }
548 move(w->line, w->col);
549 clrtoeol();
550 mvprintw(w->line, w->lmargin, w->input_line);
551 if (0) move(w->line, w->col);
552 break;
553
554 case CONTROL 'E':
555 w->ipoint = w->ilen;
556 w->col = w->lmargin + w->ilen;
557 if (0) move(w->line, w->col);
558 break;
559
560 case CONTROL 'K':
561 w->input_line[w->ipoint] = 0;
562 clrtoeol();
563 mvprintw(w->line, w->lmargin, w->input_line);
564 if (0) move(w->line, w->col);
565 break;
566
567 case 0x1b:
568 /* Escape, cancel all tags etc */
569 cancel_tags(w);
570 break;
571
572 default:
573 if ((c >= ' ') && (c <= 'z')) {
574 mvprintw(w->line, w->col, "%c", c);
575 if (w->col < (COLS-2)) {
576 w->input_line[w->ipoint++] = c;
577 w->col++;
578 }
579 if (w->ipoint > w->ilen) {
580 w->input_line[w->ipoint] = 0;
581 w->ilen = w->ipoint;
582 }
583 }
584 break;
585 }
586 return (tstatus);
587}
588
589void
590xref_interactive_mode(extract_t *info)
591{
592 istruct_t *w;
593 int c;
594 char *tstatus;
595 char add_status[20];
596
597 w = malloc(sizeof (istruct_t));
598 memset(w, 0, sizeof (istruct_t));
599 w->win = initscr();
600 w->cmdnum = 0;
601 clear();
602 cbreak();
603 noecho();
604 keypad(w->win, 1);
605 mvprintw(0, 0, "match window");
606 refresh();
607
608 draw_command(info, w);
609 c = 0;
610 w->ipoint = 0;
611 w->ilen = 0;
612 w->matches = 0;
613 w->input_line = malloc(COLS);
614 w->input_line[w->ipoint] = 0;
615 w->status = "";
616 w->tags = NULL;
617 w->displaying = NULL;
618 w->list = NULL;
619 while (c != EOF) {
620 move(w->info_line, 0);
621 clrtoeol();
622 add_status[0] = 0;
623 if (w->tag_mode) {
624 snprintf(add_status, sizeof (add_status),
625 "[Tagged:%d]", w->tagged);
626 }
627 if (w->matches) {
628 int upper, rem;
629
630 rem = w->matches - w->start;
631 if (rem > 9) {
632 upper = w->start + 9;
633 rem -= 9;
634 } else {
635 upper = w->start + rem;
636 rem = 0;
637 }
638 if (!rem) {
639 mvprintw(w->info_line, 0,
640 "Status %s: displaying %d-%d"
641 " [press ESC to exit]",
642 add_status, (w->start+1), upper);
643 } else {
644 mvprintw(w->info_line, 0,
645 "Status %s: displaying %d-%d, %d more"
646 " [press SPACE for more, ESC to exit]",
647 add_status, (w->start+1), upper, rem);
648 }
649 } else {
650 mvprintw(w->info_line, 0,
651 "Select %s mode: %s", add_status, w->status);
652 }
653 c = mvgetch(w->line, w->col);
654 w->status = "";
655
656 if (w->matches)
657 match_mode(info, w, c);
658 else
659 tstatus = select_mode(info, w, c);
660 refresh();
661 }
662
663 nocbreak();
664 echo();
665 keypad(w->win, 0);
666}