17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bdstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bdstevel@tonic-gate * (the "License").  You may not use this file except in compliance
77c478bdstevel@tonic-gate * with the License.
87c478bdstevel@tonic-gate *
97c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bdstevel@tonic-gate * See the License for the specific language governing permissions
127c478bdstevel@tonic-gate * and limitations under the License.
137c478bdstevel@tonic-gate *
147c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bdstevel@tonic-gate *
207c478bdstevel@tonic-gate * CDDL HEADER END
217c478bdstevel@tonic-gate */
227c478bdstevel@tonic-gate/*	Copyright (c) 1988 AT&T	*/
237c478bdstevel@tonic-gate/*	  All Rights Reserved  	*/
247c478bdstevel@tonic-gate
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*
277c478bdstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
287c478bdstevel@tonic-gate * Use is subject to license terms.
2967a4bb8Gary Mills * Copyright 2015 Gary Mills
307c478bdstevel@tonic-gate */
317c478bdstevel@tonic-gate
327c478bdstevel@tonic-gate/*
337c478bdstevel@tonic-gate *	cscope - interactive C symbol cross-reference
347c478bdstevel@tonic-gate *
357c478bdstevel@tonic-gate *	display functions
367c478bdstevel@tonic-gate */
377c478bdstevel@tonic-gate
387c478bdstevel@tonic-gate#include "global.h"
397c478bdstevel@tonic-gate#include "version.h"	/* FILEVERSION and FIXVERSION */
407c478bdstevel@tonic-gate#include <curses.h>	/* COLS and LINES */
417c478bdstevel@tonic-gate#include <setjmp.h>	/* jmp_buf */
427c478bdstevel@tonic-gate#include <string.h>
437c478bdstevel@tonic-gate#include <errno.h>
447c478bdstevel@tonic-gate
457c478bdstevel@tonic-gate/* see if the function column should be displayed */
467c478bdstevel@tonic-gate#define	displayfcn()	(field <= ASSIGN)
477c478bdstevel@tonic-gate
487c478bdstevel@tonic-gate#define	MINCOLS	68	/* minimum columns for 3 digit Lines message numbers */
497c478bdstevel@tonic-gate
507c478bdstevel@tonic-gateint	*displine;		/* screen line of displayed reference */
517c478bdstevel@tonic-gateint	disprefs;		/* displayed references */
527c478bdstevel@tonic-gateint	field;			/* input field */
537c478bdstevel@tonic-gateunsigned fldcolumn;		/* input field column */
547c478bdstevel@tonic-gateint	mdisprefs;		/* maximum displayed references */
557c478bdstevel@tonic-gateint	selectlen;		/* selection number field length */
567c478bdstevel@tonic-gateint	nextline;		/* next line to be shown */
577c478bdstevel@tonic-gateint	topline = 1;		/* top line of page */
587c478bdstevel@tonic-gateint	bottomline;		/* bottom line of page */
597c478bdstevel@tonic-gateint	totallines;		/* total reference lines */
607c478bdstevel@tonic-gateFILE	*refsfound;		/* references found file */
617c478bdstevel@tonic-gateFILE	*nonglobalrefs;		/* non-global references file */
627c478bdstevel@tonic-gate
637c478bdstevel@tonic-gatestatic	int	fldline;		/* input field line */
647c478bdstevel@tonic-gatestatic	int	subsystemlen;		/* OGS subsystem name display */
657c478bdstevel@tonic-gate					/* field length */
667c478bdstevel@tonic-gatestatic	int	booklen;		/* OGS book name display field length */
677c478bdstevel@tonic-gatestatic	int	filelen;		/* file name display field length */
687c478bdstevel@tonic-gatestatic	int	fcnlen;			/* function name display field length */
697c478bdstevel@tonic-gatestatic	jmp_buf	env;			/* setjmp/longjmp buffer */
707c478bdstevel@tonic-gatestatic	int	lastdispline;		/* last displayed reference line */
717c478bdstevel@tonic-gatestatic	char	lastmsg[MSGLEN + 1];	/* last message displayed */
727c478bdstevel@tonic-gatestatic	int	numlen;			/* line number display field length */
737c478bdstevel@tonic-gatestatic	char	depthstring[] = "Depth: ";
747c478bdstevel@tonic-gatestatic	char	helpstring[] = "Press the ? key for help";
757c478bdstevel@tonic-gate
767c478bdstevel@tonic-gate
777c478bdstevel@tonic-gatetypedef char *(*FP)();	/* pointer to function returning a character pointer */
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gatestatic	struct	{
807c478bdstevel@tonic-gate	char	*text1;
817c478bdstevel@tonic-gate	char	*text2;
827c478bdstevel@tonic-gate	FP	findfcn;
837c478bdstevel@tonic-gate	enum {
847c478bdstevel@tonic-gate		EGREP,
857c478bdstevel@tonic-gate		REGCMP
867c478bdstevel@tonic-gate	} patterntype;
877c478bdstevel@tonic-gate} fields[FIELDS + 1] = {
887c478bdstevel@tonic-gate	/* last search is not part of the cscope display */
897c478bdstevel@tonic-gate	{ "Find this", "C symbol",
907c478bdstevel@tonic-gate	    (FP) findsymbol, REGCMP},
917c478bdstevel@tonic-gate	{ "Find this", "definition",
927c478bdstevel@tonic-gate	    (FP) finddef, REGCMP},
937c478bdstevel@tonic-gate	{ "Find", "functions called by this function",
947c478bdstevel@tonic-gate	    (FP) findcalledby, REGCMP},
957c478bdstevel@tonic-gate	{ "Find", "functions calling this function",
967c478bdstevel@tonic-gate	    (FP) findcalling, REGCMP},
977c478bdstevel@tonic-gate	{ "Find", "assignments to",
987c478bdstevel@tonic-gate	    (FP) findassignments, REGCMP},
997c478bdstevel@tonic-gate	{ "Change this", "grep pattern",
1007c478bdstevel@tonic-gate	    findgreppat, EGREP},
1017c478bdstevel@tonic-gate	{ "Find this", "egrep pattern",
1027c478bdstevel@tonic-gate	    findegreppat, EGREP},
1037c478bdstevel@tonic-gate	{ "Find this", "file",
1047c478bdstevel@tonic-gate	    (FP) findfile, REGCMP},
1057c478bdstevel@tonic-gate	{ "Find", "files #including this file",
1067c478bdstevel@tonic-gate	    (FP) findinclude, REGCMP},
1077c478bdstevel@tonic-gate	{ "Find all", "function/class definitions",
1087c478bdstevel@tonic-gate	    (FP) findallfcns, REGCMP},
1097c478bdstevel@tonic-gate};
1107c478bdstevel@tonic-gate
1117c478bdstevel@tonic-gate/* initialize display parameters */
1127c478bdstevel@tonic-gate
1137c478bdstevel@tonic-gatevoid
1147c478bdstevel@tonic-gatedispinit(void)
1157c478bdstevel@tonic-gate{
1167c478bdstevel@tonic-gate	/* calculate the maximum displayed reference lines */
1177c478bdstevel@tonic-gate	lastdispline = FLDLINE - 2;
1187c478bdstevel@tonic-gate	mdisprefs = lastdispline - REFLINE + 1;
1197c478bdstevel@tonic-gate	if (mdisprefs <= 0) {
1207c478bdstevel@tonic-gate		(void) printw("cscope: window must be at least %d lines high",
1217c478bdstevel@tonic-gate		    FIELDS + 6);
1227c478bdstevel@tonic-gate		myexit(1);
1237c478bdstevel@tonic-gate	}
1247c478bdstevel@tonic-gate	if (COLS < MINCOLS) {
1257c478bdstevel@tonic-gate		(void) printw("cscope: window must be at least %d columns wide",
1267c478bdstevel@tonic-gate		    MINCOLS);
1277c478bdstevel@tonic-gate		myexit(1);
1287c478bdstevel@tonic-gate	}
1297c478bdstevel@tonic-gate	if (!mouse) {
1307c478bdstevel@tonic-gate		if (returnrequired == NO && mdisprefs > 9) {
1317c478bdstevel@tonic-gate			mdisprefs = 9;	/* single digit selection number */
1327c478bdstevel@tonic-gate		}
1337c478bdstevel@tonic-gate		/* calculate the maximum selection number width */
1347c478bdstevel@tonic-gate		(void) sprintf(newpat, "%d", mdisprefs);
1357c478bdstevel@tonic-gate		selectlen = strlen(newpat);
1367c478bdstevel@tonic-gate	}
1377c478bdstevel@tonic-gate	/* allocate the displayed line array */
1387c478bdstevel@tonic-gate	displine = (int *)mymalloc(mdisprefs * sizeof (int));
1397c478bdstevel@tonic-gate}
1407c478bdstevel@tonic-gate
1417c478bdstevel@tonic-gate/* display a page of the references */
1427c478bdstevel@tonic-gate
1437c478bdstevel@tonic-gatevoid
1447c478bdstevel@tonic-gatedisplay(void)
1457c478bdstevel@tonic-gate{
1467c478bdstevel@tonic-gate	char	*subsystem;		/* OGS subsystem name */
1477c478bdstevel@tonic-gate	char	*book;			/* OGS book name */
1487c478bdstevel@tonic-gate	char	file[PATHLEN + 1];	/* file name */
1497c478bdstevel@tonic-gate	char	function[PATLEN + 1];	/* function name */
1507c478bdstevel@tonic-gate	char	linenum[NUMLEN + 1];	/* line number */
1517c478bdstevel@tonic-gate	int	screenline;		/* screen line number */
1527c478bdstevel@tonic-gate	int	width;			/* source line display width */
1537c478bdstevel@tonic-gate	int	i;
1547c478bdstevel@tonic-gate	char	*s;
1557c478bdstevel@tonic-gate
1567c478bdstevel@tonic-gate	(void) erase();
1577c478bdstevel@tonic-gate
1587c478bdstevel@tonic-gate	/* if there are no references */
1597c478bdstevel@tonic-gate	if (totallines == 0) {
1607c478bdstevel@tonic-gate		if (*lastmsg != '\0') {
1617c478bdstevel@tonic-gate			(void) addstr(lastmsg);	/* redisplay any message */
1627c478bdstevel@tonic-gate		} else {
1637c478bdstevel@tonic-gate			(void) printw("Cscope version %d%s", FILEVERSION,
1647c478bdstevel@tonic-gate			    FIXVERSION);
1657c478bdstevel@tonic-gate			(void) move(0, COLS - (int)sizeof (helpstring));
1667c478bdstevel@tonic-gate			(void) addstr(helpstring);
1677c478bdstevel@tonic-gate		}
1687c478bdstevel@tonic-gate	} else {	/* display the pattern */
1697c478bdstevel@tonic-gate		if (changing == YES) {
1707c478bdstevel@tonic-gate			(void) printw("Change \"%s\" to \"%s\"",
1717c478bdstevel@tonic-gate			    pattern, newpat);
1727c478bdstevel@tonic-gate		} else {
1737c478bdstevel@tonic-gate			(void) printw("%c%s: %s",
1747c478bdstevel@tonic-gate			    toupper(fields[field].text2[0]),
1757c478bdstevel@tonic-gate			    fields[field].text2 + 1, pattern);
1767c478bdstevel@tonic-gate		}
1777c478bdstevel@tonic-gate		/* display the cscope invocation nesting depth */
1787c478bdstevel@tonic-gate		if (cscopedepth > 1) {
1797c478bdstevel@tonic-gate			(void) move(0, COLS - (int)sizeof (depthstring) - 2);
1807c478bdstevel@tonic-gate			(void) addstr(depthstring);
1817c478bdstevel@tonic-gate			(void) printw("%d", cscopedepth);
1827c478bdstevel@tonic-gate		}
1837c478bdstevel@tonic-gate		/* display the column headings */
1847c478bdstevel@tonic-gate		(void) move(2, selectlen + 1);
1857c478bdstevel@tonic-gate		if (ogs == YES && field != FILENAME) {
1867c478bdstevel@tonic-gate			(void) printw("%-*s ", subsystemlen, "Subsystem");
1877c478bdstevel@tonic-gate			(void) printw("%-*s ", booklen, "Book");
1887c478bdstevel@tonic-gate		}
1897c478bdstevel@tonic-gate		if (dispcomponents > 0) {
1907c478bdstevel@tonic-gate			(void) printw("%-*s ", filelen, "File");
1917c478bdstevel@tonic-gate		}
1927c478bdstevel@tonic-gate		if (displayfcn()) {
1937c478bdstevel@tonic-gate			(void) printw("%-*s ", fcnlen, "Function");
1947c478bdstevel@tonic-gate		}
1957c478bdstevel@tonic-gate		if (field != FILENAME) {
1967c478bdstevel@tonic-gate			(void) addstr("Line");
1977c478bdstevel@tonic-gate		}
1987c478bdstevel@tonic-gate		(void) addch('\n');
1997c478bdstevel@tonic-gate
2007c478bdstevel@tonic-gate		/* if at end of file go back to beginning */
2017c478bdstevel@tonic-gate		if (nextline > totallines) {
2027c478bdstevel@tonic-gate			seekline(1);
2037c478bdstevel@tonic-gate		}
2047c478bdstevel@tonic-gate		/* calculate the source text column */
2057c478bdstevel@tonic-gate		width = COLS - selectlen - numlen - 2;
2067c478bdstevel@tonic-gate		if (ogs == YES) {
2077c478bdstevel@tonic-gate			width -= subsystemlen + booklen + 2;
2087c478bdstevel@tonic-gate		}
2097c478bdstevel@tonic-gate		if (dispcomponents > 0) {
2107c478bdstevel@tonic-gate			width -= filelen + 1;
2117c478bdstevel@tonic-gate		}
2127c478bdstevel@tonic-gate		if (displayfcn()) {
2137c478bdstevel@tonic-gate			width -= fcnlen + 1;
2147c478bdstevel@tonic-gate		}
2157c478bdstevel@tonic-gate		/*
2167c478bdstevel@tonic-gate		 * until the max references have been displayed or
2177c478bdstevel@tonic-gate		 * there is no more room
2187c478bdstevel@tonic-gate		 */
2197c478bdstevel@tonic-gate		topline = nextline;
2207c478bdstevel@tonic-gate		for (disprefs = 0, screenline = REFLINE;
2217c478bdstevel@tonic-gate		    disprefs < mdisprefs && screenline <= lastdispline;
2227c478bdstevel@tonic-gate		    ++disprefs, ++screenline) {
2237c478bdstevel@tonic-gate			/* read the reference line */
2247c478bdstevel@tonic-gate			if (fscanf(refsfound, "%s%s%s %[^\n]", file, function,
2257c478bdstevel@tonic-gate			    linenum, yytext) < 4) {
2267c478bdstevel@tonic-gate				break;
2277c478bdstevel@tonic-gate			}
2287c478bdstevel@tonic-gate			++nextline;
2297c478bdstevel@tonic-gate			displine[disprefs] = screenline;
2307c478bdstevel@tonic-gate
2317c478bdstevel@tonic-gate			/* if no mouse, display the selection number */
2327c478bdstevel@tonic-gate			if (!mouse) {
2337c478bdstevel@tonic-gate				(void) printw("%*d", selectlen, disprefs + 1);
2347c478bdstevel@tonic-gate			}
2357c478bdstevel@tonic-gate			/* display any change mark */
2367c478bdstevel@tonic-gate			if (changing == YES &&
2377c478bdstevel@tonic-gate			    change[topline + disprefs - 1] == YES) {
2387c478bdstevel@tonic-gate				(void) addch('>');
2397c478bdstevel@tonic-gate			} else {
2407c478bdstevel@tonic-gate				(void) addch(' ');
2417c478bdstevel@tonic-gate			}
2427c478bdstevel@tonic-gate			/* display the file name */
2437c478bdstevel@tonic-gate			if (field == FILENAME) {
2447c478bdstevel@tonic-gate				(void) printw("%-.*s\n", COLS - 3, file);
2457c478bdstevel@tonic-gate				continue;
2467c478bdstevel@tonic-gate			}
2477c478bdstevel@tonic-gate			/* if OGS, display the subsystem and book names */
2487c478bdstevel@tonic-gate			if (ogs == YES) {
2497c478bdstevel@tonic-gate				ogsnames(file, &subsystem, &book);
2507c478bdstevel@tonic-gate				(void) printw("%-*.*s ", subsystemlen,
2517c478bdstevel@tonic-gate				    subsystemlen, subsystem);
2527c478bdstevel@tonic-gate				(void) printw("%-*.*s ", booklen, booklen,
2537c478bdstevel@tonic-gate				    book);
2547c478bdstevel@tonic-gate			}
2557c478bdstevel@tonic-gate			/* display the requested path components */
2567c478bdstevel@tonic-gate			if (dispcomponents > 0) {
2577c478bdstevel@tonic-gate				(void) printw("%-*.*s ", filelen, filelen,
2587c478bdstevel@tonic-gate				    pathcomponents(file, dispcomponents));
2597c478bdstevel@tonic-gate			}
2607c478bdstevel@tonic-gate			/* display the function name */
2617c478bdstevel@tonic-gate			if (displayfcn()) {
2627c478bdstevel@tonic-gate				(void) printw("%-*.*s ", fcnlen, fcnlen,
2637c478bdstevel@tonic-gate				    function);
2647c478bdstevel@tonic-gate			}
2657c478bdstevel@tonic-gate			/* display the line number */
2667c478bdstevel@tonic-gate			(void) printw("%*s ", numlen, linenum);
2677c478bdstevel@tonic-gate
2687c478bdstevel@tonic-gate			/* there may be tabs in egrep output */
2697c478bdstevel@tonic-gate			while ((s = strchr(yytext, '\t')) != NULL) {
2707c478bdstevel@tonic-gate				*s = ' ';
2717c478bdstevel@tonic-gate			}
2727c478bdstevel@tonic-gate			/* display the source line */
2737c478bdstevel@tonic-gate			s = yytext;
2747c478bdstevel@tonic-gate			for (;;) {
2757c478bdstevel@tonic-gate				/* see if the source line will fit */
2767c478bdstevel@tonic-gate				if ((i = strlen(s)) > width) {
2777c478bdstevel@tonic-gate					/* find the nearest blank */
2787c478bdstevel@tonic-gate					for (i = width; s[i] != ' ' && i > 0;
2797c478bdstevel@tonic-gate					    --i) {
2807c478bdstevel@tonic-gate					}
2817c478bdstevel@tonic-gate					if (i == 0) {
2827c478bdstevel@tonic-gate						i = width;	/* no blank */
2837c478bdstevel@tonic-gate					}
2847c478bdstevel@tonic-gate				}
2857c478bdstevel@tonic-gate				/* print up to this point */
2867c478bdstevel@tonic-gate				(void) printw("%.*s", i, s);
2877c478bdstevel@tonic-gate				s += i;
2887c478bdstevel@tonic-gate
2897c478bdstevel@tonic-gate				/* if line didn't wrap around */
2907c478bdstevel@tonic-gate				if (i < width) {
2917c478bdstevel@tonic-gate					/* go to next line */
2927c478bdstevel@tonic-gate					(void) addch('\n');
2937c478bdstevel@tonic-gate				}
2947c478bdstevel@tonic-gate				/* skip blanks */
2957c478bdstevel@tonic-gate				while (*s == ' ') {
2967c478bdstevel@tonic-gate					++s;
2977c478bdstevel@tonic-gate				}
2987c478bdstevel@tonic-gate				/* see if there is more text */
2997c478bdstevel@tonic-gate				if (*s == '\0') {
3007c478bdstevel@tonic-gate					break;
3017c478bdstevel@tonic-gate				}
3027c478bdstevel@tonic-gate				/* if the source line is too long */
3037c478bdstevel@tonic-gate				if (++screenline > lastdispline) {
3047c478bdstevel@tonic-gate					/*
3057c478bdstevel@tonic-gate					 * if this is the first displayed line,
3067c478bdstevel@tonic-gate					 * display what will fit on the screen
3077c478bdstevel@tonic-gate					 */
3087c478bdstevel@tonic-gate					if (topline == nextline - 1) {
3097c478bdstevel@tonic-gate						goto endrefs;
3107c478bdstevel@tonic-gate					}
3117c478bdstevel@tonic-gate					/* erase the reference */
3127c478bdstevel@tonic-gate					while (--screenline >=
3137c478bdstevel@tonic-gate					    displine[disprefs]) {
3147c478bdstevel@tonic-gate						(void) move(screenline, 0);
3157c478bdstevel@tonic-gate						(void) clrtoeol();
3167c478bdstevel@tonic-gate					}
3177c478bdstevel@tonic-gate					++screenline;
3187c478bdstevel@tonic-gate
3197c478bdstevel@tonic-gate					/*
3207c478bdstevel@tonic-gate					 * go back to the beginning of this
3217c478bdstevel@tonic-gate					 * reference
3227c478bdstevel@tonic-gate					 */
3237c478bdstevel@tonic-gate					--nextline;
3247c478bdstevel@tonic-gate					seekline(nextline);
3257c478bdstevel@tonic-gate					goto endrefs;
3267c478bdstevel@tonic-gate				}
3277c478bdstevel@tonic-gate				/* indent the continued source line */
3287c478bdstevel@tonic-gate				(void) move(screenline, COLS - width);
3297c478bdstevel@tonic-gate			}
3307c478bdstevel@tonic-gate
3317c478bdstevel@tonic-gate		}
3327c478bdstevel@tonic-gate	endrefs:
3337c478bdstevel@tonic-gate		/* check for more references */
3347c478bdstevel@tonic-gate		bottomline = nextline;
3357c478bdstevel@tonic-gate		if (bottomline - topline < totallines) {
3367c478bdstevel@tonic-gate			(void) move(FLDLINE - 1, 0);
3377c478bdstevel@tonic-gate			(void) standout();
3387c478bdstevel@tonic-gate			(void) printw("%*s", selectlen + 1, "");
3397c478bdstevel@tonic-gate			if (bottomline - 1 == topline) {
3407c478bdstevel@tonic-gate				(void) printw("Line %d", topline);
3417c478bdstevel@tonic-gate			} else {
3427c478bdstevel@tonic-gate				(void) printw("Lines %d-%d", topline,
3437c478bdstevel@tonic-gate				    bottomline - 1);
3447c478bdstevel@tonic-gate			}
3457c478bdstevel@tonic-gate			(void) printw(" of %d, press the space bar to "
3467c478bdstevel@tonic-gate			    "display next lines", totallines);
3477c478bdstevel@tonic-gate			(void) standend();
3487c478bdstevel@tonic-gate		}
3497c478bdstevel@tonic-gate	}
3507c478bdstevel@tonic-gate	/* display the input fields */
3517c478bdstevel@tonic-gate	(void) move(FLDLINE, 0);
3527c478bdstevel@tonic-gate	for (i = 0; i < FIELDS; ++i) {
3537c478bdstevel@tonic-gate		(void) printw("%s %s:\n", fields[i].text1, fields[i].text2);
3547c478bdstevel@tonic-gate	}
3557c478bdstevel@tonic-gate	drawscrollbar(topline, nextline, totallines);
3567c478bdstevel@tonic-gate}
3577c478bdstevel@tonic-gate
3587c478bdstevel@tonic-gate/* set the cursor position for the field */
3597c478bdstevel@tonic-gatevoid
3607c478bdstevel@tonic-gatesetfield(void)
3617c478bdstevel@tonic-gate{
3627c478bdstevel@tonic-gate	fldline = FLDLINE + field;
3637c478bdstevel@tonic-gate	fldcolumn = strlen(fields[field].text1) +
3647c478bdstevel@tonic-gate	    strlen(fields[field].text2) + 3;
3657c478bdstevel@tonic-gate}
3667c478bdstevel@tonic-gate
3677c478bdstevel@tonic-gate/* move to the current input field */
3687c478bdstevel@tonic-gate
3697c478bdstevel@tonic-gatevoid
3707c478bdstevel@tonic-gateatfield(void)
3717c478bdstevel@tonic-gate{
3727c478bdstevel@tonic-gate	(void) move(fldline, (int)fldcolumn);
3737c478bdstevel@tonic-gate}
3747c478bdstevel@tonic-gate
3757c478bdstevel@tonic-gate/* search for the symbol or text pattern */
3767c478bdstevel@tonic-gate
3777c478bdstevel@tonic-gate/*ARGSUSED*/
3787c478bdstevel@tonic-gateSIGTYPE
3797c478bdstevel@tonic-gatejumpback(int sig)
3807c478bdstevel@tonic-gate{
3817c478bdstevel@tonic-gate	longjmp(env, 1);
3827c478bdstevel@tonic-gate}
3837c478bdstevel@tonic-gate
3847c478bdstevel@tonic-gateBOOL
3857c478bdstevel@tonic-gatesearch(void)
3867c478bdstevel@tonic-gate{
3874c6c4a8Toomas Soome	char	*volatile egreperror = NULL;	/* egrep error message */
3884c6c4a8Toomas Soome	FINDINIT volatile rc = NOERROR;		/* findinit return code */
38967a4bb8Gary Mills	SIGTYPE	(*volatile savesig)() = SIG_DFL; /* old value of signal */
3907c478bdstevel@tonic-gate	FP	f;			/* searching function */
3917c478bdstevel@tonic-gate	char	*s;
3927c478bdstevel@tonic-gate	int	c;
3937c478bdstevel@tonic-gate
3947c478bdstevel@tonic-gate	/* note: the pattern may have been a cscope argument */
3957c478bdstevel@tonic-gate	if (caseless == YES) {
3967c478bdstevel@tonic-gate		for (s = pattern; *s != '\0'; ++s) {
3977c478bdstevel@tonic-gate			*s = tolower(*s);
3987c478bdstevel@tonic-gate		}
3997c478bdstevel@tonic-gate	}
4007c478bdstevel@tonic-gate	/* open the references found file for writing */
4017c478bdstevel@tonic-gate	if (writerefsfound() == NO) {
4027c478bdstevel@tonic-gate		return (NO);
4037c478bdstevel@tonic-gate	}
4047c478bdstevel@tonic-gate	/* find the pattern - stop on an interrupt */
4057c478bdstevel@tonic-gate	if (linemode == NO) {
4067c478bdstevel@tonic-gate		putmsg("Searching");
4077c478bdstevel@tonic-gate	}
4087c478bdstevel@tonic-gate	initprogress();
4097c478bdstevel@tonic-gate	if (setjmp(env) == 0) {
4107c478bdstevel@tonic-gate		savesig = signal(SIGINT, jumpback);
4117c478bdstevel@tonic-gate		f = fields[field].findfcn;
4127c478bdstevel@tonic-gate		if (fields[field].patterntype == EGREP) {
4137c478bdstevel@tonic-gate			egreperror = (*f)(pattern);
4147c478bdstevel@tonic-gate		} else {
4157c478bdstevel@tonic-gate			if ((nonglobalrefs = fopen(temp2, "w")) == NULL) {
4167c478bdstevel@tonic-gate				cannotopen(temp2);
4177c478bdstevel@tonic-gate				return (NO);
4187c478bdstevel@tonic-gate			}
4197c478bdstevel@tonic-gate			if ((rc = findinit()) == NOERROR) {
4207c478bdstevel@tonic-gate				(void) dbseek(0L); /* goto the first block */
4217c478bdstevel@tonic-gate				(*f)();
4227c478bdstevel@tonic-gate				findcleanup();
4237c478bdstevel@tonic-gate
4247c478bdstevel@tonic-gate				/* append the non-global references */
4257c478bdstevel@tonic-gate				(void) freopen(temp2, "r", nonglobalrefs);
4267c478bdstevel@tonic-gate				while ((c = getc(nonglobalrefs)) != EOF) {
4277c478bdstevel@tonic-gate					(void) putc(c, refsfound);
4287c478bdstevel@tonic-gate				}
4297c478bdstevel@tonic-gate			}
4307c478bdstevel@tonic-gate			(void) fclose(nonglobalrefs);
4317c478bdstevel@tonic-gate		}
4327c478bdstevel@tonic-gate	}
4337c478bdstevel@tonic-gate	(void) signal(SIGINT, savesig);
4347c478bdstevel@tonic-gate	/* reopen the references found file for reading */
4357c478bdstevel@tonic-gate	(void) freopen(temp1, "r", refsfound);
4367c478bdstevel@tonic-gate	nextline = 1;
4377c478bdstevel@tonic-gate	totallines = 0;
4387c478bdstevel@tonic-gate
4397c478bdstevel@tonic-gate	/* see if it is empty */
4407c478bdstevel@tonic-gate	if ((c = getc(refsfound)) == EOF) {
4417c478bdstevel@tonic-gate		if (egreperror != NULL) {
4427c478bdstevel@tonic-gate			(void) sprintf(lastmsg, "Egrep %s in this pattern: %s",
4437c478bdstevel@tonic-gate			    egreperror, pattern);
4447c478bdstevel@tonic-gate		} else if (rc == NOTSYMBOL) {
4457c478bdstevel@tonic-gate			(void) sprintf(lastmsg, "This is not a C symbol: %s",
4467c478bdstevel@tonic-gate			    pattern);
4477c478bdstevel@tonic-gate		} else if (rc == REGCMPERROR) {
4487c478bdstevel@tonic-gate			(void) sprintf(lastmsg,
4497c478bdstevel@tonic-gate			    "Error in this regcmp(3X) regular expression: %s",
4507c478bdstevel@tonic-gate			    pattern);
4517c478bdstevel@tonic-gate		} else {
4527c478bdstevel@tonic-gate			(void) sprintf(lastmsg, "Could not find the %s: %s",
4537c478bdstevel@tonic-gate			    fields[field].text2, pattern);
4547c478bdstevel@tonic-gate		}
4557c478bdstevel@tonic-gate		return (NO);
4567c478bdstevel@tonic-gate	}
4577c478bdstevel@tonic-gate	/* put back the character read */
4587c478bdstevel@tonic-gate	(void) ungetc(c, refsfound);
4597c478bdstevel@tonic-gate
4607c478bdstevel@tonic-gate	countrefs();
4617c478bdstevel@tonic-gate	return (YES);
4627c478bdstevel@tonic-gate}
4637c478bdstevel@tonic-gate
4647c478bdstevel@tonic-gate/* open the references found file for writing */
4657c478bdstevel@tonic-gate
4667c478bdstevel@tonic-gateBOOL
4677c478bdstevel@tonic-gatewriterefsfound(void)
4687c478bdstevel@tonic-gate{
4697c478bdstevel@tonic-gate	if (refsfound == NULL) {
4707c478bdstevel@tonic-gate		if ((refsfound = fopen(temp1, "w")) == NULL) {
4717c478bdstevel@tonic-gate			cannotopen(temp1);
4727c478bdstevel@tonic-gate			return (NO);
4737c478bdstevel@tonic-gate		}
4747c478bdstevel@tonic-gate	} else if (freopen(temp1, "w", refsfound) == NULL) {
4757c478bdstevel@tonic-gate		putmsg("Cannot reopen temporary file");
4767c478bdstevel@tonic-gate		return (NO);
4777c478bdstevel@tonic-gate	}
4787c478bdstevel@tonic-gate	return (YES);
4797c478bdstevel@tonic-gate}
4807c478bdstevel@tonic-gate
4817c478bdstevel@tonic-gate/* count the references found */
4827c478bdstevel@tonic-gate
4837c478bdstevel@tonic-gatevoid
4847c478bdstevel@tonic-gatecountrefs(void)
4857c478bdstevel@tonic-gate{
4867c478bdstevel@tonic-gate	char	*subsystem;		/* OGS subsystem name */
4877c478bdstevel@tonic-gate	char 	*book;			/* OGS book name */
4887c478bdstevel@tonic-gate	char	file[PATHLEN + 1];	/* file name */
4897c478bdstevel@tonic-gate	char	function[PATLEN + 1];	/* function name */
4907c478bdstevel@tonic-gate	char	linenum[NUMLEN + 1];	/* line number */
4917c478bdstevel@tonic-gate	int	i;
4927c478bdstevel@tonic-gate
4937c478bdstevel@tonic-gate	/*
4947c478bdstevel@tonic-gate	 * count the references found and find the length of the file,
4957c478bdstevel@tonic-gate	 * function, and line number display fields
4967c478bdstevel@tonic-gate	 */
4977c478bdstevel@tonic-gate	subsystemlen = 9;	/* strlen("Subsystem") */
4987c478bdstevel@tonic-gate	booklen = 4;		/* strlen("Book") */
4997c478bdstevel@tonic-gate	filelen = 4;		/* strlen("File") */
5007c478bdstevel@tonic-gate	fcnlen = 8;		/* strlen("Function") */
5017c478bdstevel@tonic-gate	numlen = 0;
5027c478bdstevel@tonic-gate	while ((i = fscanf(refsfound, "%250s%250s%6s %5000[^\n]", file,
5037c478bdstevel@tonic-gate	    function, linenum, yytext)) != EOF) {
5047c478bdstevel@tonic-gate		if (i != 4 || !isgraph(*file) ||
5057c478bdstevel@tonic-gate		    !isgraph(*function) || !isdigit(*linenum)) {
5067c478bdstevel@tonic-gate			putmsg("File does not have expected format");
5077c478bdstevel@tonic-gate			totallines = 0;
5087c478bdstevel@tonic-gate			return;
5097c478bdstevel@tonic-gate		}
5107c478bdstevel@tonic-gate		if ((i = strlen(pathcomponents(file,
5117c478bdstevel@tonic-gate		    dispcomponents))) > filelen) {
5127c478bdstevel@tonic-gate			filelen = i;
5137c478bdstevel@tonic-gate		}
5147c478bdstevel@tonic-gate		if (ogs == YES) {
5157c478bdstevel@tonic-gate			ogsnames(file, &subsystem, &book);
5167c478bdstevel@tonic-gate			if ((i = strlen(subsystem)) > subsystemlen) {
5177c478bdstevel@tonic-gate				subsystemlen = i;
5187c478bdstevel@tonic-gate			}
5197c478bdstevel@tonic-gate			if ((i = strlen(book)) > booklen) {
5207c478bdstevel@tonic-gate				booklen = i;
5217c478bdstevel@tonic-gate			}
5227c478bdstevel@tonic-gate		}
5237c478bdstevel@tonic-gate		if ((i = strlen(function)) > fcnlen) {
5247c478bdstevel@tonic-gate			fcnlen = i;
5257c478bdstevel@tonic-gate		}
5267c478bdstevel@tonic-gate		if ((i = strlen(linenum)) > numlen) {
5277c478bdstevel@tonic-gate			numlen = i;
5287c478bdstevel@tonic-gate		}
5297c478bdstevel@tonic-gate		++totallines;
5307c478bdstevel@tonic-gate	}
5317c478bdstevel@tonic-gate	rewind(refsfound);
5327c478bdstevel@tonic-gate
5337c478bdstevel@tonic-gate	/* restrict the width of displayed columns */
5347c478bdstevel@tonic-gate	i = (COLS - 5) / 3;
5357c478bdstevel@tonic-gate	if (ogs == YES) {
5367c478bdstevel@tonic-gate		i = (COLS - 7) / 5;
5377c478bdstevel@tonic-gate	}
5387c478bdstevel@tonic-gate	if (filelen > i && i > 4) {
5397c478bdstevel@tonic-gate		filelen = i;
5407c478bdstevel@tonic-gate	}
5417c478bdstevel@tonic-gate	if (subsystemlen > i && i > 9) {
5427c478bdstevel@tonic-gate		subsystemlen = i;
5437c478bdstevel@tonic-gate	}
5447c478bdstevel@tonic-gate	if (booklen > i && i > 4) {
5457c478bdstevel@tonic-gate		booklen = i;
5467c478bdstevel@tonic-gate	}
5477c478bdstevel@tonic-gate	if (fcnlen > i && i > 8) {
5487c478bdstevel@tonic-gate		fcnlen = i;
5497c478bdstevel@tonic-gate	}
5507c478bdstevel@tonic-gate}
5517c478bdstevel@tonic-gate
5527c478bdstevel@tonic-gate/* print error message on system call failure */
5537c478bdstevel@tonic-gate
5547c478bdstevel@tonic-gatevoid
5557c478bdstevel@tonic-gatemyperror(char *text)
5567c478bdstevel@tonic-gate{
5577c478bdstevel@tonic-gate	char	msg[MSGLEN + 1];	/* message */
5587c478bdstevel@tonic-gate
5597c478bdstevel@tonic-gate	(void) sprintf(msg, "%s: %s", text, strerror(errno));
5607c478bdstevel@tonic-gate	putmsg(msg);
5617c478bdstevel@tonic-gate}
5627c478bdstevel@tonic-gate
5637c478bdstevel@tonic-gate/* putmsg clears the message line and prints the message */
5647c478bdstevel@tonic-gate
5657c478bdstevel@tonic-gatevoid
5667c478bdstevel@tonic-gateputmsg(char *msg)
5677c478bdstevel@tonic-gate{
5687c478bdstevel@tonic-gate	if (incurses == NO) {
5697c478bdstevel@tonic-gate		*msg = tolower(*msg);
5707c478bdstevel@tonic-gate		(void) fprintf(stderr, "cscope: %s\n", msg);
5717c478bdstevel@tonic-gate	} else {
5727c478bdstevel@tonic-gate		(void) move(MSGLINE, 0);
5737c478bdstevel@tonic-gate		(void) clrtoeol();
5747c478bdstevel@tonic-gate		(void) addstr(msg);
5757c478bdstevel@tonic-gate		(void) refresh();
5767c478bdstevel@tonic-gate	}
5777c478bdstevel@tonic-gate	(void) strncpy(lastmsg, msg, sizeof (lastmsg) - 1);
5787c478bdstevel@tonic-gate}
5797c478bdstevel@tonic-gate
5807c478bdstevel@tonic-gate/* clearmsg2 clears the second message line */
5817c478bdstevel@tonic-gate
5827c478bdstevel@tonic-gatevoid
5837c478bdstevel@tonic-gateclearmsg2(void)
5847c478bdstevel@tonic-gate{
5857c478bdstevel@tonic-gate	if (incurses == YES) {
5867c478bdstevel@tonic-gate		(void) move(MSGLINE + 1, 0);
5877c478bdstevel@tonic-gate		(void) clrtoeol();
5887c478bdstevel@tonic-gate	}
5897c478bdstevel@tonic-gate}
5907c478bdstevel@tonic-gate
5917c478bdstevel@tonic-gate/* putmsg2 clears the second message line and prints the message */
5927c478bdstevel@tonic-gate
5937c478bdstevel@tonic-gatevoid
5947c478bdstevel@tonic-gateputmsg2(char *msg)
5957c478bdstevel@tonic-gate{
5967c478bdstevel@tonic-gate	if (incurses == NO) {
5977c478bdstevel@tonic-gate		putmsg(msg);
5987c478bdstevel@tonic-gate	} else {
5997c478bdstevel@tonic-gate		clearmsg2();
6007c478bdstevel@tonic-gate		(void) addstr(msg);
6017c478bdstevel@tonic-gate		(void) refresh();
6027c478bdstevel@tonic-gate	}
6037c478bdstevel@tonic-gate}
6047c478bdstevel@tonic-gate
6057c478bdstevel@tonic-gate/* position the references found file at the specified line */
6067c478bdstevel@tonic-gate
6077c478bdstevel@tonic-gatevoid
6087c478bdstevel@tonic-gateseekline(int line)
6097c478bdstevel@tonic-gate{
6107c478bdstevel@tonic-gate	int	c;
6117c478bdstevel@tonic-gate
6127c478bdstevel@tonic-gate	/* verify that there is a references found file */
6137c478bdstevel@tonic-gate	if (refsfound == NULL) {
6147c478bdstevel@tonic-gate		return;
6157c478bdstevel@tonic-gate	}
6167c478bdstevel@tonic-gate	/* go to the beginning of the file */
6177c478bdstevel@tonic-gate	rewind(refsfound);
6187c478bdstevel@tonic-gate
6197c478bdstevel@tonic-gate	/* find the requested line */
6207c478bdstevel@tonic-gate	nextline = 1;
6217c478bdstevel@tonic-gate	while (nextline < line && (c = getc(refsfound)) != EOF) {
6227c478bdstevel@tonic-gate		if (c == '\n') {
6237c478bdstevel@tonic-gate			nextline++;
6247c478bdstevel@tonic-gate		}
6257c478bdstevel@tonic-gate	}
6267c478bdstevel@tonic-gate}
6277c478bdstevel@tonic-gate
6287c478bdstevel@tonic-gate/* get the OGS subsystem and book names */
6297c478bdstevel@tonic-gate
6307c478bdstevel@tonic-gatevoid
6317c478bdstevel@tonic-gateogsnames(char *file, char **subsystem, char **book)
6327c478bdstevel@tonic-gate{
6337c478bdstevel@tonic-gate	static	char	buf[PATHLEN + 1];
6347c478bdstevel@tonic-gate	char	*s, *slash;
6357c478bdstevel@tonic-gate
6367c478bdstevel@tonic-gate	*subsystem = *book = "";
6377c478bdstevel@tonic-gate	(void) strcpy(buf, file);
6387c478bdstevel@tonic-gate	s = buf;
6397c478bdstevel@tonic-gate	if (*s == '/') {
6407c478bdstevel@tonic-gate		++s;
6417c478bdstevel@tonic-gate	}
6427c478bdstevel@tonic-gate	while ((slash = strchr(s, '/')) != NULL) {
6437c478bdstevel@tonic-gate		*slash = '\0';
6447c478bdstevel@tonic-gate		if ((int)strlen(s) >= 3 && strncmp(slash - 3, ".ss", 3) == 0) {
6457c478bdstevel@tonic-gate			*subsystem = s;
6467c478bdstevel@tonic-gate			s = slash + 1;
6477c478bdstevel@tonic-gate			if ((slash = strchr(s, '/')) != NULL) {
6487c478bdstevel@tonic-gate				*book = s;
6497c478bdstevel@tonic-gate				*slash = '\0';
6507c478bdstevel@tonic-gate			}
6517c478bdstevel@tonic-gate			break;
6527c478bdstevel@tonic-gate		}
6537c478bdstevel@tonic-gate		s = slash + 1;
6547c478bdstevel@tonic-gate	}
6557c478bdstevel@tonic-gate}
6567c478bdstevel@tonic-gate
6577c478bdstevel@tonic-gate/* get the requested path components */
6587c478bdstevel@tonic-gate
6597c478bdstevel@tonic-gatechar *
6607c478bdstevel@tonic-gatepathcomponents(char *path, int components)
6617c478bdstevel@tonic-gate{
6627c478bdstevel@tonic-gate	int	i;
6637c478bdstevel@tonic-gate	char	*s;
6647c478bdstevel@tonic-gate
6657c478bdstevel@tonic-gate	s = path + strlen(path) - 1;
6667c478bdstevel@tonic-gate	for (i = 0; i < components; ++i) {
6677c478bdstevel@tonic-gate		while (s > path && *--s != '/') {
6687c478bdstevel@tonic-gate			;
6697c478bdstevel@tonic-gate		}
6707c478bdstevel@tonic-gate	}
6717c478bdstevel@tonic-gate	if (s > path && *s == '/') {
6727c478bdstevel@tonic-gate		++s;
6737c478bdstevel@tonic-gate	}
6747c478bdstevel@tonic-gate	return (s);
6757c478bdstevel@tonic-gate}
676