vfontedpr.c revision 283:f7518827bcbb
1169695Skan/* 2169695Skan * Copyright (c) 1980 Regents of the University of California. 3169695Skan * All rights reserved. The Berkeley software License Agreement 4169695Skan * specifies the terms and conditions for redistribution. 5169695Skan */ 6169695Skan 7169695Skan#pragma ident "%Z%%M% %I% %E% SMI" 8169695Skan 9169695Skan#include <ctype.h> 10169695Skan#include <stdio.h> 11169695Skan#include <sys/types.h> 12169695Skan#include <sys/stat.h> 13169695Skan#include <locale.h> 14169695Skan#include <euc.h> 15169695Skan#include <stdlib.h> 16169695Skan 17169695Skan#define boolean int 18169695Skan#define TRUE 1 19169695Skan#define FALSE 0 20169695Skan#define NIL 0 21169695Skan#define STANDARD 0 22169695Skan#define ALTERNATE 1 23169695Skan 24169695Skan/* 25169695Skan * Vfontedpr. 26169695Skan * 27169695Skan * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy) 28169695Skan * 29169695Skan */ 30169695Skan 31169695Skan#define STRLEN 10 /* length of strings introducing things */ 32169695Skan#define PNAMELEN 40 /* length of a function/procedure name */ 33169695Skan#define PSMAX 20 /* size of procedure name stacking */ 34169695Skan 35169695Skan/* regular expression routines */ 36169695Skan 37169695Skanchar *expmatch(); /* match a string to an expression */ 38169695Skanchar *STRNCMP(); /* a different kind of strncmp */ 39169695Skanchar *convexp(); /* convert expression to internal form */ 40169695Skan 41169695Skanchar *tgetstr(); /* extract a string-valued capability */ 42169695Skanboolean isproc(); 43169695Skanchar *ctime(); 44169695Skanchar *strchr(); 45169695Skan 46169695Skan/* 47169695Skan * The state variables 48169695Skan */ 49169695Skan 50169695Skanboolean incomm; /* in a comment of the primary type */ 51169695Skanboolean instr; /* in a string constant */ 52169695Skanboolean inchr; /* in a string constant */ 53169695Skanboolean nokeyw = FALSE; /* no keywords being flagged */ 54169695Skanboolean doindex = FALSE; /* form an index */ 55169695Skanboolean twocol = FALSE; /* in two-column mode */ 56169695Skanboolean filter = FALSE; /* act as a filter (like eqn) */ 57169695Skanboolean pass = FALSE; /* when acting as a filter, pass indicates 58169695Skan * whether we are currently processing 59169695Skan * input. 60169695Skan */ 61169695Skanboolean prccont; /* continue last procedure */ 62169695Skanint comtype; /* type of comment */ 63169695Skanint margin; 64169695Skanint psptr; /* the stack index of the current procedure */ 65169695Skanchar pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */ 66169695Skanint plstack[PSMAX]; /* the procedure nesting level stack */ 67169695Skanint blklevel; /* current nesting level */ 68169695Skanint prclevel; /* nesting level at which procedure definitions 69169695Skan may be found, -1 if none currently valid 70169695Skan (meaningful only if l_prclevel is true) */ 71169695Skanchar *defsfile = "/usr/lib/vgrindefs"; /* name of language definitions file */ 72169695Skanchar pname[BUFSIZ+1]; 73169695Skan 74169695Skan/* 75169695Skan * The language specific globals 76169695Skan */ 77169695Skan 78169695Skanchar *language = "c"; /* the language indicator */ 79169695Skanchar *l_keywds[BUFSIZ/2]; /* keyword table address */ 80169695Skanchar *l_prcbeg; /* regular expr for procedure begin */ 81169695Skanchar *l_combeg; /* string introducing a comment */ 82169695Skanchar *l_comend; /* string ending a comment */ 83169695Skanchar *l_acmbeg; /* string introducing a comment */ 84169695Skanchar *l_acmend; /* string ending a comment */ 85169695Skanchar *l_blkbeg; /* string begining of a block */ 86169695Skanchar *l_blkend; /* string ending a block */ 87169695Skanchar *l_strbeg; /* delimiter for string constant */ 88169695Skanchar *l_strend; /* delimiter for string constant */ 89169695Skanchar *l_chrbeg; /* delimiter for character constant */ 90169695Skanchar *l_chrend; /* delimiter for character constant */ 91169695Skanchar *l_prcenable; /* re indicating that procedure definitions 92169695Skan can be found in the next lexical level -- 93169695Skan kludge for lisp-like languages that use 94169695Skan something like 95169695Skan (defun (proc ...) 96169695Skan (proc ...) 97169695Skan ) 98169695Skan to define procedures */ 99169695Skanchar l_escape; /* character used to escape characters */ 100169695Skanboolean l_toplex; /* procedures only defined at top lex level */ 101169695Skanboolean l_prclevel; /* procedure definitions valid only within 102169695Skan the nesting level indicated by the px 103169695Skan (l_prcenable) capability */ 104169695Skan 105169695Skan/* 106169695Skan * for the benefit of die-hards who aren't convinced that tabs 107169695Skan * occur every eight columns 108169695Skan */ 109169695Skanshort tabsize = 8; 110169695Skan 111169695Skan/* 112169695Skan * global variables also used by expmatch 113169695Skan */ 114169695Skanboolean _escaped; /* if last character was an escape */ 115169695Skanchar *Start; /* start of the current string */ 116169695Skanboolean l_onecase; /* upper and lower case are equivalent */ 117169695Skanchar *l_idchars; /* characters legal in identifiers in addition 118169695Skan to letters and digits (default "_") */ 119169695Skan 120169695Skanstatic void putcp(int c); 121169695Skanstatic int width(char *s, char *os); 122169695Skanstatic int tabs(char *s, char *os); 123169695Skanstatic void putKcp(char *start, char *end, boolean force); 124169695Skanstatic void putScp(char *os); 125169695Skanstatic int iskw(char *s); 126169695Skan 127169695Skan/* 128169695Skan * The code below emits troff macros and directives that consume part of the 129169695Skan * troff macro and register space. See tmac.vgrind for an enumeration of 130169695Skan * these macros and registers. 131169695Skan */ 132169695Skan 133169695Skanint 134169695Skanmain(int argc, char *argv[]) 135169695Skan{ 136169695Skan FILE *in; 137169695Skan char *fname; 138169695Skan struct stat stbuf; 139169695Skan char buf[BUFSIZ]; 140169695Skan char idbuf[256]; /* enough for all 8 bit chars */ 141169695Skan char strings[2 * BUFSIZ]; 142169695Skan char defs[2 * BUFSIZ]; 143169695Skan int needbp = 0; 144169695Skan int i; 145169695Skan char *cp; 146169695Skan 147169695Skan (void) setlocale(LC_ALL, ""); 148169695Skan#if !defined(TEXT_DOMAIN) 149169695Skan#define TEXT_DOMAIN "SYS_TEST" 150169695Skan#endif 151169695Skan (void) textdomain(TEXT_DOMAIN); 152169695Skan 153169695Skan /* 154169695Skan * Dump the name by which we were invoked. 155169695Skan */ 156169695Skan argc--, argv++; 157169695Skan 158169695Skan /* 159169695Skan * Process arguments. For the sake of compatibility with older versions 160169695Skan * of the program, the syntax accepted below is very idiosyncratic. Some 161169695Skan * options require space between the option and its argument; others 162169695Skan * disallow it. No options may be bundled together. 163169695Skan * 164169695Skan * Actually, there is one incompatibility. Files and options formerly 165169695Skan * could be arbitrarily intermixed, but this is no longer allowed. (This 166169695Skan * possiblity was never documented.) 167169695Skan */ 168169695Skan while (argc > 0 && *argv[0] == '-') { 169169695Skan switch (*(cp = argv[0] + 1)) { 170169695Skan 171169695Skan case '\0': /* - */ 172169695Skan /* Take input from stdin. */ 173169695Skan /* 174169695Skan * This option implies the end of the flag arguments. Leave the 175169695Skan * "-" in place for the file processing code to see. 176169695Skan */ 177169695Skan goto flagsdone; 178169695Skan 179169695Skan case '2': /* -2 */ 180169695Skan /* Enter two column mode. */ 181169695Skan twocol = 1; 182169695Skan printf("'nr =2 1\n"); 183169695Skan break; 184169695Skan 185169695Skan case 'd': /* -d <defs-file> */ 186169695Skan /* Specify the language description file. */ 187169695Skan defsfile = argv[1]; 188169695Skan argc--, argv++; 189169695Skan break; 190169695Skan 191169695Skan case 'f': /* -f */ 192169695Skan /* Act as a filter like eqn. */ 193169695Skan filter = 1; 194169695Skan /* 195169695Skan * Slide remaining arguments down one position and postpend "-", 196169695Skan * to force reading from stdin. 197169695Skan */ 198169695Skan for (i = 0; i < argc - 1; i++) 199169695Skan argv[i] = argv[i + 1]; 200169695Skan argv[argc - 1] = "-"; 201169695Skan continue; 202169695Skan 203169695Skan case 'h': /* -h [header] */ 204169695Skan /* Specify header string. */ 205169695Skan if (argc == 1) { 206169695Skan printf("'ds =H\n"); 207169695Skan break; 208169695Skan } 209169695Skan printf("'ds =H %s\n", argv[1]); 210169695Skan argc--, argv++; 211169695Skan break; 212169695Skan 213169695Skan case 'l': /* -l<language> */ 214169695Skan /* Specify the language. */ 215169695Skan language = cp + 1; 216169695Skan break; 217169695Skan 218169695Skan case 'n': /* -n */ 219169695Skan /* Indicate no keywords. */ 220169695Skan nokeyw = 1; 221169695Skan break; 222169695Skan 223169695Skan case 's': /* -s<size> */ 224169695Skan /* Specify the font size. */ 225169695Skan i = 0; 226169695Skan cp++; 227169695Skan while (*cp) 228169695Skan i = i * 10 + (*cp++ - '0'); 229169695Skan printf("'nr vP %d\n", i); 230169695Skan break; 231169695Skan 232169695Skan case 't': /* -t */ 233169695Skan /* Specify a nondefault tab size. */ 234169695Skan tabsize = 4; 235169695Skan break; 236169695Skan 237169695Skan case 'x': /* -x */ 238169695Skan /* Build an index. */ 239169695Skan doindex = 1; 240169695Skan /* This option implies "-n" as well; turn it on. */ 241169695Skan argv[0] = "-n"; 242169695Skan continue; 243169695Skan } 244169695Skan 245169695Skan /* Advance to next argument. */ 246169695Skan argc--, argv++; 247169695Skan } 248169695Skan 249169695Skanflagsdone: 250169695Skan 251169695Skan /* 252169695Skan * Get the language definition from the defs file. 253169695Skan */ 254169695Skan i = tgetent (defs, language, defsfile); 255169695Skan if (i == 0) { 256169695Skan fprintf (stderr, gettext("no entry for language %s\n"), language); 257169695Skan exit (0); 258169695Skan } else if (i < 0) { 259169695Skan fprintf (stderr, gettext("cannot find vgrindefs file %s\n"), defsfile); 260169695Skan exit (0); 261169695Skan } 262169695Skan cp = strings; 263169695Skan if (tgetstr ("kw", &cp) == NIL) 264169695Skan nokeyw = TRUE; 265169695Skan else { 266169695Skan char **cpp; 267169695Skan 268169695Skan cpp = l_keywds; 269169695Skan cp = strings; 270169695Skan while (*cp) { 271169695Skan while (*cp == ' ' || *cp =='\t') 272169695Skan *cp++ = NULL; 273169695Skan if (*cp) 274169695Skan *cpp++ = cp; 275169695Skan while (*cp != ' ' && *cp != '\t' && *cp) 276169695Skan cp++; 277169695Skan } 278169695Skan *cpp = NIL; 279169695Skan } 280169695Skan cp = buf; 281169695Skan l_prcbeg = convexp (tgetstr ("pb", &cp)); 282169695Skan cp = buf; 283169695Skan l_combeg = convexp (tgetstr ("cb", &cp)); 284169695Skan cp = buf; 285169695Skan l_comend = convexp (tgetstr ("ce", &cp)); 286169695Skan cp = buf; 287169695Skan l_acmbeg = convexp (tgetstr ("ab", &cp)); 288169695Skan cp = buf; 289169695Skan l_acmend = convexp (tgetstr ("ae", &cp)); 290169695Skan cp = buf; 291169695Skan l_strbeg = convexp (tgetstr ("sb", &cp)); 292169695Skan cp = buf; 293169695Skan l_strend = convexp (tgetstr ("se", &cp)); 294169695Skan cp = buf; 295169695Skan l_blkbeg = convexp (tgetstr ("bb", &cp)); 296169695Skan cp = buf; 297169695Skan l_blkend = convexp (tgetstr ("be", &cp)); 298169695Skan cp = buf; 299169695Skan l_chrbeg = convexp (tgetstr ("lb", &cp)); 300169695Skan cp = buf; 301169695Skan l_chrend = convexp (tgetstr ("le", &cp)); 302169695Skan cp = buf; 303169695Skan l_prcenable = convexp (tgetstr ("px", &cp)); 304169695Skan cp = idbuf; 305169695Skan l_idchars = tgetstr ("id", &cp); 306169695Skan /* Set default, for compatibility with old version */ 307169695Skan if (l_idchars == NIL) 308169695Skan l_idchars = "_"; 309169695Skan l_escape = '\\'; 310169695Skan l_onecase = tgetflag ("oc"); 311169695Skan l_toplex = tgetflag ("tl"); 312169695Skan l_prclevel = tgetflag ("pl"); 313169695Skan 314169695Skan /* 315169695Skan * Emit a call to the initialization macro. If not in filter mode, emit a 316169695Skan * call to the vS macro, so that tmac.vgrind can uniformly assume that all 317169695Skan * program input is bracketed with vS-vE pairs. 318169695Skan */ 319169695Skan printf("'vI\n"); 320169695Skan if (!filter) 321169695Skan printf("'vS\n"); 322169695Skan 323169695Skan if (doindex) { 324169695Skan /* 325169695Skan * XXX: Hard-wired spacing information. This should probably turn 326169695Skan * into the emission of a macro invocation, so that tmac.vgrind 327169695Skan * can make up its own mind about what spacing is appropriate. 328169695Skan */ 329169695Skan if (twocol) 330169695Skan printf("'ta 2.5i 2.75i 4.0iR\n'in .25i\n"); 331169695Skan else 332169695Skan printf("'ta 4i 4.25i 5.5iR\n'in .5i\n"); 333169695Skan } 334169695Skan 335169695Skan while (argc > 0) { 336169695Skan if (strcmp(argv[0], "-") == 0) { 337169695Skan /* Embed an instance of the original stdin. */ 338169695Skan in = fdopen(fileno(stdin), "r"); 339169695Skan fname = ""; 340169695Skan } else { 341169695Skan /* Open the file for input. */ 342169695Skan if ((in = fopen(argv[0], "r")) == NULL) { 343169695Skan perror(argv[0]); 344169695Skan exit(1); 345169695Skan } 346169695Skan fname = argv[0]; 347169695Skan } 348169695Skan argc--, argv++; 349169695Skan 350169695Skan /* 351169695Skan * Reinitialize for the current file. 352169695Skan */ 353169695Skan incomm = FALSE; 354169695Skan instr = FALSE; 355169695Skan inchr = FALSE; 356169695Skan _escaped = FALSE; 357169695Skan blklevel = 0; 358169695Skan prclevel = -1; 359169695Skan for (psptr=0; psptr<PSMAX; psptr++) { 360169695Skan pstack[psptr][0] = NULL; 361169695Skan plstack[psptr] = 0; 362169695Skan } 363169695Skan psptr = -1; 364169695Skan printf("'-F\n"); 365169695Skan if (!filter) { 366169695Skan char *cp; 367169695Skan 368169695Skan printf(".ds =F %s\n", fname); 369169695Skan if (needbp) { 370169695Skan needbp = 0; 371169695Skan printf(".()\n"); 372169695Skan printf(".bp\n"); 373169695Skan } 374169695Skan fstat(fileno(in), &stbuf); 375169695Skan cp = ctime(&stbuf.st_mtime); 376169695Skan cp[16] = '\0'; 377169695Skan cp[24] = '\0'; 378169695Skan printf(".ds =M %s %s\n", cp+4, cp+20); 379169695Skan printf("'wh 0 vH\n"); 380169695Skan printf("'wh -1i vF\n"); 381169695Skan } 382169695Skan if (needbp && filter) { 383169695Skan needbp = 0; 384169695Skan printf(".()\n"); 385169695Skan printf(".bp\n"); 386169695Skan } 387169695Skan 388169695Skan /* 389169695Skan * MAIN LOOP!!! 390169695Skan */ 391169695Skan while (fgets(buf, sizeof buf, in) != NULL) { 392169695Skan if (buf[0] == '\f') { 393169695Skan printf(".bp\n"); 394169695Skan } 395169695Skan if (buf[0] == '.') { 396169695Skan printf("%s", buf); 397169695Skan if (!strncmp (buf+1, "vS", 2)) 398169695Skan pass = TRUE; 399169695Skan if (!strncmp (buf+1, "vE", 2)) 400169695Skan pass = FALSE; 401169695Skan continue; 402169695Skan } 403169695Skan prccont = FALSE; 404169695Skan if (!filter || pass) 405169695Skan putScp(buf); 406169695Skan else 407169695Skan printf("%s", buf); 408169695Skan if (prccont && (psptr >= 0)) 409169695Skan printf("'FC %s\n", pstack[psptr]); 410169695Skan#ifdef DEBUG 411169695Skan printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr); 412169695Skan#endif 413169695Skan margin = 0; 414169695Skan } 415169695Skan 416169695Skan needbp = 1; 417169695Skan (void) fclose(in); 418169695Skan } 419169695Skan 420169695Skan /* Close off the vS-vE pair. */ 421169695Skan if (!filter) 422169695Skan printf("'vE\n"); 423169695Skan 424169695Skan return (0); 425169695Skan} 426169695Skan 427169695Skan#define isidchr(c) (isalnum(c) || ((c) != NIL && strchr(l_idchars, (c)) != NIL)) 428169695Skan 429169695Skanstatic void 430169695SkanputScp(char *os) 431169695Skan{ 432169695Skan char *s = os; /* pointer to unmatched string */ 433169695Skan char dummy[BUFSIZ]; /* dummy to be used by expmatch */ 434169695Skan char *comptr; /* end of a comment delimiter */ 435169695Skan char *acmptr; /* end of a comment delimiter */ 436169695Skan char *strptr; /* end of a string delimiter */ 437169695Skan char *chrptr; /* end of a character const delimiter */ 438169695Skan char *blksptr; /* end of a lexical block start */ 439169695Skan char *blkeptr; /* end of a lexical block end */ 440169695Skan 441169695Skan Start = os; /* remember the start for expmatch */ 442169695Skan _escaped = FALSE; 443169695Skan if (nokeyw || incomm || instr) 444169695Skan goto skip; 445169695Skan if (isproc(s)) { 446169695Skan printf("'FN %s\n", pname); 447169695Skan if (psptr < PSMAX-1) { 448169695Skan ++psptr; 449169695Skan strncpy (pstack[psptr], pname, PNAMELEN); 450169695Skan pstack[psptr][PNAMELEN] = NULL; 451169695Skan plstack[psptr] = blklevel; 452169695Skan } 453169695Skan } 454169695Skan /* 455169695Skan * if l_prclevel is set, check to see whether this lexical level 456169695Skan * is one immediately below which procedure definitions are allowed. 457169695Skan */ 458169695Skan if (l_prclevel && !incomm && !instr && !inchr) { 459169695Skan if (expmatch (s, l_prcenable, dummy) != NIL) 460169695Skan prclevel = blklevel + 1; 461169695Skan } 462169695Skanskip: 463169695Skan do { 464169695Skan /* check for string, comment, blockstart, etc */ 465169695Skan if (!incomm && !instr && !inchr) { 466169695Skan 467169695Skan blkeptr = expmatch (s, l_blkend, dummy); 468169695Skan blksptr = expmatch (s, l_blkbeg, dummy); 469169695Skan comptr = expmatch (s, l_combeg, dummy); 470169695Skan acmptr = expmatch (s, l_acmbeg, dummy); 471169695Skan strptr = expmatch (s, l_strbeg, dummy); 472169695Skan chrptr = expmatch (s, l_chrbeg, dummy); 473169695Skan 474169695Skan /* start of a comment? */ 475169695Skan if (comptr != NIL) 476169695Skan if ((comptr < strptr || strptr == NIL) 477169695Skan && (comptr < acmptr || acmptr == NIL) 478169695Skan && (comptr < chrptr || chrptr == NIL) 479169695Skan && (comptr < blksptr || blksptr == NIL) 480169695Skan && (comptr < blkeptr || blkeptr == NIL)) { 481169695Skan putKcp (s, comptr-1, FALSE); 482169695Skan s = comptr; 483169695Skan incomm = TRUE; 484169695Skan comtype = STANDARD; 485169695Skan if (s != os) 486169695Skan printf ("\\c"); 487169695Skan printf ("\\c\n'+C\n"); 488169695Skan continue; 489169695Skan } 490169695Skan 491169695Skan /* start of a comment? */ 492169695Skan if (acmptr != NIL) 493169695Skan if ((acmptr < strptr || strptr == NIL) 494169695Skan && (acmptr < chrptr || chrptr == NIL) 495169695Skan && (acmptr < blksptr || blksptr == NIL) 496169695Skan && (acmptr < blkeptr || blkeptr == NIL)) { 497169695Skan putKcp (s, acmptr-1, FALSE); 498169695Skan s = acmptr; 499169695Skan incomm = TRUE; 500169695Skan comtype = ALTERNATE; 501169695Skan if (s != os) 502169695Skan printf ("\\c"); 503169695Skan printf ("\\c\n'+C\n"); 504169695Skan continue; 505169695Skan } 506169695Skan 507169695Skan /* start of a string? */ 508169695Skan if (strptr != NIL) 509169695Skan if ((strptr < chrptr || chrptr == NIL) 510169695Skan && (strptr < blksptr || blksptr == NIL) 511169695Skan && (strptr < blkeptr || blkeptr == NIL)) { 512169695Skan putKcp (s, strptr-1, FALSE); 513169695Skan s = strptr; 514169695Skan instr = TRUE; 515169695Skan continue; 516169695Skan } 517169695Skan 518169695Skan /* start of a character string? */ 519169695Skan if (chrptr != NIL) 520169695Skan if ((chrptr < blksptr || blksptr == NIL) 521169695Skan && (chrptr < blkeptr || blkeptr == NIL)) { 522169695Skan putKcp (s, chrptr-1, FALSE); 523169695Skan s = chrptr; 524169695Skan inchr = TRUE; 525169695Skan continue; 526169695Skan } 527169695Skan 528169695Skan /* end of a lexical block */ 529169695Skan if (blkeptr != NIL) { 530169695Skan if (blkeptr < blksptr || blksptr == NIL) { 531169695Skan /* reset prclevel if necessary */ 532169695Skan if (l_prclevel && prclevel == blklevel) 533169695Skan prclevel = -1; 534169695Skan putKcp (s, blkeptr - 1, FALSE); 535169695Skan s = blkeptr; 536169695Skan blklevel--; 537169695Skan if (psptr >= 0 && plstack[psptr] >= blklevel) { 538169695Skan 539169695Skan /* end of current procedure */ 540169695Skan if (s != os) 541169695Skan printf ("\\c"); 542169695Skan printf ("\\c\n'-F\n"); 543169695Skan blklevel = plstack[psptr]; 544169695Skan 545169695Skan /* see if we should print the last proc name */ 546169695Skan if (--psptr >= 0) 547169695Skan prccont = TRUE; 548169695Skan else 549169695Skan psptr = -1; 550169695Skan } 551169695Skan continue; 552169695Skan } 553169695Skan } 554169695Skan 555169695Skan /* start of a lexical block */ 556169695Skan if (blksptr != NIL) { 557169695Skan putKcp (s, blksptr - 1, FALSE); 558169695Skan s = blksptr; 559169695Skan blklevel++; 560169695Skan continue; 561169695Skan } 562169695Skan 563169695Skan /* check for end of comment */ 564169695Skan } else if (incomm) { 565169695Skan comptr = expmatch (s, l_comend, dummy); 566169695Skan acmptr = expmatch (s, l_acmend, dummy); 567169695Skan if (((comtype == STANDARD) && (comptr != NIL)) || 568169695Skan ((comtype == ALTERNATE) && (acmptr != NIL))) { 569169695Skan if (comtype == STANDARD) { 570169695Skan putKcp (s, comptr-1, TRUE); 571169695Skan s = comptr; 572169695Skan } else { 573169695Skan putKcp (s, acmptr-1, TRUE); 574169695Skan s = acmptr; 575169695Skan } 576169695Skan incomm = FALSE; 577169695Skan printf("\\c\n'-C\n"); 578169695Skan continue; 579169695Skan } else { 580169695Skan putKcp (s, s + strlen(s) -1, TRUE); 581169695Skan s = s + strlen(s); 582169695Skan continue; 583169695Skan } 584169695Skan 585169695Skan /* check for end of string */ 586169695Skan } else if (instr) { 587169695Skan if ((strptr = expmatch (s, l_strend, dummy)) != NIL) { 588169695Skan putKcp (s, strptr-1, TRUE); 589169695Skan s = strptr; 590169695Skan instr = FALSE; 591169695Skan continue; 592169695Skan } else { 593169695Skan putKcp (s, s+strlen(s)-1, TRUE); 594169695Skan s = s + strlen(s); 595169695Skan continue; 596169695Skan } 597169695Skan 598169695Skan /* check for end of character string */ 599169695Skan } else if (inchr) { 600169695Skan if ((chrptr = expmatch (s, l_chrend, dummy)) != NIL) { 601169695Skan putKcp (s, chrptr-1, TRUE); 602169695Skan s = chrptr; 603169695Skan inchr = FALSE; 604169695Skan continue; 605169695Skan } else { 606169695Skan putKcp (s, s+strlen(s)-1, TRUE); 607169695Skan s = s + strlen(s); 608169695Skan continue; 609169695Skan } 610169695Skan } 611169695Skan 612169695Skan /* print out the line */ 613169695Skan putKcp (s, s + strlen(s) -1, FALSE); 614169695Skan s = s + strlen(s); 615169695Skan } while (*s); 616169695Skan} 617169695Skan 618169695Skanstatic void 619169695SkanputKcp(char *start, char *end, boolean force) 620169695Skan /* start - start of string to write */ 621169695Skan /* end - end of string to write */ 622169695Skan /* force - true if we should force nokeyw */ 623169695Skan{ 624169695Skan int i; 625169695Skan int xfld = 0; 626169695Skan 627169695Skan while (start <= end) { 628169695Skan if (doindex) { 629169695Skan if (*start == ' ' || *start == '\t') { 630169695Skan if (xfld == 0) 631169695Skan printf(""); 632169695Skan printf("\t"); 633169695Skan xfld = 1; 634169695Skan while (*start == ' ' || *start == '\t') 635169695Skan start++; 636169695Skan continue; 637169695Skan } 638169695Skan } 639169695Skan 640169695Skan /* take care of nice tab stops */ 641169695Skan if (*start == '\t') { 642169695Skan while (*start == '\t') 643169695Skan start++; 644169695Skan i = tabs(Start, start) - margin / tabsize; 645169695Skan printf ("\\h'|%dn'", 646169695Skan i * (tabsize == 4 ? 5 : 10) + 1 - margin % tabsize); 647169695Skan continue; 648169695Skan } 649169695Skan 650169695Skan if (!nokeyw && !force) 651169695Skan if ( (*start == '#' || isidchr(*start)) 652169695Skan && (start == Start || !isidchr(start[-1])) 653169695Skan ) { 654169695Skan i = iskw(start); 655169695Skan if (i > 0) { 656169695Skan printf("\\*(+K"); 657169695Skan do 658169695Skan putcp(*start++); 659169695Skan while (--i > 0); 660169695Skan printf("\\*(-K"); 661169695Skan continue; 662169695Skan } 663169695Skan } 664169695Skan 665169695Skan putcp (*start++); 666169695Skan } 667169695Skan} 668169695Skan 669169695Skan 670169695Skanstatic int 671169695Skantabs(char *s, char *os) 672169695Skan{ 673169695Skan 674169695Skan return (width(s, os) / tabsize); 675169695Skan} 676169695Skan 677169695Skanstatic int 678169695Skanwidth(char *s, char *os) 679169695Skan{ 680169695Skan int i = 0; 681169695Skan unsigned char c; 682169695Skan int n; 683169695Skan 684169695Skan while (s < os) { 685169695Skan if (*s == '\t') { 686169695Skan i = (i + tabsize) &~ (tabsize-1); 687169695Skan s++; 688169695Skan continue; 689169695Skan } 690169695Skan c = *(unsigned char *)s; 691169695Skan if (c < ' ') 692169695Skan i += 2, s++; 693169695Skan else if (c >= 0200) { 694169695Skan if ((n = mblen(s, MB_CUR_MAX)) > 0) { 695169695Skan i += csetcol(csetno(c)); 696169695Skan s += n; 697169695Skan } else 698169695Skan s++; 699169695Skan } else 700169695Skan i++, s++; 701169695Skan } 702169695Skan return (i); 703169695Skan} 704169695Skan 705169695Skanstatic void 706169695Skanputcp(int c) 707169695Skan{ 708169695Skan 709169695Skan switch(c) { 710169695Skan 711169695Skan case 0: 712169695Skan break; 713169695Skan 714169695Skan case '\f': 715169695Skan break; 716169695Skan 717169695Skan case '{': 718169695Skan printf("\\*(+K{\\*(-K"); 719169695Skan break; 720169695Skan 721169695Skan case '}': 722169695Skan printf("\\*(+K}\\*(-K"); 723169695Skan break; 724169695Skan 725169695Skan case '\\': 726169695Skan printf("\\e"); 727169695Skan break; 728169695Skan 729169695Skan case '_': 730169695Skan printf("\\*_"); 731169695Skan break; 732169695Skan 733169695Skan case '-': 734169695Skan printf("\\*-"); 735169695Skan break; 736169695Skan 737169695Skan /* 738169695Skan * The following two cases deal with the accent characters. 739169695Skan * If they're part of a comment, we assume that they're part 740169695Skan * of running text and hand them to troff as regular quote 741169695Skan * characters. Otherwise, we assume they're being used as 742169695Skan * special characters (e.g., string delimiters) and arrange 743169695Skan * for troff to render them as accents. This is an imperfect 744169695Skan * heuristic that produces slightly better appearance than the 745169695Skan * former behavior of unconditionally rendering the characters 746169695Skan * as accents. (See bug 1040343.) 747169695Skan */ 748169695Skan 749169695Skan case '`': 750169695Skan if (incomm) 751169695Skan printf("`"); 752169695Skan else 753169695Skan printf("\\`"); 754169695Skan break; 755169695Skan 756169695Skan case '\'': 757169695Skan if (incomm) 758169695Skan printf("'"); 759169695Skan else 760169695Skan printf("\\'"); 761169695Skan break; 762169695Skan 763169695Skan case '.': 764169695Skan printf("\\&."); 765169695Skan break; 766169695Skan 767169695Skan /* 768169695Skan * The following two cases contain special hacking 769169695Skan * to make C-style comments line up. The tests aren't 770169695Skan * really adequate; they lead to grotesqueries such 771169695Skan * as italicized multiplication and division operators. 772169695Skan * However, the obvious test (!incomm) doesn't work, 773169695Skan * because incomm isn't set until after we've put out 774169695Skan * the comment-begin characters. The real problem is 775169695Skan * that expmatch() doesn't give us enough information. 776169695Skan */ 777169695Skan 778169695Skan case '*': 779169695Skan if (instr || inchr) 780169695Skan printf("*"); 781169695Skan else 782169695Skan printf("\\f2*\\fP"); 783169695Skan break; 784169695Skan 785169695Skan case '/': 786169695Skan if (instr || inchr) 787169695Skan printf("/"); 788169695Skan else 789169695Skan printf("\\f2\\h'\\w' 'u-\\w'/'u'/\\fP"); 790169695Skan break; 791169695Skan 792169695Skan default: 793169695Skan if (c < 040) 794169695Skan putchar('^'), c |= '@'; 795169695Skan case '\t': 796169695Skan case '\n': 797169695Skan putchar(c); 798169695Skan } 799169695Skan} 800169695Skan 801169695Skan/* 802169695Skan * look for a process beginning on this line 803169695Skan */ 804169695Skanboolean 805169695Skanisproc(s) 806169695Skan char *s; 807169695Skan{ 808169695Skan pname[0] = NULL; 809169695Skan if (l_prclevel ? (prclevel == blklevel) : (!l_toplex || blklevel == 0)) 810169695Skan if (expmatch (s, l_prcbeg, pname) != NIL) { 811169695Skan return (TRUE); 812169695Skan } 813169695Skan return (FALSE); 814169695Skan} 815169695Skan 816169695Skan 817169695Skan/* 818169695Skan * iskw - check to see if the next word is a keyword 819169695Skan * Return its length if it is or 0 if it isn't. 820169695Skan */ 821169695Skan 822169695Skanstatic int 823169695Skaniskw(char *s) 824169695Skan{ 825169695Skan char **ss = l_keywds; 826169695Skan int i = 1; 827169695Skan char *cp = s; 828169695Skan 829169695Skan /* Get token length. */ 830169695Skan while (++cp, isidchr(*cp)) 831169695Skan i++; 832169695Skan 833169695Skan while (cp = *ss++) { 834169695Skan if (!STRNCMP(s,cp,i) && !isidchr(cp[i])) 835169695Skan return (i); 836169695Skan } 837169695Skan return (0); 838169695Skan} 839169695Skan