11841Sroot #include <ctype.h> 21841Sroot #include <stdio.h> 31841Sroot #include <sys/types.h> 41841Sroot #include <sys/stat.h> 51841Sroot 62199Sroot #define boolean int 72199Sroot #define TRUE 1 82199Sroot #define FALSE 0 92199Sroot #define NIL 0 102199Sroot 111841Sroot /* 121841Sroot * Vfontedpr. 131841Sroot * 142199Sroot * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy) 151862Sroot * 161841Sroot */ 171862Sroot 181862Sroot #define STRLEN 10 /* length of strings introducing things */ 191862Sroot #define PNAMELEN 40 /* length of a function/procedure name */ 202199Sroot #define PSMAX 20 /* size of procedure name stacking */ 211862Sroot 222199Sroot /* regular expression routines */ 231862Sroot 242199Sroot char *expmatch(); /* match a string to an expression */ 252199Sroot char *STRNCMP(); /* a different kindof strncmp */ 262199Sroot char *convexp(); /* convert expression to internal form */ 271862Sroot 282199Sroot boolean isproc(); 291862Sroot 301862Sroot 312199Sroot char *ctime(); 321862Sroot 332199Sroot /* 342199Sroot * The state variables 352199Sroot */ 361862Sroot 372199Sroot boolean incomm; /* in a comment of the primary type */ 382199Sroot boolean instr; /* in a string constant */ 392199Sroot boolean inchr; /* in a string constant */ 402199Sroot boolean nokeyw = FALSE; /* no keywords being flagged */ 412199Sroot boolean index = FALSE; /* form an index */ 422199Sroot boolean filter = FALSE; /* act as a filter (like eqn) */ 432199Sroot boolean pass = FALSE; /* when acting as a filter, pass indicates 442199Sroot * whether we are currently processing 452199Sroot * input. 462199Sroot */ 472199Sroot boolean prccont; /* continue last procedure */ 482199Sroot int margin; 492199Sroot int psptr; /* the stack index of the current procedure */ 502199Sroot char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */ 512199Sroot int plstack[PSMAX]; /* the procedure nesting level stack */ 522199Sroot int blklevel; /* current nesting level */ 532199Sroot char *defsfile = "/usr/lib/vgrindefs"; /* name of language definitions file */ 542199Sroot char pname[BUFSIZ+1]; 551862Sroot 562199Sroot /* 572199Sroot * The language specific globals 582199Sroot */ 591862Sroot 602199Sroot char *language = "c"; /* the language indicator */ 612199Sroot char *l_keywds[BUFSIZ/2]; /* keyword table address */ 622199Sroot char *l_prcbeg; /* regular expr for procedure begin */ 632199Sroot char *l_combeg; /* string introducing a comment */ 642199Sroot char *l_comend; /* string ending a comment */ 652199Sroot char *l_blkbeg; /* string begining of a block */ 662199Sroot char *l_blkend; /* string ending a block */ 672199Sroot char *l_strbeg; /* delimiter for string constant */ 682199Sroot char *l_strend; /* delimiter for string constant */ 692199Sroot char *l_chrbeg; /* delimiter for character constant */ 702199Sroot char *l_chrend; /* delimiter for character constant */ 712199Sroot char l_escape; /* character used to escape characters */ 722199Sroot boolean l_toplex; /* procedures only defined at top lex level */ 731878Sroot 741862Sroot /* 752199Sroot * global variables also used by expmatch 761862Sroot */ 772199Sroot boolean _escaped; /* if last character was an escape */ 782199Sroot char *_start; /* start of the current string */ 792199Sroot boolean l_onecase; /* upper and lower case are equivalent */ 801862Sroot 812199Sroot #define ps(x) printf("%s", x) 821862Sroot 832199Sroot main(argc, argv) 842199Sroot int argc; 852199Sroot char *argv[]; 862199Sroot { 872199Sroot int lineno; 882199Sroot char *fname = ""; 892199Sroot char *ptr; 902199Sroot struct stat stbuf; 912199Sroot char buf[BUFSIZ]; 922199Sroot char strings[2 * BUFSIZ]; 932199Sroot char defs[2 * BUFSIZ]; 942199Sroot int needbp = 0; 951862Sroot 962199Sroot argc--, argv++; 972199Sroot do { 982199Sroot char *cp; 992199Sroot int i; 1001878Sroot 1012199Sroot if (argc > 0) { 1022199Sroot if (!strcmp(argv[0], "-h")) { 1032199Sroot if (argc == 1) { 1042199Sroot printf("'ds =H\n"); 1052199Sroot argc = 0; 1062199Sroot goto rest; 1072199Sroot } 1082199Sroot printf("'ds =H %s\n", argv[1]); 109*3393Spresott argc--, argv++; 110*3393Spresott argc--, argv++; 1112199Sroot if (argc > 0) 1122199Sroot continue; 1132199Sroot goto rest; 1142199Sroot } 1151862Sroot 1162199Sroot /* act as a filter like eqn */ 1172199Sroot if (!strcmp(argv[0], "-f")) { 1182199Sroot filter++; 1192199Sroot argv[0] = argv[argc-1]; 1202199Sroot argv[argc-1] = "-"; 1212199Sroot continue; 1222199Sroot } 1231862Sroot 1242199Sroot /* take input from the standard place */ 1252199Sroot if (!strcmp(argv[0], "-")) { 1262199Sroot argc = 0; 1272199Sroot goto rest; 1282199Sroot } 1291878Sroot 1302199Sroot /* build an index */ 1312199Sroot if (!strcmp(argv[0], "-x")) { 1322199Sroot index++; 1332199Sroot argv[0] = "-n"; 1342199Sroot } 1351841Sroot 1362199Sroot /* indicate no keywords */ 1372199Sroot if (!strcmp(argv[0], "-n")) { 1382199Sroot nokeyw++; 1392199Sroot argc--, argv++; 1402199Sroot continue; 1412199Sroot } 1421862Sroot 1432199Sroot /* specify the font size */ 1442199Sroot if (!strncmp(argv[0], "-s", 2)) { 1452199Sroot i = 0; 1462199Sroot cp = argv[0] + 2; 1472199Sroot while (*cp) 1482199Sroot i = i * 10 + (*cp++ - '0'); 1492199Sroot printf("'ps %d\n'vs %d\n", i, i+1); 1502199Sroot argc--, argv++; 1512199Sroot continue; 1522199Sroot } 1531841Sroot 1542199Sroot /* specify the language */ 1552199Sroot if (!strncmp(argv[0], "-l", 2)) { 1562199Sroot language = argv[0]+2; 1572199Sroot argc--, argv++; 1582199Sroot continue; 1592199Sroot } 1601841Sroot 1612199Sroot /* specify the language description file */ 1622199Sroot if (!strncmp(argv[0], "-d", 2)) { 1632199Sroot defsfile = argv[1]; 1642199Sroot argc--, argv++; 1652199Sroot argc--, argv++; 1662199Sroot continue; 1672199Sroot } 1681862Sroot 1692199Sroot /* open the file for input */ 1702199Sroot if (freopen(argv[0], "r", stdin) == NULL) { 1712199Sroot perror(argv[0]); 1722199Sroot exit(1); 1732199Sroot } 1742199Sroot if (index) 1752199Sroot printf("'ta 4i 4.25i 5.5iR\n'in .5i\n"); 1762199Sroot fname = argv[0]; 1772199Sroot argc--, argv++; 1782199Sroot } 1792199Sroot rest: 1801862Sroot 1812199Sroot /* 1822199Sroot * get the language definition from the defs file 1832199Sroot */ 1842199Sroot i = tgetent (defs, language, defsfile); 1852199Sroot if (i == 0) { 1862199Sroot fprintf (stderr, "no entry for language %s\n", language); 1872199Sroot exit (0); 1882199Sroot } else if (i < 0) { 1892199Sroot fprintf (stderr, "cannot find vgrindefs file %s\n", defsfile); 1902199Sroot exit (0); 1912199Sroot } 1922199Sroot cp = strings; 1932199Sroot if (tgetstr ("kw", &cp) == NIL) 1942199Sroot nokeyw = TRUE; 1952199Sroot else { 1962199Sroot char **cpp; 1971878Sroot 1982199Sroot cpp = l_keywds; 1992199Sroot cp = strings; 2002199Sroot while (*cp) { 2012199Sroot while (*cp == ' ' || *cp =='\t') 2022199Sroot *cp++ = NULL; 2032199Sroot if (*cp) 2042199Sroot *cpp++ = cp; 2052199Sroot while (*cp != ' ' && *cp != '\t' && *cp) 2062199Sroot cp++; 2072199Sroot } 2082199Sroot *cpp = NIL; 2092199Sroot } 2102199Sroot cp = buf; 2112199Sroot l_prcbeg = convexp (tgetstr ("pb", &cp)); 2122199Sroot cp = buf; 2132199Sroot l_combeg = convexp (tgetstr ("cb", &cp)); 2142199Sroot cp = buf; 2152199Sroot l_comend = convexp (tgetstr ("ce", &cp)); 2162199Sroot cp = buf; 2172199Sroot l_strbeg = convexp (tgetstr ("sb", &cp)); 2182199Sroot cp = buf; 2192199Sroot l_strend = convexp (tgetstr ("se", &cp)); 2202199Sroot cp = buf; 2212199Sroot l_blkbeg = convexp (tgetstr ("bb", &cp)); 2222199Sroot cp = buf; 2232199Sroot l_blkend = convexp (tgetstr ("be", &cp)); 2242199Sroot cp = buf; 2252199Sroot l_chrbeg = convexp (tgetstr ("lb", &cp)); 2262199Sroot cp = buf; 2272199Sroot l_chrend = convexp (tgetstr ("le", &cp)); 2282199Sroot l_escape = '\\'; 2292199Sroot l_onecase = tgetflag ("oc"); 2302199Sroot l_toplex = tgetflag ("tl"); 2312199Sroot /* initialize the program */ 2321878Sroot 2332199Sroot incomm = FALSE; 2342199Sroot instr = FALSE; 2352199Sroot inchr = FALSE; 2362199Sroot _escaped = FALSE; 2372199Sroot blklevel = 0; 2382199Sroot for (psptr=0; psptr<PSMAX; psptr++) { 2392199Sroot pstack[psptr][0] = NULL; 2402199Sroot plstack[psptr] = 0; 2412199Sroot } 2422199Sroot psptr = -1; 2432199Sroot ps("'-F\n"); 2442199Sroot if (!filter) { 2452199Sroot printf(".ds =F %s\n", fname); 2462199Sroot fstat(fileno(stdin), &stbuf); 2472199Sroot cp = ctime(&stbuf.st_mtime); 2482199Sroot cp[16] = '\0'; 2492199Sroot cp[24] = '\0'; 2502199Sroot printf(".ds =M %s %s\n", cp+4, cp+20); 251*3393Spresott ps("'wh 0 vH\n"); 252*3393Spresott ps("'wh -1i vF\n"); 2532199Sroot } 2542199Sroot if (needbp) { 2552199Sroot needbp = 0; 2562199Sroot printf(".()\n"); 2572199Sroot printf(".bp\n"); 2582199Sroot } 2591878Sroot 2602199Sroot /* 2612199Sroot * MAIN LOOP!!! 2622199Sroot */ 2632199Sroot while (fgets(buf, sizeof buf, stdin) != NULL) { 2642199Sroot if (buf[0] == '\f') { 2652199Sroot printf(".bp\n"); 2662199Sroot } 2672199Sroot if (buf[0] == '.') { 2682199Sroot printf("%s", buf); 2692199Sroot if (!strncmp (buf+1, "vS", 2)) 2702199Sroot pass = TRUE; 2712199Sroot if (!strncmp (buf+1, "vE", 2)) 2722199Sroot pass = FALSE; 2732199Sroot continue; 2742199Sroot } 2752199Sroot prccont = FALSE; 2762199Sroot if (!filter || pass) 2772199Sroot putScp(buf); 2782199Sroot else 2792199Sroot printf("%s", buf); 2802199Sroot if (prccont && (psptr >= 0)) { 2812199Sroot ps("'FC "); 2822199Sroot ps(pstack[psptr]); 2832199Sroot ps("\n"); 2842199Sroot } 2852199Sroot #ifdef DEBUG 2862199Sroot printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr); 2872199Sroot #endif 2882199Sroot margin = 0; 2892199Sroot } 2902199Sroot needbp = 1; 2912199Sroot } while (argc > 0); 2922199Sroot exit(0); 2931841Sroot } 2941841Sroot 2951841Sroot #define isidchr(c) (isalnum(c) || (c) == '_') 2961841Sroot 2971841Sroot putScp(os) 2982199Sroot char *os; 2991841Sroot { 3002199Sroot register char *s = os; /* pointer to unmatched string */ 3012199Sroot char dummy[BUFSIZ]; /* dummy to be used by expmatch */ 3022199Sroot char *comptr; /* end of a comment delimiter */ 3032199Sroot char *strptr; /* end of a string delimiter */ 3042199Sroot char *chrptr; /* end of a character const delimiter */ 3052199Sroot char *blksptr; /* end of a lexical block start */ 3062199Sroot char *blkeptr; /* end of a lexical block end */ 3071841Sroot 3082199Sroot _start = os; /* remember the start for expmatch */ 3092199Sroot _escaped = FALSE; 3102199Sroot if (nokeyw || incomm || instr) 3112199Sroot goto skip; 3122199Sroot if (isproc(s)) { 3132199Sroot ps("'FN "); 3142199Sroot ps(pname); 3152293Sroot ps("\n"); 3162199Sroot if (psptr < PSMAX) { 3172199Sroot ++psptr; 3182199Sroot strncpy (pstack[psptr], pname, PNAMELEN); 3192199Sroot pstack[psptr][PNAMELEN] = NULL; 3202199Sroot plstack[psptr] = blklevel; 3212199Sroot } 3222199Sroot } 3231841Sroot skip: 3242199Sroot do { 3252199Sroot /* check for string, comment, blockstart, etc */ 3262199Sroot if (!incomm && !instr && !inchr) { 3272199Sroot 3282199Sroot blkeptr = expmatch (s, l_blkend, dummy); 3292199Sroot blksptr = expmatch (s, l_blkbeg, dummy); 3302199Sroot comptr = expmatch (s, l_combeg, dummy); 3312199Sroot strptr = expmatch (s, l_strbeg, dummy); 3322199Sroot chrptr = expmatch (s, l_chrbeg, dummy); 3332199Sroot 3342199Sroot /* start of a comment? */ 3352199Sroot if (comptr != NIL) 3362199Sroot if ((comptr < strptr || strptr == NIL) 3372199Sroot && (comptr < chrptr || chrptr == NIL) 3382199Sroot && (comptr < blksptr || blksptr == NIL) 3392199Sroot && (comptr < blkeptr || blkeptr == NIL)) { 3402199Sroot putKcp (s, comptr-1, FALSE); 3412199Sroot s = comptr; 3422199Sroot incomm = TRUE; 3432199Sroot if (s != os) 3442199Sroot ps ("\\c"); 3452199Sroot ps ("\\c\n'+C\n"); 3462199Sroot continue; 3471841Sroot } 3481878Sroot 3492199Sroot /* start of a string? */ 3502199Sroot if (strptr != NIL) 3512199Sroot if ((strptr < chrptr || chrptr == NIL) 3522212Sroot && (strptr < blksptr || blksptr == NIL) 3532212Sroot && (strptr < blkeptr || blkeptr == NIL)) { 3542199Sroot putKcp (s, strptr-1, FALSE); 3552199Sroot s = strptr; 3562199Sroot instr = TRUE; 3572199Sroot continue; 3582199Sroot } 3591878Sroot 3602199Sroot /* start of a character string? */ 3612199Sroot if (chrptr != NIL) 3622212Sroot if ((chrptr < blksptr || blksptr == NIL) 3632212Sroot && (chrptr < blkeptr || blkeptr == NIL)) { 3642199Sroot putKcp (s, chrptr-1, FALSE); 3652199Sroot s = chrptr; 3662199Sroot inchr = TRUE; 3672199Sroot continue; 3681841Sroot } 3691878Sroot 3702199Sroot /* end of a lexical block */ 3712199Sroot if (blkeptr != NIL) { 3722199Sroot if (blkeptr < blksptr || blksptr == NIL) { 3732199Sroot putKcp (s, blkeptr - 1, FALSE); 3742199Sroot s = blkeptr; 3752199Sroot blklevel--; 3762199Sroot if (psptr >= 0 && plstack[psptr] >= blklevel) { 3771878Sroot 3782199Sroot /* end of current procedure */ 3791841Sroot if (s != os) 3802199Sroot ps ("\\c"); 3812199Sroot ps ("\\c\n'-F\n"); 3822199Sroot blklevel = plstack[psptr]; 3831878Sroot 3842199Sroot /* see if we should print the last proc name */ 3852199Sroot if (--psptr >= 0) 3862199Sroot prccont = TRUE; 3872199Sroot else 3882199Sroot psptr = -1; 3892199Sroot } 3902199Sroot continue; 3911841Sroot } 3922199Sroot } 3931878Sroot 3942199Sroot /* start of a lexical block */ 3952199Sroot if (blksptr != NIL) { 3962199Sroot putKcp (s, blksptr - 1, FALSE); 3972199Sroot s = blksptr; 3982199Sroot blklevel++; 3992199Sroot continue; 4002199Sroot } 4012199Sroot 4022199Sroot /* check for end of comment */ 4032199Sroot } else if (incomm) { 4042199Sroot if ((comptr = expmatch (s, l_comend, dummy)) != NIL) { 4052199Sroot putKcp (s, comptr-1, TRUE); 4062199Sroot s = comptr; 4072199Sroot incomm = FALSE; 4082199Sroot ps("\\c\n'-C\n"); 4092199Sroot continue; 4102199Sroot } else { 4112199Sroot putKcp (s, s + strlen(s) -1); 4122199Sroot s = s + strlen(s); 4132199Sroot continue; 4142199Sroot } 4152199Sroot 4162199Sroot /* check for end of string */ 4172199Sroot } else if (instr) { 4182199Sroot if ((strptr = expmatch (s, l_strend, dummy)) != NIL) { 4192199Sroot putKcp (s, strptr-1, TRUE); 4202199Sroot s = strptr; 4212199Sroot instr = FALSE; 4222199Sroot continue; 4232199Sroot } else { 4242199Sroot putKcp (s, s+strlen(s)-1, TRUE); 4252199Sroot s = s + strlen(s); 4262199Sroot continue; 4272199Sroot } 4282199Sroot 4292199Sroot /* check for end of character string */ 4302199Sroot } else if (inchr) { 4312199Sroot if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) { 4322199Sroot putKcp (s, chrptr-1, TRUE); 4332199Sroot s = chrptr; 4342199Sroot inchr = FALSE; 4352199Sroot continue; 4362199Sroot } else { 4372199Sroot putKcp (s, s+strlen(s)-1, TRUE); 4382199Sroot s = s + strlen(s); 4392199Sroot continue; 4402199Sroot } 4411841Sroot } 4422199Sroot 4432199Sroot /* print out the line */ 4442199Sroot putKcp (s, s + strlen(s) -1, FALSE); 4452199Sroot s = s + strlen(s); 4462199Sroot } while (*s); 4471841Sroot } 4481841Sroot 4492199Sroot putKcp (start, end, force) 4502199Sroot char *start; /* start of string to write */ 4512199Sroot char *end; /* end of string to write */ 4522199Sroot boolean force; /* true if we should force nokeyw */ 4532199Sroot { 4542199Sroot int i; 4552320Sroot int xfld = 0; 4562199Sroot 4572199Sroot while (start <= end) { 4582320Sroot if (index) { 4592320Sroot if (*start == ' ' || *start == '\t') { 4602320Sroot if (xfld == 0) 4612320Sroot printf(""); 4622320Sroot printf("\t"); 4632320Sroot xfld = 1; 4642320Sroot while (*start == ' ' || *start == '\t') 4652320Sroot start++; 4662320Sroot continue; 4672320Sroot } 4682320Sroot } 4692199Sroot 4702199Sroot /* take care of nice tab stops */ 4712199Sroot if (*start == '\t') { 4722199Sroot while (*start == '\t') 4732199Sroot start++; 4742199Sroot i = tabs(_start, start) - margin / 8; 4752199Sroot printf("\\h'|%dn'", i * 10 + 1 - margin % 8); 4762199Sroot continue; 4772199Sroot } 4782199Sroot 4792199Sroot if (!nokeyw && !force) 4802199Sroot if ((*start == '#' || isidchr(*start)) 4812199Sroot && (start == _start || !isidchr(start[-1]))) { 4822199Sroot i = iskw(start); 4832199Sroot if (i > 0) { 4842199Sroot ps("\\*(+K"); 4852199Sroot do 4862199Sroot putcp(*start++); 4872199Sroot while (--i > 0); 4882199Sroot ps("\\*(-K"); 4892199Sroot continue; 4902199Sroot } 4912199Sroot } 4922199Sroot 4932199Sroot putcp (*start++); 4942199Sroot } 4952199Sroot } 4962199Sroot 4972199Sroot 4981841Sroot tabs(s, os) 4992199Sroot char *s, *os; 5001841Sroot { 5011841Sroot 5022199Sroot return (width(s, os) / 8); 5031841Sroot } 5041841Sroot 5051841Sroot width(s, os) 5061841Sroot register char *s, *os; 5071841Sroot { 5081841Sroot register int i = 0; 5091841Sroot 5101841Sroot while (s < os) { 5111841Sroot if (*s == '\t') { 5121841Sroot i = (i + 8) &~ 7; 5131841Sroot s++; 5141841Sroot continue; 5151841Sroot } 5161841Sroot if (*s < ' ') 5171841Sroot i += 2; 5181841Sroot else 5191841Sroot i++; 5201841Sroot s++; 5211841Sroot } 5221841Sroot return (i); 5231841Sroot } 5241841Sroot 5251841Sroot putcp(c) 5261841Sroot register int c; 5271841Sroot { 5281841Sroot 5291841Sroot switch(c) { 5301841Sroot 5312199Sroot case 0: 5322199Sroot break; 5332199Sroot 5342199Sroot case '\f': 5352199Sroot break; 5362199Sroot 5371841Sroot case '{': 5381841Sroot ps("\\*(+K{\\*(-K"); 5391841Sroot break; 5401841Sroot 5411841Sroot case '}': 5421841Sroot ps("\\*(+K}\\*(-K"); 5431841Sroot break; 5441841Sroot 5451841Sroot case '\\': 5461841Sroot ps("\\e"); 5471841Sroot break; 5481841Sroot 5491841Sroot case '_': 5501841Sroot ps("\\*_"); 5511841Sroot break; 5521841Sroot 5531841Sroot case '-': 5541841Sroot ps("\\*-"); 5551841Sroot break; 5561841Sroot 5571841Sroot case '`': 5581841Sroot ps("\\`"); 5591841Sroot break; 5601841Sroot 5611841Sroot case '\'': 5621841Sroot ps("\\'"); 5631841Sroot break; 5641841Sroot 5651841Sroot case '.': 5661841Sroot ps("\\&."); 5671841Sroot break; 5681841Sroot 5692418Sroot case '*': 5702418Sroot ps("\\fI*\\fP"); 5712418Sroot break; 5722418Sroot 5732199Sroot case '/': 5742418Sroot ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP"); 5752199Sroot break; 5762199Sroot 5771841Sroot default: 5781841Sroot if (c < 040) 5791841Sroot putchar('^'), c |= '@'; 5801841Sroot case '\t': 5811841Sroot case '\n': 5821841Sroot putchar(c); 5831841Sroot } 5841841Sroot } 5851841Sroot 5862199Sroot /* 5872199Sroot * look for a process beginning on this line 5881878Sroot */ 5892199Sroot boolean 5902199Sroot isproc(s) 5912199Sroot char *s; 5921878Sroot { 5932199Sroot pname[0] = NULL; 5942199Sroot if (!l_toplex || blklevel == 0) 5952199Sroot if (expmatch (s, l_prcbeg, pname) != NIL) { 5962199Sroot return (TRUE); 5972199Sroot } 5982199Sroot return (FALSE); 5991878Sroot } 6001878Sroot 6012199Sroot 6021878Sroot /* iskw - check to see if the next word is a keyword 6031878Sroot */ 6041878Sroot 6051841Sroot iskw(s) 6061841Sroot register char *s; 6071841Sroot { 6082199Sroot register char **ss = l_keywds; 6091841Sroot register int i = 1; 6101841Sroot register char *cp = s; 6111841Sroot 6121841Sroot while (++cp, isidchr(*cp)) 6131841Sroot i++; 6141841Sroot while (cp = *ss++) 6152199Sroot if (!STRNCMP(s,cp,i) && !isidchr(cp[i])) 6161841Sroot return (i); 6171841Sroot return (0); 6181841Sroot } 619