1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * cscope - interactive C symbol or text cross-reference 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * searching functions 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <unistd.h> 40*7c478bd9Sstevel@tonic-gate #include <stdio.h> 41*7c478bd9Sstevel@tonic-gate #include <libgen.h> 42*7c478bd9Sstevel@tonic-gate #include "global.h" 43*7c478bd9Sstevel@tonic-gate #include "vp.h" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * most of these functions have been optimized so their innermost loops have 47*7c478bd9Sstevel@tonic-gate * only one test for the desired character by putting the char and 48*7c478bd9Sstevel@tonic-gate * an end-of-block marker (\0) at the end of the disk block buffer. 49*7c478bd9Sstevel@tonic-gate * When the inner loop exits on the char, an outer loop will see if 50*7c478bd9Sstevel@tonic-gate * the char is followed by a \0. If so, it will read the next block 51*7c478bd9Sstevel@tonic-gate * and restart the inner loop. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate char block[BUFSIZ + 2]; /* leave room for end-of-block mark */ 55*7c478bd9Sstevel@tonic-gate int blocklen; /* length of disk block read */ 56*7c478bd9Sstevel@tonic-gate char blockmark; /* mark character to be searched for */ 57*7c478bd9Sstevel@tonic-gate long blocknumber; /* block number */ 58*7c478bd9Sstevel@tonic-gate char *blockp; /* pointer to current char in block */ 59*7c478bd9Sstevel@tonic-gate char lastfilepath[PATHLEN + 1]; /* last file that full path was */ 60*7c478bd9Sstevel@tonic-gate /* computed for */ 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate static char cpattern[PATLEN + 1]; /* compressed pattern */ 63*7c478bd9Sstevel@tonic-gate static long lastfcnoffset; /* last function name offset */ 64*7c478bd9Sstevel@tonic-gate static long postingsfound; /* retrieved number of postings */ 65*7c478bd9Sstevel@tonic-gate static char *regexp; /* regular expression */ 66*7c478bd9Sstevel@tonic-gate static POSTING *postingp; /* retrieved posting set pointer */ 67*7c478bd9Sstevel@tonic-gate static long searchcount; /* count of files searched */ 68*7c478bd9Sstevel@tonic-gate static long starttime; /* start time for progress messages */ 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static POSTING *getposting(void); 71*7c478bd9Sstevel@tonic-gate static void putsource(FILE *output); 72*7c478bd9Sstevel@tonic-gate static void putref(char *file, char *function); 73*7c478bd9Sstevel@tonic-gate static void findcalledbysub(char *file); 74*7c478bd9Sstevel@tonic-gate static void findterm(void); 75*7c478bd9Sstevel@tonic-gate static void fileprogress(void); 76*7c478bd9Sstevel@tonic-gate static void putpostingref(POSTING *p); 77*7c478bd9Sstevel@tonic-gate static void putline(FILE *output); 78*7c478bd9Sstevel@tonic-gate static char *strtolower(char *s); 79*7c478bd9Sstevel@tonic-gate static char *filepath(char *file); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* find the symbol in the cross-reference */ 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate void 84*7c478bd9Sstevel@tonic-gate findsymbol(void) 85*7c478bd9Sstevel@tonic-gate { 86*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 87*7c478bd9Sstevel@tonic-gate char function[PATLEN + 1]; /* function name */ 88*7c478bd9Sstevel@tonic-gate char macro[PATLEN + 1]; /* macro name */ 89*7c478bd9Sstevel@tonic-gate char symbol[PATLEN + 1]; /* symbol name */ 90*7c478bd9Sstevel@tonic-gate char *cp; 91*7c478bd9Sstevel@tonic-gate char c; 92*7c478bd9Sstevel@tonic-gate char *s; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate if (invertedindex == YES) { 95*7c478bd9Sstevel@tonic-gate long lastline = 0; 96*7c478bd9Sstevel@tonic-gate POSTING *p; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate findterm(); 99*7c478bd9Sstevel@tonic-gate while ((p = getposting()) != NULL) { 100*7c478bd9Sstevel@tonic-gate if (p->type != INCLUDE && p->lineoffset != lastline) { 101*7c478bd9Sstevel@tonic-gate putpostingref(p); 102*7c478bd9Sstevel@tonic-gate lastline = p->lineoffset; 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate return; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate (void) scanpast('\t'); /* find the end of the header */ 108*7c478bd9Sstevel@tonic-gate skiprefchar(); /* skip the file marker */ 109*7c478bd9Sstevel@tonic-gate getstring(file); /* save the file name */ 110*7c478bd9Sstevel@tonic-gate *function = '\0'; 111*7c478bd9Sstevel@tonic-gate /* a macro can be inside a function, but not vice versa */ 112*7c478bd9Sstevel@tonic-gate *macro = '\0'; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* find the next symbol */ 115*7c478bd9Sstevel@tonic-gate /* note: this code was expanded in-line for speed */ 116*7c478bd9Sstevel@tonic-gate /* while (scanpast('\n') != NULL) { */ 117*7c478bd9Sstevel@tonic-gate /* other macros were replaced by code using cp instead of blockp */ 118*7c478bd9Sstevel@tonic-gate cp = blockp; 119*7c478bd9Sstevel@tonic-gate for (;;) { 120*7c478bd9Sstevel@tonic-gate setmark('\n'); 121*7c478bd9Sstevel@tonic-gate do { /* innermost loop optimized to only one test */ 122*7c478bd9Sstevel@tonic-gate while (*cp != '\n') { 123*7c478bd9Sstevel@tonic-gate ++cp; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate } while (*(cp + 1) == '\0' && (cp = readblock()) != NULL); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* skip the found character */ 128*7c478bd9Sstevel@tonic-gate if (cp != NULL && *(++cp + 1) == '\0') { 129*7c478bd9Sstevel@tonic-gate cp = readblock(); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 132*7c478bd9Sstevel@tonic-gate break; 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate /* look for a source file or function name */ 135*7c478bd9Sstevel@tonic-gate if (*cp == '\t') { 136*7c478bd9Sstevel@tonic-gate blockp = cp; 137*7c478bd9Sstevel@tonic-gate switch (getrefchar()) { 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate case NEWFILE: /* file name */ 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* save the name */ 142*7c478bd9Sstevel@tonic-gate skiprefchar(); 143*7c478bd9Sstevel@tonic-gate getstring(file); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* check for the end of the symbols */ 146*7c478bd9Sstevel@tonic-gate if (*file == '\0') { 147*7c478bd9Sstevel@tonic-gate return; 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate fileprogress(); 150*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate case FCNEND: /* function end */ 153*7c478bd9Sstevel@tonic-gate *function = '\0'; 154*7c478bd9Sstevel@tonic-gate goto notmatched; /* don't match name */ 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate case FCNDEF: /* function name */ 157*7c478bd9Sstevel@tonic-gate s = function; 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 161*7c478bd9Sstevel@tonic-gate if (fileversion >= 10) { 162*7c478bd9Sstevel@tonic-gate s = macro; 163*7c478bd9Sstevel@tonic-gate } else { 164*7c478bd9Sstevel@tonic-gate s = symbol; 165*7c478bd9Sstevel@tonic-gate } 166*7c478bd9Sstevel@tonic-gate break; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate case DEFINEEND: 169*7c478bd9Sstevel@tonic-gate *macro = '\0'; 170*7c478bd9Sstevel@tonic-gate goto notmatched; /* don't match name */ 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate case INCLUDE: /* #include file */ 173*7c478bd9Sstevel@tonic-gate goto notmatched; /* don't match name */ 174*7c478bd9Sstevel@tonic-gate default: /* other symbol */ 175*7c478bd9Sstevel@tonic-gate s = symbol; 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate /* save the name */ 178*7c478bd9Sstevel@tonic-gate skiprefchar(); 179*7c478bd9Sstevel@tonic-gate getstring(s); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* see if this is a regular expression pattern */ 182*7c478bd9Sstevel@tonic-gate if (regexp != NULL) { 183*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 184*7c478bd9Sstevel@tonic-gate s = strtolower(s); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate if (*s != '\0' && regex(regexp, s) != NULL) { 187*7c478bd9Sstevel@tonic-gate goto matched; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate /* match the symbol to the text pattern */ 191*7c478bd9Sstevel@tonic-gate else if (strequal(pattern, s)) { 192*7c478bd9Sstevel@tonic-gate goto matched; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate goto notmatched; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate /* if this is a regular expression pattern */ 197*7c478bd9Sstevel@tonic-gate if (regexp != NULL) { 198*7c478bd9Sstevel@tonic-gate c = *cp; 199*7c478bd9Sstevel@tonic-gate if (c & 0200) { /* digraph char? */ 200*7c478bd9Sstevel@tonic-gate c = dichar1[(c & 0177) / 8]; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate /* if this is a symbol */ 203*7c478bd9Sstevel@tonic-gate if (isalpha(c) || c == '_') { 204*7c478bd9Sstevel@tonic-gate blockp = cp; 205*7c478bd9Sstevel@tonic-gate getstring(symbol); 206*7c478bd9Sstevel@tonic-gate s = symbol; 207*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 208*7c478bd9Sstevel@tonic-gate s = strtolower(s); 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate /* match the symbol to the regular expression */ 211*7c478bd9Sstevel@tonic-gate if (regex(regexp, s) != NULL) { 212*7c478bd9Sstevel@tonic-gate goto matched; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate goto notmatched; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate /* match the character to the text pattern */ 218*7c478bd9Sstevel@tonic-gate else if (*cp == cpattern[0]) { 219*7c478bd9Sstevel@tonic-gate blockp = cp; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* match the rest of the symbol to the text pattern */ 222*7c478bd9Sstevel@tonic-gate if (matchrest()) { 223*7c478bd9Sstevel@tonic-gate s = NULL; 224*7c478bd9Sstevel@tonic-gate matched: 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * output the file, calling function or macro, 227*7c478bd9Sstevel@tonic-gate * and source line 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate if (*macro != '\0' && s != macro) { 230*7c478bd9Sstevel@tonic-gate putref(file, macro); 231*7c478bd9Sstevel@tonic-gate } else if (s != function) { 232*7c478bd9Sstevel@tonic-gate putref(file, function); 233*7c478bd9Sstevel@tonic-gate } else { 234*7c478bd9Sstevel@tonic-gate putref(file, ""); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate if (blockp == NULL) { 237*7c478bd9Sstevel@tonic-gate return; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate notmatched: 241*7c478bd9Sstevel@tonic-gate cp = blockp; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate blockp = cp; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate /* find the function definition or #define */ 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate void 250*7c478bd9Sstevel@tonic-gate finddef(void) 251*7c478bd9Sstevel@tonic-gate { 252*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 253*7c478bd9Sstevel@tonic-gate char function[PATLEN + 1]; /* function name */ 254*7c478bd9Sstevel@tonic-gate char macro[PATLEN + 1]; /* macro name */ 255*7c478bd9Sstevel@tonic-gate char symbol[PATLEN + 1]; /* symbol name */ 256*7c478bd9Sstevel@tonic-gate char *s; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate if (invertedindex == YES) { 259*7c478bd9Sstevel@tonic-gate POSTING *p; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate findterm(); 262*7c478bd9Sstevel@tonic-gate while ((p = getposting()) != NULL) { 263*7c478bd9Sstevel@tonic-gate switch (p->type) { 264*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 265*7c478bd9Sstevel@tonic-gate case FCNDEF: 266*7c478bd9Sstevel@tonic-gate case CLASSDEF: 267*7c478bd9Sstevel@tonic-gate case ENUMDEF: 268*7c478bd9Sstevel@tonic-gate case MEMBERDEF: 269*7c478bd9Sstevel@tonic-gate case STRUCTDEF: 270*7c478bd9Sstevel@tonic-gate case TYPEDEF: 271*7c478bd9Sstevel@tonic-gate case UNIONDEF: 272*7c478bd9Sstevel@tonic-gate case GLOBALDEF: /* other global definition */ 273*7c478bd9Sstevel@tonic-gate case LOCALDEF: /* other local definition */ 274*7c478bd9Sstevel@tonic-gate case PARAMETER: 275*7c478bd9Sstevel@tonic-gate putpostingref(p); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate return; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate /* find the next file name or definition */ 281*7c478bd9Sstevel@tonic-gate *function = '\0'; 282*7c478bd9Sstevel@tonic-gate /* a macro can be inside a function, but not vice versa */ 283*7c478bd9Sstevel@tonic-gate *macro = '\0'; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 286*7c478bd9Sstevel@tonic-gate switch (*blockp) { 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate case NEWFILE: 289*7c478bd9Sstevel@tonic-gate skiprefchar(); /* save file name */ 290*7c478bd9Sstevel@tonic-gate getstring(file); 291*7c478bd9Sstevel@tonic-gate if (*file == '\0') { /* if end of symbols */ 292*7c478bd9Sstevel@tonic-gate return; 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate fileprogress(); 295*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate case FCNEND: /* function end */ 298*7c478bd9Sstevel@tonic-gate *function = '\0'; 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate case FCNDEF: /* function name */ 302*7c478bd9Sstevel@tonic-gate s = function; 303*7c478bd9Sstevel@tonic-gate goto def; 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 306*7c478bd9Sstevel@tonic-gate if (fileversion >= 10) { 307*7c478bd9Sstevel@tonic-gate s = macro; 308*7c478bd9Sstevel@tonic-gate } else { 309*7c478bd9Sstevel@tonic-gate s = symbol; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate goto def; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate case DEFINEEND: 314*7c478bd9Sstevel@tonic-gate *macro = '\0'; 315*7c478bd9Sstevel@tonic-gate break; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate case CLASSDEF: 318*7c478bd9Sstevel@tonic-gate case ENUMDEF: 319*7c478bd9Sstevel@tonic-gate case MEMBERDEF: 320*7c478bd9Sstevel@tonic-gate case STRUCTDEF: 321*7c478bd9Sstevel@tonic-gate case TYPEDEF: 322*7c478bd9Sstevel@tonic-gate case UNIONDEF: 323*7c478bd9Sstevel@tonic-gate case GLOBALDEF: /* other global definition */ 324*7c478bd9Sstevel@tonic-gate case LOCALDEF: /* other local definition */ 325*7c478bd9Sstevel@tonic-gate case PARAMETER: 326*7c478bd9Sstevel@tonic-gate s = symbol; 327*7c478bd9Sstevel@tonic-gate def: 328*7c478bd9Sstevel@tonic-gate /* save the name */ 329*7c478bd9Sstevel@tonic-gate skiprefchar(); 330*7c478bd9Sstevel@tonic-gate getstring(s); 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* see if this is a regular expression pattern */ 333*7c478bd9Sstevel@tonic-gate if (regexp != NULL) { 334*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 335*7c478bd9Sstevel@tonic-gate s = strtolower(s); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate if (*s != '\0' && regex(regexp, s) != NULL) { 338*7c478bd9Sstevel@tonic-gate goto matched; 339*7c478bd9Sstevel@tonic-gate } 340*7c478bd9Sstevel@tonic-gate } else if (strequal(pattern, s)) { 341*7c478bd9Sstevel@tonic-gate /* match the symbol to the text pattern */ 342*7c478bd9Sstevel@tonic-gate matched: 343*7c478bd9Sstevel@tonic-gate /* 344*7c478bd9Sstevel@tonic-gate * output the file, calling function or macro, 345*7c478bd9Sstevel@tonic-gate * and source line 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate if (*macro != '\0' && s != macro) { 348*7c478bd9Sstevel@tonic-gate putref(file, macro); 349*7c478bd9Sstevel@tonic-gate } else if (s != function) { 350*7c478bd9Sstevel@tonic-gate putref(file, function); 351*7c478bd9Sstevel@tonic-gate } else { 352*7c478bd9Sstevel@tonic-gate putref(file, ""); 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* find all function definitions (used by samuel only) */ 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate void 362*7c478bd9Sstevel@tonic-gate findallfcns(void) 363*7c478bd9Sstevel@tonic-gate { 364*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 365*7c478bd9Sstevel@tonic-gate char function[PATLEN + 1]; /* function name */ 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* find the next file name or definition */ 368*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 369*7c478bd9Sstevel@tonic-gate switch (*blockp) { 370*7c478bd9Sstevel@tonic-gate case NEWFILE: 371*7c478bd9Sstevel@tonic-gate skiprefchar(); /* save file name */ 372*7c478bd9Sstevel@tonic-gate getstring(file); 373*7c478bd9Sstevel@tonic-gate if (*file == '\0') { /* if end of symbols */ 374*7c478bd9Sstevel@tonic-gate return; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate fileprogress(); 377*7c478bd9Sstevel@tonic-gate break; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate case FCNDEF: 380*7c478bd9Sstevel@tonic-gate case CLASSDEF: 381*7c478bd9Sstevel@tonic-gate skiprefchar(); /* save function name */ 382*7c478bd9Sstevel@tonic-gate getstring(function); 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate /* output the file, function and source line */ 385*7c478bd9Sstevel@tonic-gate putref(file, function); 386*7c478bd9Sstevel@tonic-gate break; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* find the functions called by this function */ 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate void 394*7c478bd9Sstevel@tonic-gate findcalledby(void) 395*7c478bd9Sstevel@tonic-gate { 396*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate if (invertedindex == YES) { 399*7c478bd9Sstevel@tonic-gate POSTING *p; 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate findterm(); 402*7c478bd9Sstevel@tonic-gate while ((p = getposting()) != NULL) { 403*7c478bd9Sstevel@tonic-gate switch (p->type) { 404*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 405*7c478bd9Sstevel@tonic-gate case FCNDEF: 406*7c478bd9Sstevel@tonic-gate if (dbseek(p->lineoffset) != -1 && 407*7c478bd9Sstevel@tonic-gate scanpast('\t') != NULL) { /* skip def */ 408*7c478bd9Sstevel@tonic-gate findcalledbysub(srcfiles[p->fileindex]); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate return; 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate /* find the function definition(s) */ 415*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 416*7c478bd9Sstevel@tonic-gate switch (*blockp) { 417*7c478bd9Sstevel@tonic-gate case NEWFILE: 418*7c478bd9Sstevel@tonic-gate skiprefchar(); /* save file name */ 419*7c478bd9Sstevel@tonic-gate getstring(file); 420*7c478bd9Sstevel@tonic-gate if (*file == '\0') { /* if end of symbols */ 421*7c478bd9Sstevel@tonic-gate return; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate fileprogress(); 424*7c478bd9Sstevel@tonic-gate break; 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 427*7c478bd9Sstevel@tonic-gate if (fileversion < 10) { 428*7c478bd9Sstevel@tonic-gate break; 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate case FCNDEF: 433*7c478bd9Sstevel@tonic-gate skiprefchar(); /* match name to pattern */ 434*7c478bd9Sstevel@tonic-gate if (match()) { 435*7c478bd9Sstevel@tonic-gate findcalledbysub(file); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate break; 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate static void 443*7c478bd9Sstevel@tonic-gate findcalledbysub(char *file) 444*7c478bd9Sstevel@tonic-gate { 445*7c478bd9Sstevel@tonic-gate /* find the next function call or the end of this function */ 446*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 447*7c478bd9Sstevel@tonic-gate switch (*blockp) { 448*7c478bd9Sstevel@tonic-gate case DEFINE: /* #define inside a function */ 449*7c478bd9Sstevel@tonic-gate if (fileversion >= 10) { /* skip it */ 450*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL && 451*7c478bd9Sstevel@tonic-gate *blockp != DEFINEEND) 452*7c478bd9Sstevel@tonic-gate ; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate break; 455*7c478bd9Sstevel@tonic-gate case FCNCALL: /* function call */ 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate /* output the file name */ 458*7c478bd9Sstevel@tonic-gate (void) fprintf(refsfound, "%s ", filepath(file)); 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* output the function name */ 461*7c478bd9Sstevel@tonic-gate skiprefchar(); 462*7c478bd9Sstevel@tonic-gate putline(refsfound); 463*7c478bd9Sstevel@tonic-gate (void) putc(' ', refsfound); 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate /* output the source line */ 466*7c478bd9Sstevel@tonic-gate putsource(refsfound); 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate case DEFINEEND: /* #define end */ 470*7c478bd9Sstevel@tonic-gate case FCNEND: /* function end */ 471*7c478bd9Sstevel@tonic-gate case FCNDEF: /* function end (pre 9.5) */ 472*7c478bd9Sstevel@tonic-gate case NEWFILE: /* file end */ 473*7c478bd9Sstevel@tonic-gate return; 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate /* find the functions calling this function */ 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate void 481*7c478bd9Sstevel@tonic-gate findcalling(void) 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 484*7c478bd9Sstevel@tonic-gate char function[PATLEN + 1]; /* function name */ 485*7c478bd9Sstevel@tonic-gate char macro[PATLEN + 1]; /* macro name */ 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (invertedindex == YES) { 488*7c478bd9Sstevel@tonic-gate POSTING *p; 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate findterm(); 491*7c478bd9Sstevel@tonic-gate while ((p = getposting()) != NULL) { 492*7c478bd9Sstevel@tonic-gate if (p->type == FCNCALL) { 493*7c478bd9Sstevel@tonic-gate putpostingref(p); 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate return; 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate /* find the next file name or function definition */ 499*7c478bd9Sstevel@tonic-gate /* a macro can be inside a function, but not vice versa */ 500*7c478bd9Sstevel@tonic-gate *macro = '\0'; 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 503*7c478bd9Sstevel@tonic-gate switch (*blockp) { 504*7c478bd9Sstevel@tonic-gate case NEWFILE: /* save file name */ 505*7c478bd9Sstevel@tonic-gate skiprefchar(); 506*7c478bd9Sstevel@tonic-gate getstring(file); 507*7c478bd9Sstevel@tonic-gate if (*file == '\0') { /* if end of symbols */ 508*7c478bd9Sstevel@tonic-gate return; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate fileprogress(); 511*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 512*7c478bd9Sstevel@tonic-gate case FCNEND: /* function end */ 513*7c478bd9Sstevel@tonic-gate *function = '\0'; 514*7c478bd9Sstevel@tonic-gate break; 515*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 516*7c478bd9Sstevel@tonic-gate if (fileversion >= 10) { 517*7c478bd9Sstevel@tonic-gate skiprefchar(); 518*7c478bd9Sstevel@tonic-gate getstring(macro); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate break; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate case DEFINEEND: 523*7c478bd9Sstevel@tonic-gate *macro = '\0'; 524*7c478bd9Sstevel@tonic-gate break; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate case FCNDEF: /* save calling function name */ 527*7c478bd9Sstevel@tonic-gate skiprefchar(); 528*7c478bd9Sstevel@tonic-gate getstring(function); 529*7c478bd9Sstevel@tonic-gate break; 530*7c478bd9Sstevel@tonic-gate case FCNCALL: /* match function called to pattern */ 531*7c478bd9Sstevel@tonic-gate skiprefchar(); 532*7c478bd9Sstevel@tonic-gate if (match()) { 533*7c478bd9Sstevel@tonic-gate /* output the file, calling function or */ 534*7c478bd9Sstevel@tonic-gate /* macro, and source */ 535*7c478bd9Sstevel@tonic-gate if (*macro != '\0') { 536*7c478bd9Sstevel@tonic-gate putref(file, macro); 537*7c478bd9Sstevel@tonic-gate } else { 538*7c478bd9Sstevel@tonic-gate putref(file, function); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate /* find direct assignment to, and increment and decrement of, this variable */ 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate void 548*7c478bd9Sstevel@tonic-gate findassignments(void) 549*7c478bd9Sstevel@tonic-gate { 550*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 551*7c478bd9Sstevel@tonic-gate char function[PATLEN + 1]; /* function name */ 552*7c478bd9Sstevel@tonic-gate char macro[PATLEN + 1]; /* macro name */ 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate if (fileversion < 13) { 555*7c478bd9Sstevel@tonic-gate putmsg("Database built with cscope version < 13 does not " 556*7c478bd9Sstevel@tonic-gate "have assignment information"); 557*7c478bd9Sstevel@tonic-gate (void) sleep(3); 558*7c478bd9Sstevel@tonic-gate return; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate #if CTRACE 561*7c478bd9Sstevel@tonic-gate ctroff(); 562*7c478bd9Sstevel@tonic-gate #endif 563*7c478bd9Sstevel@tonic-gate if (invertedindex == YES) { 564*7c478bd9Sstevel@tonic-gate POSTING *p; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate findterm(); 567*7c478bd9Sstevel@tonic-gate while ((p = getposting()) != NULL) { 568*7c478bd9Sstevel@tonic-gate switch (p->type) { 569*7c478bd9Sstevel@tonic-gate case ASSIGNMENT: 570*7c478bd9Sstevel@tonic-gate case GLOBALDEF: /* can have initializer */ 571*7c478bd9Sstevel@tonic-gate case LOCALDEF: /* can have initializer */ 572*7c478bd9Sstevel@tonic-gate case PARAMETER: /* initial value */ 573*7c478bd9Sstevel@tonic-gate putpostingref(p); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate return; 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate /* find the next file name or function definition */ 579*7c478bd9Sstevel@tonic-gate /* a macro can be inside a function, but not vice versa */ 580*7c478bd9Sstevel@tonic-gate *macro = '\0'; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 583*7c478bd9Sstevel@tonic-gate switch (*blockp) { 584*7c478bd9Sstevel@tonic-gate case NEWFILE: /* save file name */ 585*7c478bd9Sstevel@tonic-gate skiprefchar(); 586*7c478bd9Sstevel@tonic-gate getstring(file); 587*7c478bd9Sstevel@tonic-gate if (*file == '\0') { /* if end of symbols */ 588*7c478bd9Sstevel@tonic-gate return; 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate fileprogress(); 591*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 592*7c478bd9Sstevel@tonic-gate case FCNEND: /* function end */ 593*7c478bd9Sstevel@tonic-gate *function = '\0'; 594*7c478bd9Sstevel@tonic-gate break; 595*7c478bd9Sstevel@tonic-gate case DEFINE: /* could be a macro */ 596*7c478bd9Sstevel@tonic-gate if (fileversion >= 10) { 597*7c478bd9Sstevel@tonic-gate skiprefchar(); 598*7c478bd9Sstevel@tonic-gate getstring(macro); 599*7c478bd9Sstevel@tonic-gate } 600*7c478bd9Sstevel@tonic-gate break; 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate case DEFINEEND: 603*7c478bd9Sstevel@tonic-gate *macro = '\0'; 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate case FCNDEF: /* save calling function name */ 607*7c478bd9Sstevel@tonic-gate skiprefchar(); 608*7c478bd9Sstevel@tonic-gate getstring(function); 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate case ASSIGNMENT: /* match assignment to pattern */ 611*7c478bd9Sstevel@tonic-gate case GLOBALDEF: /* can have initializer */ 612*7c478bd9Sstevel@tonic-gate case LOCALDEF: /* can have initializer */ 613*7c478bd9Sstevel@tonic-gate case PARAMETER: /* initial value */ 614*7c478bd9Sstevel@tonic-gate skiprefchar(); 615*7c478bd9Sstevel@tonic-gate if (match()) { 616*7c478bd9Sstevel@tonic-gate /* output the file, calling function or */ 617*7c478bd9Sstevel@tonic-gate /* macro, and source */ 618*7c478bd9Sstevel@tonic-gate if (*macro != '\0') { 619*7c478bd9Sstevel@tonic-gate putref(file, macro); 620*7c478bd9Sstevel@tonic-gate } else { 621*7c478bd9Sstevel@tonic-gate putref(file, function); 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate /* find the grep pattern in the source files */ 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate char * 631*7c478bd9Sstevel@tonic-gate findgreppat(void) 632*7c478bd9Sstevel@tonic-gate { 633*7c478bd9Sstevel@tonic-gate char egreppat[2 * PATLEN]; 634*7c478bd9Sstevel@tonic-gate char *cp, *pp; 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate /* translate egrep special characters in the regular expression */ 637*7c478bd9Sstevel@tonic-gate cp = egreppat; 638*7c478bd9Sstevel@tonic-gate for (pp = pattern; *pp != '\0'; ++pp) { 639*7c478bd9Sstevel@tonic-gate if (strchr("+?|()", *pp) != NULL) { 640*7c478bd9Sstevel@tonic-gate *cp++ = '\\'; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate *cp++ = *pp; 643*7c478bd9Sstevel@tonic-gate } 644*7c478bd9Sstevel@tonic-gate *cp = '\0'; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate /* search the source files */ 647*7c478bd9Sstevel@tonic-gate return (findegreppat(egreppat)); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* find this regular expression in the source files */ 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate char * 653*7c478bd9Sstevel@tonic-gate findegreppat(char *egreppat) 654*7c478bd9Sstevel@tonic-gate { 655*7c478bd9Sstevel@tonic-gate int i; 656*7c478bd9Sstevel@tonic-gate char *egreperror; 657*7c478bd9Sstevel@tonic-gate char msg[MSGLEN + 1]; 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate /* compile the pattern */ 660*7c478bd9Sstevel@tonic-gate if ((egreperror = egrepinit(egreppat)) == NULL) { 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* search the files */ 663*7c478bd9Sstevel@tonic-gate for (i = 0; i < nsrcfiles; ++i) { 664*7c478bd9Sstevel@tonic-gate char *file = filepath(srcfiles[i]); 665*7c478bd9Sstevel@tonic-gate fileprogress(); 666*7c478bd9Sstevel@tonic-gate if (egrep(file, refsfound, "%s <unknown> %ld ") < 0) { 667*7c478bd9Sstevel@tonic-gate (void) sprintf(msg, "Cannot open file %s", 668*7c478bd9Sstevel@tonic-gate file); 669*7c478bd9Sstevel@tonic-gate putmsg2(msg); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate } 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate return (egreperror); 674*7c478bd9Sstevel@tonic-gate } 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate /* find matching file names */ 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate void 679*7c478bd9Sstevel@tonic-gate findfile(void) 680*7c478bd9Sstevel@tonic-gate { 681*7c478bd9Sstevel@tonic-gate int i; 682*7c478bd9Sstevel@tonic-gate char *s; 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate for (i = 0; i < nsrcfiles; ++i) { 685*7c478bd9Sstevel@tonic-gate s = srcfiles[i]; 686*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 687*7c478bd9Sstevel@tonic-gate s = strtolower(s); 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate if (regex(regexp, s) != NULL) { 690*7c478bd9Sstevel@tonic-gate (void) fprintf(refsfound, "%s <unknown> 1 <unknown>\n", 691*7c478bd9Sstevel@tonic-gate filepath(srcfiles[i])); 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate } 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* find files #including this file */ 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate void 699*7c478bd9Sstevel@tonic-gate findinclude(void) 700*7c478bd9Sstevel@tonic-gate { 701*7c478bd9Sstevel@tonic-gate char file[PATHLEN + 1]; /* source file name */ 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate if (invertedindex == YES) { 704*7c478bd9Sstevel@tonic-gate POSTING *p; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate findterm(); 707*7c478bd9Sstevel@tonic-gate while ((p = getposting()) != NULL) { 708*7c478bd9Sstevel@tonic-gate if (p->type == INCLUDE) { 709*7c478bd9Sstevel@tonic-gate putpostingref(p); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate } 712*7c478bd9Sstevel@tonic-gate return; 713*7c478bd9Sstevel@tonic-gate } 714*7c478bd9Sstevel@tonic-gate /* find the next file name or function definition */ 715*7c478bd9Sstevel@tonic-gate while (scanpast('\t') != NULL) { 716*7c478bd9Sstevel@tonic-gate switch (*blockp) { 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate case NEWFILE: /* save file name */ 719*7c478bd9Sstevel@tonic-gate skiprefchar(); 720*7c478bd9Sstevel@tonic-gate getstring(file); 721*7c478bd9Sstevel@tonic-gate if (*file == '\0') { /* if end of symbols */ 722*7c478bd9Sstevel@tonic-gate return; 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate fileprogress(); 725*7c478bd9Sstevel@tonic-gate break; 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate case INCLUDE: /* match function called to pattern */ 728*7c478bd9Sstevel@tonic-gate skiprefchar(); 729*7c478bd9Sstevel@tonic-gate /* skip global or local #include marker */ 730*7c478bd9Sstevel@tonic-gate skiprefchar(); 731*7c478bd9Sstevel@tonic-gate if (match()) { 732*7c478bd9Sstevel@tonic-gate /* output the file and source line */ 733*7c478bd9Sstevel@tonic-gate putref(file, ""); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate /* initialize */ 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate FINDINIT 742*7c478bd9Sstevel@tonic-gate findinit(void) 743*7c478bd9Sstevel@tonic-gate { 744*7c478bd9Sstevel@tonic-gate char buf[PATLEN + 3]; 745*7c478bd9Sstevel@tonic-gate BOOL isregexp = NO; 746*7c478bd9Sstevel@tonic-gate int i; 747*7c478bd9Sstevel@tonic-gate char *s; 748*7c478bd9Sstevel@tonic-gate unsigned c; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate /* remove trailing white space */ 751*7c478bd9Sstevel@tonic-gate for (s = pattern + strlen(pattern) - 1; isspace(*s); --s) { 752*7c478bd9Sstevel@tonic-gate *s = '\0'; 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate /* allow a partial match for a file name */ 755*7c478bd9Sstevel@tonic-gate if (field == FILENAME || field == INCLUDES) { 756*7c478bd9Sstevel@tonic-gate /* allow types.h to match #include <sys/types.h> */ 757*7c478bd9Sstevel@tonic-gate if (invertedindex == YES && field == INCLUDES && 758*7c478bd9Sstevel@tonic-gate strncmp(pattern, ".*", 2) != 0) { 759*7c478bd9Sstevel@tonic-gate (void) sprintf(pattern, ".*%s", strcpy(buf, pattern)); 760*7c478bd9Sstevel@tonic-gate } 761*7c478bd9Sstevel@tonic-gate if ((regexp = regcmp(pattern, (char *)NULL)) == NULL) { 762*7c478bd9Sstevel@tonic-gate return (REGCMPERROR); 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate return (NOERROR); 765*7c478bd9Sstevel@tonic-gate } 766*7c478bd9Sstevel@tonic-gate /* see if the pattern is a regular expression */ 767*7c478bd9Sstevel@tonic-gate if (strpbrk(pattern, "^.[{*+$") != NULL) { 768*7c478bd9Sstevel@tonic-gate isregexp = YES; 769*7c478bd9Sstevel@tonic-gate } else { 770*7c478bd9Sstevel@tonic-gate /* check for a valid C symbol */ 771*7c478bd9Sstevel@tonic-gate s = pattern; 772*7c478bd9Sstevel@tonic-gate if (!isalpha(*s) && *s != '_') { 773*7c478bd9Sstevel@tonic-gate return (NOTSYMBOL); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate while (*++s != '\0') { 776*7c478bd9Sstevel@tonic-gate if (!isalnum(*s) && *s != '_') { 777*7c478bd9Sstevel@tonic-gate return (NOTSYMBOL); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate /* 781*7c478bd9Sstevel@tonic-gate * look for use of the -T option (truncate symbol to 8 782*7c478bd9Sstevel@tonic-gate * characters) on a database not built with -T 783*7c478bd9Sstevel@tonic-gate */ 784*7c478bd9Sstevel@tonic-gate if (truncatesyms == YES && isuptodate == YES && 785*7c478bd9Sstevel@tonic-gate dbtruncated == NO && s - pattern >= 8) { 786*7c478bd9Sstevel@tonic-gate (void) strcpy(pattern + 8, ".*"); 787*7c478bd9Sstevel@tonic-gate isregexp = YES; 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate } 790*7c478bd9Sstevel@tonic-gate /* if this is a regular expression or letter case is to be ignored */ 791*7c478bd9Sstevel@tonic-gate /* or there is an inverted index */ 792*7c478bd9Sstevel@tonic-gate if (isregexp == YES || caseless == YES || invertedindex == YES) { 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate /* remove a leading ^ */ 795*7c478bd9Sstevel@tonic-gate s = pattern; 796*7c478bd9Sstevel@tonic-gate if (*s == '^') { 797*7c478bd9Sstevel@tonic-gate (void) strcpy(newpat, s + 1); 798*7c478bd9Sstevel@tonic-gate (void) strcpy(s, newpat); 799*7c478bd9Sstevel@tonic-gate } 800*7c478bd9Sstevel@tonic-gate /* remove a trailing $ */ 801*7c478bd9Sstevel@tonic-gate i = strlen(s) - 1; 802*7c478bd9Sstevel@tonic-gate if (s[i] == '$') { 803*7c478bd9Sstevel@tonic-gate s[i] = '\0'; 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate /* if requested, try to truncate a C symbol pattern */ 806*7c478bd9Sstevel@tonic-gate if (truncatesyms == YES && strpbrk(s, "[{*+") == NULL) { 807*7c478bd9Sstevel@tonic-gate s[8] = '\0'; 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate /* must be an exact match */ 810*7c478bd9Sstevel@tonic-gate /* 811*7c478bd9Sstevel@tonic-gate * note: regcmp doesn't recognize ^*keypad$ as an syntax error 812*7c478bd9Sstevel@tonic-gate * unless it is given as a single arg 813*7c478bd9Sstevel@tonic-gate */ 814*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "^%s$", s); 815*7c478bd9Sstevel@tonic-gate if ((regexp = regcmp(buf, (char *)NULL)) == NULL) { 816*7c478bd9Sstevel@tonic-gate return (REGCMPERROR); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate } else { 819*7c478bd9Sstevel@tonic-gate /* if requested, truncate a C symbol pattern */ 820*7c478bd9Sstevel@tonic-gate if (truncatesyms == YES && field <= CALLING) { 821*7c478bd9Sstevel@tonic-gate pattern[8] = '\0'; 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate /* compress the string pattern for matching */ 824*7c478bd9Sstevel@tonic-gate s = cpattern; 825*7c478bd9Sstevel@tonic-gate for (i = 0; (c = pattern[i]) != '\0'; ++i) { 826*7c478bd9Sstevel@tonic-gate if (dicode1[c] && dicode2[(unsigned)pattern[i + 1]]) { 827*7c478bd9Sstevel@tonic-gate c = (0200 - 2) + dicode1[c] + 828*7c478bd9Sstevel@tonic-gate dicode2[(unsigned)pattern[i + 1]]; 829*7c478bd9Sstevel@tonic-gate ++i; 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate *s++ = (char)c; 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate *s = '\0'; 834*7c478bd9Sstevel@tonic-gate } 835*7c478bd9Sstevel@tonic-gate return (NOERROR); 836*7c478bd9Sstevel@tonic-gate } 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate void 839*7c478bd9Sstevel@tonic-gate findcleanup(void) 840*7c478bd9Sstevel@tonic-gate { 841*7c478bd9Sstevel@tonic-gate /* discard any regular expression */ 842*7c478bd9Sstevel@tonic-gate if (regexp != NULL) { 843*7c478bd9Sstevel@tonic-gate free(regexp); 844*7c478bd9Sstevel@tonic-gate regexp = NULL; 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate /* find this term, which can be a regular expression */ 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate static void 851*7c478bd9Sstevel@tonic-gate findterm(void) 852*7c478bd9Sstevel@tonic-gate { 853*7c478bd9Sstevel@tonic-gate char *s; 854*7c478bd9Sstevel@tonic-gate int len; 855*7c478bd9Sstevel@tonic-gate char prefix[PATLEN + 1]; 856*7c478bd9Sstevel@tonic-gate char term[PATLEN + 1]; 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate npostings = 0; /* will be non-zero after database built */ 859*7c478bd9Sstevel@tonic-gate lastfcnoffset = 0; /* clear the last function name found */ 860*7c478bd9Sstevel@tonic-gate boolclear(); /* clear the posting set */ 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate /* get the string prefix (if any) of the regular expression */ 863*7c478bd9Sstevel@tonic-gate (void) strcpy(prefix, pattern); 864*7c478bd9Sstevel@tonic-gate if ((s = strpbrk(prefix, ".[{*+")) != NULL) { 865*7c478bd9Sstevel@tonic-gate *s = '\0'; 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate /* if letter case is to be ignored */ 868*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate /* 871*7c478bd9Sstevel@tonic-gate * convert the prefix to upper case because it is lexically 872*7c478bd9Sstevel@tonic-gate * less than lower case 873*7c478bd9Sstevel@tonic-gate */ 874*7c478bd9Sstevel@tonic-gate s = prefix; 875*7c478bd9Sstevel@tonic-gate while (*s != '\0') { 876*7c478bd9Sstevel@tonic-gate *s = toupper(*s); 877*7c478bd9Sstevel@tonic-gate ++s; 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate /* find the term lexically >= the prefix */ 881*7c478bd9Sstevel@tonic-gate (void) invfind(&invcontrol, prefix); 882*7c478bd9Sstevel@tonic-gate if (caseless == YES) { /* restore lower case */ 883*7c478bd9Sstevel@tonic-gate (void) strcpy(prefix, strtolower(prefix)); 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate /* 886*7c478bd9Sstevel@tonic-gate * a null prefix matches the null term in the inverted index, 887*7c478bd9Sstevel@tonic-gate * so move to the first real term 888*7c478bd9Sstevel@tonic-gate */ 889*7c478bd9Sstevel@tonic-gate if (*prefix == '\0') { 890*7c478bd9Sstevel@tonic-gate (void) invforward(&invcontrol); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate len = strlen(prefix); 893*7c478bd9Sstevel@tonic-gate do { 894*7c478bd9Sstevel@tonic-gate (void) invterm(&invcontrol, term); /* get the term */ 895*7c478bd9Sstevel@tonic-gate s = term; 896*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 897*7c478bd9Sstevel@tonic-gate s = strtolower(s); /* make it lower case */ 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate /* if it matches */ 900*7c478bd9Sstevel@tonic-gate if (regex(regexp, s) != NULL) { 901*7c478bd9Sstevel@tonic-gate /* add it's postings to the set */ 902*7c478bd9Sstevel@tonic-gate if ((postingp = boolfile(&invcontrol, 903*7c478bd9Sstevel@tonic-gate &npostings, OR)) == NULL) { 904*7c478bd9Sstevel@tonic-gate break; 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate } else if (len > 0) { 907*7c478bd9Sstevel@tonic-gate /* if there is a prefix */ 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate /* 910*7c478bd9Sstevel@tonic-gate * if ignoring letter case and the term is out of the 911*7c478bd9Sstevel@tonic-gate * range of possible matches 912*7c478bd9Sstevel@tonic-gate */ 913*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 914*7c478bd9Sstevel@tonic-gate if (strncmp(term, prefix, len) > 0) { 915*7c478bd9Sstevel@tonic-gate break; /* stop searching */ 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate /* if using letter case and the prefix doesn't match */ 919*7c478bd9Sstevel@tonic-gate else if (strncmp(term, prefix, len) != 0) { 920*7c478bd9Sstevel@tonic-gate break; /* stop searching */ 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate /* display progress about every three seconds */ 924*7c478bd9Sstevel@tonic-gate if (++searchcount % 50 == 0) { 925*7c478bd9Sstevel@tonic-gate progress("%ld of %ld symbols matched", 926*7c478bd9Sstevel@tonic-gate searchcount, totalterms); 927*7c478bd9Sstevel@tonic-gate } 928*7c478bd9Sstevel@tonic-gate } while (invforward(&invcontrol)); /* while didn't wrap around */ 929*7c478bd9Sstevel@tonic-gate 930*7c478bd9Sstevel@tonic-gate /* initialize the progress message for retrieving the references */ 931*7c478bd9Sstevel@tonic-gate initprogress(); 932*7c478bd9Sstevel@tonic-gate postingsfound = npostings; 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* display the file search progress about every three seconds */ 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate static void 938*7c478bd9Sstevel@tonic-gate fileprogress(void) 939*7c478bd9Sstevel@tonic-gate { 940*7c478bd9Sstevel@tonic-gate if (++searchcount % 10 == 0) { 941*7c478bd9Sstevel@tonic-gate progress("%ld of %ld files searched", searchcount, 942*7c478bd9Sstevel@tonic-gate (long)nsrcfiles); 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate 946*7c478bd9Sstevel@tonic-gate /* initialize the progress message */ 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate void 949*7c478bd9Sstevel@tonic-gate initprogress(void) 950*7c478bd9Sstevel@tonic-gate { 951*7c478bd9Sstevel@tonic-gate searchcount = 0; 952*7c478bd9Sstevel@tonic-gate starttime = time((long *)NULL); 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate /* display the progress every three seconds */ 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate void 958*7c478bd9Sstevel@tonic-gate progress(char *format, long n1, long n2) 959*7c478bd9Sstevel@tonic-gate { 960*7c478bd9Sstevel@tonic-gate char msg[MSGLEN + 1]; 961*7c478bd9Sstevel@tonic-gate long now; 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate /* print after 2 seconds so the average is nearer 3 seconds */ 964*7c478bd9Sstevel@tonic-gate if (linemode == NO && (now = time((long *)NULL)) - starttime >= 2) { 965*7c478bd9Sstevel@tonic-gate starttime = now; 966*7c478bd9Sstevel@tonic-gate (void) sprintf(msg, format, n1, n2); 967*7c478bd9Sstevel@tonic-gate putmsg(msg); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate /* match the pattern to the string */ 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate BOOL 974*7c478bd9Sstevel@tonic-gate match(void) 975*7c478bd9Sstevel@tonic-gate { 976*7c478bd9Sstevel@tonic-gate char string[PATLEN + 1]; 977*7c478bd9Sstevel@tonic-gate char *s; 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate /* see if this is a regular expression pattern */ 980*7c478bd9Sstevel@tonic-gate if (regexp != NULL) { 981*7c478bd9Sstevel@tonic-gate getstring(string); 982*7c478bd9Sstevel@tonic-gate if (*string == '\0') { 983*7c478bd9Sstevel@tonic-gate return (NO); 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate s = string; 986*7c478bd9Sstevel@tonic-gate if (caseless == YES) { 987*7c478bd9Sstevel@tonic-gate s = strtolower(s); 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate return (regex(regexp, s) ? YES : NO); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate /* it is a string pattern */ 992*7c478bd9Sstevel@tonic-gate return ((BOOL)(*blockp == cpattern[0] && matchrest())); 993*7c478bd9Sstevel@tonic-gate } 994*7c478bd9Sstevel@tonic-gate 995*7c478bd9Sstevel@tonic-gate /* match the rest of the pattern to the name */ 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate BOOL 998*7c478bd9Sstevel@tonic-gate matchrest(void) 999*7c478bd9Sstevel@tonic-gate { 1000*7c478bd9Sstevel@tonic-gate int i = 1; 1001*7c478bd9Sstevel@tonic-gate 1002*7c478bd9Sstevel@tonic-gate skiprefchar(); 1003*7c478bd9Sstevel@tonic-gate do { 1004*7c478bd9Sstevel@tonic-gate while (*blockp == cpattern[i]) { 1005*7c478bd9Sstevel@tonic-gate ++blockp; 1006*7c478bd9Sstevel@tonic-gate ++i; 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate } while (*(blockp + 1) == '\0' && readblock() != NULL); 1009*7c478bd9Sstevel@tonic-gate 1010*7c478bd9Sstevel@tonic-gate if (*blockp == '\n' && cpattern[i] == '\0') { 1011*7c478bd9Sstevel@tonic-gate return (YES); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate return (NO); 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate /* get the next posting for this term */ 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate static POSTING * 1019*7c478bd9Sstevel@tonic-gate getposting(void) 1020*7c478bd9Sstevel@tonic-gate { 1021*7c478bd9Sstevel@tonic-gate if (npostings-- <= 0) { 1022*7c478bd9Sstevel@tonic-gate return (NULL); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate /* display progress about every three seconds */ 1025*7c478bd9Sstevel@tonic-gate if (++searchcount % 100 == 0) { 1026*7c478bd9Sstevel@tonic-gate progress("%ld of %ld possible references retrieved", 1027*7c478bd9Sstevel@tonic-gate searchcount, postingsfound); 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate return (postingp++); 1030*7c478bd9Sstevel@tonic-gate } 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate /* put the posting reference into the file */ 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate static void 1035*7c478bd9Sstevel@tonic-gate putpostingref(POSTING *p) 1036*7c478bd9Sstevel@tonic-gate { 1037*7c478bd9Sstevel@tonic-gate static char function[PATLEN + 1]; /* function name */ 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate if (p->fcnoffset == 0) { 1040*7c478bd9Sstevel@tonic-gate *function = '\0'; 1041*7c478bd9Sstevel@tonic-gate } else if (p->fcnoffset != lastfcnoffset) { 1042*7c478bd9Sstevel@tonic-gate if (dbseek(p->fcnoffset) != -1) { 1043*7c478bd9Sstevel@tonic-gate getstring(function); 1044*7c478bd9Sstevel@tonic-gate lastfcnoffset = p->fcnoffset; 1045*7c478bd9Sstevel@tonic-gate } 1046*7c478bd9Sstevel@tonic-gate } 1047*7c478bd9Sstevel@tonic-gate if (dbseek(p->lineoffset) != -1) { 1048*7c478bd9Sstevel@tonic-gate putref(srcfiles[p->fileindex], function); 1049*7c478bd9Sstevel@tonic-gate } 1050*7c478bd9Sstevel@tonic-gate } 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate /* put the reference into the file */ 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate static void 1055*7c478bd9Sstevel@tonic-gate putref(char *file, char *function) 1056*7c478bd9Sstevel@tonic-gate { 1057*7c478bd9Sstevel@tonic-gate FILE *output; 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate /* put global references first */ 1060*7c478bd9Sstevel@tonic-gate if (*function == '\0') { 1061*7c478bd9Sstevel@tonic-gate function = "<global>"; 1062*7c478bd9Sstevel@tonic-gate output = refsfound; 1063*7c478bd9Sstevel@tonic-gate } else { 1064*7c478bd9Sstevel@tonic-gate output = nonglobalrefs; 1065*7c478bd9Sstevel@tonic-gate } 1066*7c478bd9Sstevel@tonic-gate if (fprintf(output, "%s %s ", filepath(file), function) == EOF) { 1067*7c478bd9Sstevel@tonic-gate cannotwrite(temp1); 1068*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate putsource(output); 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate /* put the source line into the file */ 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate static void 1076*7c478bd9Sstevel@tonic-gate putsource(FILE *output) 1077*7c478bd9Sstevel@tonic-gate { 1078*7c478bd9Sstevel@tonic-gate char *cp, nextc = '\0'; 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate if (fileversion <= 5) { 1081*7c478bd9Sstevel@tonic-gate (void) scanpast(' '); 1082*7c478bd9Sstevel@tonic-gate putline(output); 1083*7c478bd9Sstevel@tonic-gate (void) putc('\n', output); 1084*7c478bd9Sstevel@tonic-gate return; 1085*7c478bd9Sstevel@tonic-gate } 1086*7c478bd9Sstevel@tonic-gate /* scan back to the beginning of the source line */ 1087*7c478bd9Sstevel@tonic-gate cp = blockp; 1088*7c478bd9Sstevel@tonic-gate while (*cp != '\n' || nextc != '\n') { 1089*7c478bd9Sstevel@tonic-gate nextc = *cp; 1090*7c478bd9Sstevel@tonic-gate if (--cp < block) { 1091*7c478bd9Sstevel@tonic-gate /* read the previous block */ 1092*7c478bd9Sstevel@tonic-gate (void) dbseek((blocknumber - 1) * BUFSIZ); 1093*7c478bd9Sstevel@tonic-gate cp = &block[BUFSIZ - 1]; 1094*7c478bd9Sstevel@tonic-gate } 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate /* there must be a double newline followed by a line number */ 1097*7c478bd9Sstevel@tonic-gate blockp = cp; 1098*7c478bd9Sstevel@tonic-gate setmark(' '); /* so getrefchar doesn't skip the last block char */ 1099*7c478bd9Sstevel@tonic-gate if (*blockp != '\n' || getrefchar() != '\n' || 1100*7c478bd9Sstevel@tonic-gate !isdigit(getrefchar()) && fileversion >= 12) { 1101*7c478bd9Sstevel@tonic-gate putmsg("Internal error: cannot get source line from database"); 1102*7c478bd9Sstevel@tonic-gate myexit(1); 1103*7c478bd9Sstevel@tonic-gate } 1104*7c478bd9Sstevel@tonic-gate /* until a double newline is found */ 1105*7c478bd9Sstevel@tonic-gate do { 1106*7c478bd9Sstevel@tonic-gate /* skip a symbol type */ 1107*7c478bd9Sstevel@tonic-gate if (*blockp == '\t') { 1108*7c478bd9Sstevel@tonic-gate skiprefchar(); 1109*7c478bd9Sstevel@tonic-gate skiprefchar(); 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate /* output a piece of the source line */ 1112*7c478bd9Sstevel@tonic-gate putline(output); 1113*7c478bd9Sstevel@tonic-gate } while (blockp != NULL && getrefchar() != '\n'); 1114*7c478bd9Sstevel@tonic-gate (void) putc('\n', output); 1115*7c478bd9Sstevel@tonic-gate } 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate /* put the rest of the cross-reference line into the file */ 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate static void 1120*7c478bd9Sstevel@tonic-gate putline(FILE *output) 1121*7c478bd9Sstevel@tonic-gate { 1122*7c478bd9Sstevel@tonic-gate char *cp; 1123*7c478bd9Sstevel@tonic-gate unsigned c; 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate setmark('\n'); 1126*7c478bd9Sstevel@tonic-gate cp = blockp; 1127*7c478bd9Sstevel@tonic-gate do { 1128*7c478bd9Sstevel@tonic-gate while ((c = *cp) != '\n') { 1129*7c478bd9Sstevel@tonic-gate /* check for a compressed digraph */ 1130*7c478bd9Sstevel@tonic-gate if (c & 0200) { 1131*7c478bd9Sstevel@tonic-gate c &= 0177; 1132*7c478bd9Sstevel@tonic-gate (void) putc(dichar1[c / 8], output); 1133*7c478bd9Sstevel@tonic-gate (void) putc(dichar2[c & 7], output); 1134*7c478bd9Sstevel@tonic-gate } else if (c < ' ') { 1135*7c478bd9Sstevel@tonic-gate /* a compressed keyword */ 1136*7c478bd9Sstevel@tonic-gate (void) fputs(keyword[c].text, output); 1137*7c478bd9Sstevel@tonic-gate if (keyword[c].delim != '\0') { 1138*7c478bd9Sstevel@tonic-gate (void) putc(' ', output); 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate if (keyword[c].delim == '(') { 1141*7c478bd9Sstevel@tonic-gate (void) putc('(', output); 1142*7c478bd9Sstevel@tonic-gate } 1143*7c478bd9Sstevel@tonic-gate } else { 1144*7c478bd9Sstevel@tonic-gate (void) putc((int)c, output); 1145*7c478bd9Sstevel@tonic-gate } 1146*7c478bd9Sstevel@tonic-gate ++cp; 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate } while (*(cp + 1) == '\0' && (cp = readblock()) != NULL); 1149*7c478bd9Sstevel@tonic-gate blockp = cp; 1150*7c478bd9Sstevel@tonic-gate } 1151*7c478bd9Sstevel@tonic-gate 1152*7c478bd9Sstevel@tonic-gate /* put the rest of the cross-reference line into the string */ 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate void 1155*7c478bd9Sstevel@tonic-gate getstring(char *s) 1156*7c478bd9Sstevel@tonic-gate { 1157*7c478bd9Sstevel@tonic-gate char *cp; 1158*7c478bd9Sstevel@tonic-gate unsigned c; 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate setmark('\n'); 1161*7c478bd9Sstevel@tonic-gate cp = blockp; 1162*7c478bd9Sstevel@tonic-gate do { 1163*7c478bd9Sstevel@tonic-gate while ((c = *cp) != '\n') { 1164*7c478bd9Sstevel@tonic-gate if (c & 0200) { 1165*7c478bd9Sstevel@tonic-gate c &= 0177; 1166*7c478bd9Sstevel@tonic-gate *s++ = dichar1[c / 8]; 1167*7c478bd9Sstevel@tonic-gate *s++ = dichar2[c & 7]; 1168*7c478bd9Sstevel@tonic-gate } else { 1169*7c478bd9Sstevel@tonic-gate *s++ = (char)c; 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate ++cp; 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate } while (*(cp + 1) == '\0' && (cp = readblock()) != NULL); 1174*7c478bd9Sstevel@tonic-gate blockp = cp; 1175*7c478bd9Sstevel@tonic-gate *s = '\0'; 1176*7c478bd9Sstevel@tonic-gate } 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate /* scan past the next occurence of this character in the cross-reference */ 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate char * 1181*7c478bd9Sstevel@tonic-gate scanpast(int c) 1182*7c478bd9Sstevel@tonic-gate { 1183*7c478bd9Sstevel@tonic-gate char *cp; 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate setmark(c); 1186*7c478bd9Sstevel@tonic-gate cp = blockp; 1187*7c478bd9Sstevel@tonic-gate do { /* innermost loop optimized to only one test */ 1188*7c478bd9Sstevel@tonic-gate while (*cp != c) { 1189*7c478bd9Sstevel@tonic-gate ++cp; 1190*7c478bd9Sstevel@tonic-gate } 1191*7c478bd9Sstevel@tonic-gate } while (*(cp + 1) == '\0' && (cp = readblock()) != NULL); 1192*7c478bd9Sstevel@tonic-gate blockp = cp; 1193*7c478bd9Sstevel@tonic-gate if (cp != NULL) { 1194*7c478bd9Sstevel@tonic-gate skiprefchar(); /* skip the found character */ 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate return (blockp); 1197*7c478bd9Sstevel@tonic-gate } 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate /* read a block of the cross-reference */ 1200*7c478bd9Sstevel@tonic-gate 1201*7c478bd9Sstevel@tonic-gate char * 1202*7c478bd9Sstevel@tonic-gate readblock(void) 1203*7c478bd9Sstevel@tonic-gate { 1204*7c478bd9Sstevel@tonic-gate /* read the next block */ 1205*7c478bd9Sstevel@tonic-gate blocklen = read(symrefs, block, BUFSIZ); 1206*7c478bd9Sstevel@tonic-gate blockp = block; 1207*7c478bd9Sstevel@tonic-gate 1208*7c478bd9Sstevel@tonic-gate /* add the search character and end-of-block mark */ 1209*7c478bd9Sstevel@tonic-gate block[blocklen] = blockmark; 1210*7c478bd9Sstevel@tonic-gate block[blocklen + 1] = '\0'; 1211*7c478bd9Sstevel@tonic-gate 1212*7c478bd9Sstevel@tonic-gate /* return NULL on end-of-file */ 1213*7c478bd9Sstevel@tonic-gate if (blocklen == 0) { 1214*7c478bd9Sstevel@tonic-gate blockp = NULL; 1215*7c478bd9Sstevel@tonic-gate } else { 1216*7c478bd9Sstevel@tonic-gate ++blocknumber; 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate return (blockp); 1219*7c478bd9Sstevel@tonic-gate } 1220*7c478bd9Sstevel@tonic-gate 1221*7c478bd9Sstevel@tonic-gate /* seek to the database offset */ 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate long 1224*7c478bd9Sstevel@tonic-gate dbseek(long offset) 1225*7c478bd9Sstevel@tonic-gate { 1226*7c478bd9Sstevel@tonic-gate long n; 1227*7c478bd9Sstevel@tonic-gate int rc = 0; 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate if ((n = offset / BUFSIZ) != blocknumber) { 1230*7c478bd9Sstevel@tonic-gate if ((rc = lseek(symrefs, n * BUFSIZ, 0)) == -1) { 1231*7c478bd9Sstevel@tonic-gate myperror("Lseek failed"); 1232*7c478bd9Sstevel@tonic-gate (void) sleep(3); 1233*7c478bd9Sstevel@tonic-gate return (rc); 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate (void) readblock(); 1236*7c478bd9Sstevel@tonic-gate blocknumber = n; 1237*7c478bd9Sstevel@tonic-gate } 1238*7c478bd9Sstevel@tonic-gate blockp = block + offset % BUFSIZ; 1239*7c478bd9Sstevel@tonic-gate return (rc); 1240*7c478bd9Sstevel@tonic-gate } 1241*7c478bd9Sstevel@tonic-gate 1242*7c478bd9Sstevel@tonic-gate /* convert the string to lower case */ 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate static char * 1245*7c478bd9Sstevel@tonic-gate strtolower(char *s) 1246*7c478bd9Sstevel@tonic-gate { 1247*7c478bd9Sstevel@tonic-gate static char buf[PATLEN + 1]; 1248*7c478bd9Sstevel@tonic-gate char *lp = buf; 1249*7c478bd9Sstevel@tonic-gate 1250*7c478bd9Sstevel@tonic-gate while (*s != '\0') { 1251*7c478bd9Sstevel@tonic-gate /* 1252*7c478bd9Sstevel@tonic-gate * note: s in not incremented in this line because the BSD 1253*7c478bd9Sstevel@tonic-gate * compatibility tolower macro evaluates its argument twice 1254*7c478bd9Sstevel@tonic-gate */ 1255*7c478bd9Sstevel@tonic-gate *lp++ = tolower(*s); 1256*7c478bd9Sstevel@tonic-gate ++s; 1257*7c478bd9Sstevel@tonic-gate } 1258*7c478bd9Sstevel@tonic-gate *lp = '\0'; 1259*7c478bd9Sstevel@tonic-gate return (buf); 1260*7c478bd9Sstevel@tonic-gate } 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate /* if needed, convert a relative path to a full path */ 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate static char * 1265*7c478bd9Sstevel@tonic-gate filepath(char *file) 1266*7c478bd9Sstevel@tonic-gate { 1267*7c478bd9Sstevel@tonic-gate static char path[PATHLEN + 1]; 1268*7c478bd9Sstevel@tonic-gate int i; 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate if (*file != '/') { 1271*7c478bd9Sstevel@tonic-gate 1272*7c478bd9Sstevel@tonic-gate /* if same file as last time, return the same path */ 1273*7c478bd9Sstevel@tonic-gate if (strequal(file, lastfilepath)) { 1274*7c478bd9Sstevel@tonic-gate return (path); 1275*7c478bd9Sstevel@tonic-gate } 1276*7c478bd9Sstevel@tonic-gate (void) strcpy(lastfilepath, file); 1277*7c478bd9Sstevel@tonic-gate 1278*7c478bd9Sstevel@tonic-gate /* if requested, prepend a path to a relative file path */ 1279*7c478bd9Sstevel@tonic-gate if (prependpath != NULL) { 1280*7c478bd9Sstevel@tonic-gate (void) sprintf(path, "%s/%s", prependpath, file); 1281*7c478bd9Sstevel@tonic-gate return (path); 1282*7c478bd9Sstevel@tonic-gate } 1283*7c478bd9Sstevel@tonic-gate /* 1284*7c478bd9Sstevel@tonic-gate * if the database was built with a view path, return a 1285*7c478bd9Sstevel@tonic-gate * full path so "cscope -d -f" does not have to be called 1286*7c478bd9Sstevel@tonic-gate * from the build directory with the same view path 1287*7c478bd9Sstevel@tonic-gate */ 1288*7c478bd9Sstevel@tonic-gate if (dbvpndirs > 1) { 1289*7c478bd9Sstevel@tonic-gate for (i = 0; i < dbvpndirs; i++) { 1290*7c478bd9Sstevel@tonic-gate (void) sprintf(path, 1291*7c478bd9Sstevel@tonic-gate "%s/%s", dbvpdirs[i], file); 1292*7c478bd9Sstevel@tonic-gate if (access(path, READ) != -1) { 1293*7c478bd9Sstevel@tonic-gate return (path); 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate } 1296*7c478bd9Sstevel@tonic-gate } 1297*7c478bd9Sstevel@tonic-gate (void) strcpy(path, file); /* for lastfilepath check */ 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate return (file); 1300*7c478bd9Sstevel@tonic-gate } 1301