Print this page
3471 cscope-fast writes constant strings when erroring
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/cscope-fast/display.c
+++ new/usr/src/tools/cscope-fast/display.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
21 21 */
22 22 /* Copyright (c) 1988 AT&T */
23 23 /* All Rights Reserved */
24 24
25 25
26 26 /*
27 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 28 * Use is subject to license terms.
29 29 */
30 30
31 -#pragma ident "%Z%%M% %I% %E% SMI"
32 -
33 31 /*
34 32 * cscope - interactive C symbol cross-reference
35 33 *
36 34 * display functions
37 35 */
38 36
39 37 #include "global.h"
40 38 #include "version.h" /* FILEVERSION and FIXVERSION */
41 39 #include <curses.h> /* COLS and LINES */
42 40 #include <setjmp.h> /* jmp_buf */
43 41 #include <string.h>
44 42 #include <errno.h>
45 43
46 44 /* see if the function column should be displayed */
47 45 #define displayfcn() (field <= ASSIGN)
48 46
49 47 #define MINCOLS 68 /* minimum columns for 3 digit Lines message numbers */
50 48
51 49 int *displine; /* screen line of displayed reference */
52 50 int disprefs; /* displayed references */
53 51 int field; /* input field */
54 52 unsigned fldcolumn; /* input field column */
55 53 int mdisprefs; /* maximum displayed references */
56 54 int selectlen; /* selection number field length */
57 55 int nextline; /* next line to be shown */
58 56 int topline = 1; /* top line of page */
59 57 int bottomline; /* bottom line of page */
60 58 int totallines; /* total reference lines */
61 59 FILE *refsfound; /* references found file */
62 60 FILE *nonglobalrefs; /* non-global references file */
63 61
64 62 static int fldline; /* input field line */
65 63 static int subsystemlen; /* OGS subsystem name display */
66 64 /* field length */
67 65 static int booklen; /* OGS book name display field length */
68 66 static int filelen; /* file name display field length */
69 67 static int fcnlen; /* function name display field length */
70 68 static jmp_buf env; /* setjmp/longjmp buffer */
71 69 static int lastdispline; /* last displayed reference line */
72 70 static char lastmsg[MSGLEN + 1]; /* last message displayed */
73 71 static int numlen; /* line number display field length */
74 72 static char depthstring[] = "Depth: ";
75 73 static char helpstring[] = "Press the ? key for help";
76 74
77 75
78 76 typedef char *(*FP)(); /* pointer to function returning a character pointer */
79 77
80 78 static struct {
81 79 char *text1;
82 80 char *text2;
83 81 FP findfcn;
84 82 enum {
85 83 EGREP,
86 84 REGCMP
87 85 } patterntype;
88 86 } fields[FIELDS + 1] = {
89 87 /* last search is not part of the cscope display */
90 88 { "Find this", "C symbol",
91 89 (FP) findsymbol, REGCMP},
92 90 { "Find this", "definition",
93 91 (FP) finddef, REGCMP},
94 92 { "Find", "functions called by this function",
95 93 (FP) findcalledby, REGCMP},
96 94 { "Find", "functions calling this function",
97 95 (FP) findcalling, REGCMP},
98 96 { "Find", "assignments to",
99 97 (FP) findassignments, REGCMP},
100 98 { "Change this", "grep pattern",
101 99 findgreppat, EGREP},
102 100 { "Find this", "egrep pattern",
103 101 findegreppat, EGREP},
104 102 { "Find this", "file",
105 103 (FP) findfile, REGCMP},
106 104 { "Find", "files #including this file",
107 105 (FP) findinclude, REGCMP},
108 106 { "Find all", "function/class definitions",
109 107 (FP) findallfcns, REGCMP},
110 108 };
111 109
112 110 /* initialize display parameters */
113 111
114 112 void
115 113 dispinit(void)
116 114 {
117 115 /* calculate the maximum displayed reference lines */
118 116 lastdispline = FLDLINE - 2;
119 117 mdisprefs = lastdispline - REFLINE + 1;
120 118 if (mdisprefs <= 0) {
121 119 (void) printw("cscope: window must be at least %d lines high",
122 120 FIELDS + 6);
123 121 myexit(1);
124 122 }
125 123 if (COLS < MINCOLS) {
126 124 (void) printw("cscope: window must be at least %d columns wide",
127 125 MINCOLS);
128 126 myexit(1);
129 127 }
130 128 if (!mouse) {
131 129 if (returnrequired == NO && mdisprefs > 9) {
132 130 mdisprefs = 9; /* single digit selection number */
133 131 }
134 132 /* calculate the maximum selection number width */
135 133 (void) sprintf(newpat, "%d", mdisprefs);
136 134 selectlen = strlen(newpat);
137 135 }
138 136 /* allocate the displayed line array */
139 137 displine = (int *)mymalloc(mdisprefs * sizeof (int));
140 138 }
141 139
142 140 /* display a page of the references */
143 141
144 142 void
145 143 display(void)
146 144 {
147 145 char *subsystem; /* OGS subsystem name */
148 146 char *book; /* OGS book name */
149 147 char file[PATHLEN + 1]; /* file name */
150 148 char function[PATLEN + 1]; /* function name */
151 149 char linenum[NUMLEN + 1]; /* line number */
152 150 int screenline; /* screen line number */
153 151 int width; /* source line display width */
154 152 int i;
155 153 char *s;
156 154
157 155 (void) erase();
158 156
159 157 /* if there are no references */
160 158 if (totallines == 0) {
161 159 if (*lastmsg != '\0') {
162 160 (void) addstr(lastmsg); /* redisplay any message */
163 161 } else {
164 162 (void) printw("Cscope version %d%s", FILEVERSION,
165 163 FIXVERSION);
166 164 (void) move(0, COLS - (int)sizeof (helpstring));
167 165 (void) addstr(helpstring);
168 166 }
169 167 } else { /* display the pattern */
170 168 if (changing == YES) {
171 169 (void) printw("Change \"%s\" to \"%s\"",
172 170 pattern, newpat);
173 171 } else {
174 172 (void) printw("%c%s: %s",
175 173 toupper(fields[field].text2[0]),
176 174 fields[field].text2 + 1, pattern);
177 175 }
178 176 /* display the cscope invocation nesting depth */
179 177 if (cscopedepth > 1) {
180 178 (void) move(0, COLS - (int)sizeof (depthstring) - 2);
181 179 (void) addstr(depthstring);
182 180 (void) printw("%d", cscopedepth);
183 181 }
184 182 /* display the column headings */
185 183 (void) move(2, selectlen + 1);
186 184 if (ogs == YES && field != FILENAME) {
187 185 (void) printw("%-*s ", subsystemlen, "Subsystem");
188 186 (void) printw("%-*s ", booklen, "Book");
189 187 }
190 188 if (dispcomponents > 0) {
191 189 (void) printw("%-*s ", filelen, "File");
192 190 }
193 191 if (displayfcn()) {
194 192 (void) printw("%-*s ", fcnlen, "Function");
195 193 }
196 194 if (field != FILENAME) {
197 195 (void) addstr("Line");
198 196 }
199 197 (void) addch('\n');
200 198
201 199 /* if at end of file go back to beginning */
202 200 if (nextline > totallines) {
203 201 seekline(1);
204 202 }
205 203 /* calculate the source text column */
206 204 width = COLS - selectlen - numlen - 2;
207 205 if (ogs == YES) {
208 206 width -= subsystemlen + booklen + 2;
209 207 }
210 208 if (dispcomponents > 0) {
211 209 width -= filelen + 1;
212 210 }
213 211 if (displayfcn()) {
214 212 width -= fcnlen + 1;
215 213 }
216 214 /*
217 215 * until the max references have been displayed or
218 216 * there is no more room
219 217 */
220 218 topline = nextline;
221 219 for (disprefs = 0, screenline = REFLINE;
222 220 disprefs < mdisprefs && screenline <= lastdispline;
223 221 ++disprefs, ++screenline) {
224 222 /* read the reference line */
225 223 if (fscanf(refsfound, "%s%s%s %[^\n]", file, function,
226 224 linenum, yytext) < 4) {
227 225 break;
228 226 }
229 227 ++nextline;
230 228 displine[disprefs] = screenline;
231 229
232 230 /* if no mouse, display the selection number */
233 231 if (!mouse) {
234 232 (void) printw("%*d", selectlen, disprefs + 1);
235 233 }
236 234 /* display any change mark */
237 235 if (changing == YES &&
238 236 change[topline + disprefs - 1] == YES) {
239 237 (void) addch('>');
240 238 } else {
241 239 (void) addch(' ');
242 240 }
243 241 /* display the file name */
244 242 if (field == FILENAME) {
245 243 (void) printw("%-.*s\n", COLS - 3, file);
246 244 continue;
247 245 }
248 246 /* if OGS, display the subsystem and book names */
249 247 if (ogs == YES) {
250 248 ogsnames(file, &subsystem, &book);
251 249 (void) printw("%-*.*s ", subsystemlen,
252 250 subsystemlen, subsystem);
253 251 (void) printw("%-*.*s ", booklen, booklen,
254 252 book);
255 253 }
256 254 /* display the requested path components */
257 255 if (dispcomponents > 0) {
258 256 (void) printw("%-*.*s ", filelen, filelen,
259 257 pathcomponents(file, dispcomponents));
260 258 }
261 259 /* display the function name */
262 260 if (displayfcn()) {
263 261 (void) printw("%-*.*s ", fcnlen, fcnlen,
264 262 function);
265 263 }
266 264 /* display the line number */
267 265 (void) printw("%*s ", numlen, linenum);
268 266
269 267 /* there may be tabs in egrep output */
270 268 while ((s = strchr(yytext, '\t')) != NULL) {
271 269 *s = ' ';
272 270 }
273 271 /* display the source line */
274 272 s = yytext;
275 273 for (;;) {
276 274 /* see if the source line will fit */
277 275 if ((i = strlen(s)) > width) {
278 276 /* find the nearest blank */
279 277 for (i = width; s[i] != ' ' && i > 0;
280 278 --i) {
281 279 }
282 280 if (i == 0) {
283 281 i = width; /* no blank */
284 282 }
285 283 }
286 284 /* print up to this point */
287 285 (void) printw("%.*s", i, s);
288 286 s += i;
289 287
290 288 /* if line didn't wrap around */
291 289 if (i < width) {
292 290 /* go to next line */
293 291 (void) addch('\n');
294 292 }
295 293 /* skip blanks */
296 294 while (*s == ' ') {
297 295 ++s;
298 296 }
299 297 /* see if there is more text */
300 298 if (*s == '\0') {
301 299 break;
302 300 }
303 301 /* if the source line is too long */
304 302 if (++screenline > lastdispline) {
305 303 /*
306 304 * if this is the first displayed line,
307 305 * display what will fit on the screen
308 306 */
309 307 if (topline == nextline - 1) {
310 308 goto endrefs;
311 309 }
312 310 /* erase the reference */
313 311 while (--screenline >=
314 312 displine[disprefs]) {
315 313 (void) move(screenline, 0);
316 314 (void) clrtoeol();
317 315 }
318 316 ++screenline;
319 317
320 318 /*
321 319 * go back to the beginning of this
322 320 * reference
323 321 */
324 322 --nextline;
325 323 seekline(nextline);
326 324 goto endrefs;
327 325 }
328 326 /* indent the continued source line */
329 327 (void) move(screenline, COLS - width);
330 328 }
331 329
332 330 }
333 331 endrefs:
334 332 /* check for more references */
335 333 bottomline = nextline;
336 334 if (bottomline - topline < totallines) {
337 335 (void) move(FLDLINE - 1, 0);
338 336 (void) standout();
339 337 (void) printw("%*s", selectlen + 1, "");
340 338 if (bottomline - 1 == topline) {
341 339 (void) printw("Line %d", topline);
342 340 } else {
343 341 (void) printw("Lines %d-%d", topline,
344 342 bottomline - 1);
345 343 }
346 344 (void) printw(" of %d, press the space bar to "
347 345 "display next lines", totallines);
348 346 (void) standend();
349 347 }
350 348 }
351 349 /* display the input fields */
352 350 (void) move(FLDLINE, 0);
353 351 for (i = 0; i < FIELDS; ++i) {
354 352 (void) printw("%s %s:\n", fields[i].text1, fields[i].text2);
355 353 }
356 354 drawscrollbar(topline, nextline, totallines);
357 355 }
358 356
359 357 /* set the cursor position for the field */
360 358 void
361 359 setfield(void)
362 360 {
363 361 fldline = FLDLINE + field;
364 362 fldcolumn = strlen(fields[field].text1) +
365 363 strlen(fields[field].text2) + 3;
366 364 }
367 365
368 366 /* move to the current input field */
369 367
370 368 void
371 369 atfield(void)
372 370 {
373 371 (void) move(fldline, (int)fldcolumn);
374 372 }
375 373
376 374 /* search for the symbol or text pattern */
377 375
378 376 /*ARGSUSED*/
379 377 SIGTYPE
380 378 jumpback(int sig)
381 379 {
382 380 longjmp(env, 1);
383 381 }
384 382
385 383 BOOL
386 384 search(void)
387 385 {
388 386 char *egreperror = NULL; /* egrep error message */
389 387 FINDINIT rc = NOERROR; /* findinit return code */
390 388 SIGTYPE (*savesig)(); /* old value of signal */
391 389 FP f; /* searching function */
392 390 char *s;
393 391 int c;
394 392
395 393 /* note: the pattern may have been a cscope argument */
396 394 if (caseless == YES) {
397 395 for (s = pattern; *s != '\0'; ++s) {
398 396 *s = tolower(*s);
399 397 }
400 398 }
401 399 /* open the references found file for writing */
402 400 if (writerefsfound() == NO) {
403 401 return (NO);
404 402 }
405 403 /* find the pattern - stop on an interrupt */
406 404 if (linemode == NO) {
407 405 putmsg("Searching");
408 406 }
409 407 initprogress();
410 408 if (setjmp(env) == 0) {
411 409 savesig = signal(SIGINT, jumpback);
412 410 f = fields[field].findfcn;
413 411 if (fields[field].patterntype == EGREP) {
414 412 egreperror = (*f)(pattern);
415 413 } else {
416 414 if ((nonglobalrefs = fopen(temp2, "w")) == NULL) {
417 415 cannotopen(temp2);
418 416 return (NO);
419 417 }
420 418 if ((rc = findinit()) == NOERROR) {
421 419 (void) dbseek(0L); /* goto the first block */
422 420 (*f)();
423 421 findcleanup();
424 422
425 423 /* append the non-global references */
426 424 (void) freopen(temp2, "r", nonglobalrefs);
427 425 while ((c = getc(nonglobalrefs)) != EOF) {
428 426 (void) putc(c, refsfound);
429 427 }
430 428 }
431 429 (void) fclose(nonglobalrefs);
432 430 }
433 431 }
434 432 (void) signal(SIGINT, savesig);
435 433 /* reopen the references found file for reading */
436 434 (void) freopen(temp1, "r", refsfound);
437 435 nextline = 1;
438 436 totallines = 0;
439 437
440 438 /* see if it is empty */
441 439 if ((c = getc(refsfound)) == EOF) {
442 440 if (egreperror != NULL) {
443 441 (void) sprintf(lastmsg, "Egrep %s in this pattern: %s",
444 442 egreperror, pattern);
445 443 } else if (rc == NOTSYMBOL) {
446 444 (void) sprintf(lastmsg, "This is not a C symbol: %s",
447 445 pattern);
448 446 } else if (rc == REGCMPERROR) {
449 447 (void) sprintf(lastmsg,
450 448 "Error in this regcmp(3X) regular expression: %s",
451 449 pattern);
452 450 } else {
453 451 (void) sprintf(lastmsg, "Could not find the %s: %s",
454 452 fields[field].text2, pattern);
455 453 }
456 454 return (NO);
457 455 }
458 456 /* put back the character read */
459 457 (void) ungetc(c, refsfound);
460 458
461 459 countrefs();
462 460 return (YES);
463 461 }
464 462
465 463 /* open the references found file for writing */
466 464
467 465 BOOL
468 466 writerefsfound(void)
469 467 {
470 468 if (refsfound == NULL) {
471 469 if ((refsfound = fopen(temp1, "w")) == NULL) {
472 470 cannotopen(temp1);
473 471 return (NO);
474 472 }
475 473 } else if (freopen(temp1, "w", refsfound) == NULL) {
476 474 putmsg("Cannot reopen temporary file");
477 475 return (NO);
478 476 }
479 477 return (YES);
480 478 }
481 479
482 480 /* count the references found */
483 481
484 482 void
485 483 countrefs(void)
486 484 {
487 485 char *subsystem; /* OGS subsystem name */
488 486 char *book; /* OGS book name */
489 487 char file[PATHLEN + 1]; /* file name */
490 488 char function[PATLEN + 1]; /* function name */
491 489 char linenum[NUMLEN + 1]; /* line number */
492 490 int i;
493 491
494 492 /*
495 493 * count the references found and find the length of the file,
496 494 * function, and line number display fields
497 495 */
498 496 subsystemlen = 9; /* strlen("Subsystem") */
499 497 booklen = 4; /* strlen("Book") */
500 498 filelen = 4; /* strlen("File") */
501 499 fcnlen = 8; /* strlen("Function") */
502 500 numlen = 0;
503 501 while ((i = fscanf(refsfound, "%250s%250s%6s %5000[^\n]", file,
504 502 function, linenum, yytext)) != EOF) {
505 503 if (i != 4 || !isgraph(*file) ||
506 504 !isgraph(*function) || !isdigit(*linenum)) {
507 505 putmsg("File does not have expected format");
508 506 totallines = 0;
509 507 return;
510 508 }
511 509 if ((i = strlen(pathcomponents(file,
512 510 dispcomponents))) > filelen) {
513 511 filelen = i;
514 512 }
515 513 if (ogs == YES) {
516 514 ogsnames(file, &subsystem, &book);
517 515 if ((i = strlen(subsystem)) > subsystemlen) {
518 516 subsystemlen = i;
519 517 }
520 518 if ((i = strlen(book)) > booklen) {
521 519 booklen = i;
522 520 }
523 521 }
524 522 if ((i = strlen(function)) > fcnlen) {
525 523 fcnlen = i;
526 524 }
527 525 if ((i = strlen(linenum)) > numlen) {
528 526 numlen = i;
529 527 }
530 528 ++totallines;
531 529 }
532 530 rewind(refsfound);
533 531
534 532 /* restrict the width of displayed columns */
535 533 i = (COLS - 5) / 3;
536 534 if (ogs == YES) {
537 535 i = (COLS - 7) / 5;
538 536 }
539 537 if (filelen > i && i > 4) {
540 538 filelen = i;
541 539 }
542 540 if (subsystemlen > i && i > 9) {
543 541 subsystemlen = i;
544 542 }
545 543 if (booklen > i && i > 4) {
546 544 booklen = i;
547 545 }
548 546 if (fcnlen > i && i > 8) {
549 547 fcnlen = i;
550 548 }
551 549 }
552 550
553 551 /* print error message on system call failure */
554 552
555 553 void
556 554 myperror(char *text)
557 555 {
558 556 char msg[MSGLEN + 1]; /* message */
559 557
↓ open down ↓ |
517 lines elided |
↑ open up ↑ |
560 558 (void) sprintf(msg, "%s: %s", text, strerror(errno));
561 559 putmsg(msg);
562 560 }
563 561
564 562 /* putmsg clears the message line and prints the message */
565 563
566 564 void
567 565 putmsg(char *msg)
568 566 {
569 567 if (incurses == NO) {
570 - *msg = tolower(*msg);
571 - (void) fprintf(stderr, "cscope: %s\n", msg);
568 + char *str = stralloc(msg);
569 + *str = tolower(*str);
570 + (void) fprintf(stderr, "cscope: %s\n", str);
571 + (void) free(str);
572 572 } else {
573 573 (void) move(MSGLINE, 0);
574 574 (void) clrtoeol();
575 575 (void) addstr(msg);
576 576 (void) refresh();
577 577 }
578 578 (void) strncpy(lastmsg, msg, sizeof (lastmsg) - 1);
579 579 }
580 580
581 581 /* clearmsg2 clears the second message line */
582 582
583 583 void
584 584 clearmsg2(void)
585 585 {
586 586 if (incurses == YES) {
587 587 (void) move(MSGLINE + 1, 0);
588 588 (void) clrtoeol();
589 589 }
590 590 }
591 591
592 592 /* putmsg2 clears the second message line and prints the message */
593 593
594 594 void
595 595 putmsg2(char *msg)
596 596 {
597 597 if (incurses == NO) {
598 598 putmsg(msg);
599 599 } else {
600 600 clearmsg2();
601 601 (void) addstr(msg);
602 602 (void) refresh();
603 603 }
604 604 }
605 605
606 606 /* position the references found file at the specified line */
607 607
608 608 void
609 609 seekline(int line)
610 610 {
611 611 int c;
612 612
613 613 /* verify that there is a references found file */
614 614 if (refsfound == NULL) {
615 615 return;
616 616 }
617 617 /* go to the beginning of the file */
618 618 rewind(refsfound);
619 619
620 620 /* find the requested line */
621 621 nextline = 1;
622 622 while (nextline < line && (c = getc(refsfound)) != EOF) {
623 623 if (c == '\n') {
624 624 nextline++;
625 625 }
626 626 }
627 627 }
628 628
629 629 /* get the OGS subsystem and book names */
630 630
631 631 void
632 632 ogsnames(char *file, char **subsystem, char **book)
633 633 {
634 634 static char buf[PATHLEN + 1];
635 635 char *s, *slash;
636 636
637 637 *subsystem = *book = "";
638 638 (void) strcpy(buf, file);
639 639 s = buf;
640 640 if (*s == '/') {
641 641 ++s;
642 642 }
643 643 while ((slash = strchr(s, '/')) != NULL) {
644 644 *slash = '\0';
645 645 if ((int)strlen(s) >= 3 && strncmp(slash - 3, ".ss", 3) == 0) {
646 646 *subsystem = s;
647 647 s = slash + 1;
648 648 if ((slash = strchr(s, '/')) != NULL) {
649 649 *book = s;
650 650 *slash = '\0';
651 651 }
652 652 break;
653 653 }
654 654 s = slash + 1;
655 655 }
656 656 }
657 657
658 658 /* get the requested path components */
659 659
660 660 char *
661 661 pathcomponents(char *path, int components)
662 662 {
663 663 int i;
664 664 char *s;
665 665
666 666 s = path + strlen(path) - 1;
667 667 for (i = 0; i < components; ++i) {
668 668 while (s > path && *--s != '/') {
669 669 ;
670 670 }
671 671 }
672 672 if (s > path && *s == '/') {
673 673 ++s;
674 674 }
675 675 return (s);
676 676 }
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX