1*ce7279d8Sjsg /* $OpenBSD: cmode.c,v 1.23 2024/05/21 05:00:48 jsg Exp $ */
243e1f234Skjell /*
343e1f234Skjell * This file is in the public domain.
443e1f234Skjell *
543e1f234Skjell * Author: Kjell Wooding <kjell@openbsd.org>
643e1f234Skjell */
743e1f234Skjell
843e1f234Skjell /*
943e1f234Skjell * Implement an non-irritating KNF-compliant mode for editing
1043e1f234Skjell * C code.
1143e1f234Skjell */
12cc6738c5Sbcallah
13cc6738c5Sbcallah #include <sys/queue.h>
1443e1f234Skjell #include <ctype.h>
15cc6738c5Sbcallah #include <signal.h>
16cc6738c5Sbcallah #include <stdio.h>
1743e1f234Skjell
1843e1f234Skjell #include "def.h"
1943e1f234Skjell #include "funmap.h"
20cc6738c5Sbcallah #include "kbd.h"
2143e1f234Skjell
2243e1f234Skjell /* Pull in from modes.c */
2343e1f234Skjell extern int changemode(int, int, char *);
2443e1f234Skjell
2543e1f234Skjell static int cc_strip_trailp = TRUE; /* Delete Trailing space? */
2643e1f234Skjell static int cc_basic_indent = 8; /* Basic Indent multiple */
2743e1f234Skjell static int cc_cont_indent = 4; /* Continued line indent */
2843e1f234Skjell static int cc_colon_indent = -8; /* Label / case indent */
2943e1f234Skjell
3043e1f234Skjell static int getmatch(int, int);
3143e1f234Skjell static int getindent(const struct line *, int *);
3292cb5ab0Skjell static int in_whitespace(struct line *, int);
3392cb5ab0Skjell static int findcolpos(const struct buffer *, const struct line *, int);
3492cb5ab0Skjell static struct line *findnonblank(struct line *);
3592cb5ab0Skjell static int isnonblank(const struct line *, int);
3692cb5ab0Skjell
376238f0cdSlum void cmode_init(void);
3843e1f234Skjell
3943e1f234Skjell /* Keymaps */
4043e1f234Skjell
4143e1f234Skjell static PF cmode_brace[] = {
42d3776cdaSkjell cc_brace, /* } */
4343e1f234Skjell };
4443e1f234Skjell
459d7fdde6Skjell static PF cmode_cCP[] = {
469d7fdde6Skjell compile, /* C-c P */
479d7fdde6Skjell };
489d7fdde6Skjell
499d7fdde6Skjell
509d7fdde6Skjell static PF cmode_cc[] = {
519d7fdde6Skjell NULL, /* ^C */
529d7fdde6Skjell rescan, /* ^D */
539d7fdde6Skjell rescan, /* ^E */
549d7fdde6Skjell rescan, /* ^F */
559d7fdde6Skjell rescan, /* ^G */
569d7fdde6Skjell rescan, /* ^H */
5743e1f234Skjell cc_tab, /* ^I */
5843e1f234Skjell rescan, /* ^J */
5943e1f234Skjell rescan, /* ^K */
6043e1f234Skjell rescan, /* ^L */
6143e1f234Skjell cc_lfindent, /* ^M */
6243e1f234Skjell };
6343e1f234Skjell
6492cb5ab0Skjell static PF cmode_spec[] = {
6543e1f234Skjell cc_char, /* : */
6643e1f234Skjell };
6743e1f234Skjell
6808e58701Sbcallah static struct KEYMAPE (1) cmode_cmap = {
699d7fdde6Skjell 1,
7008e58701Sbcallah 1,
719d7fdde6Skjell rescan,
729d7fdde6Skjell {
739d7fdde6Skjell { 'P', 'P', cmode_cCP, NULL }
749d7fdde6Skjell }
759d7fdde6Skjell };
769d7fdde6Skjell
7708e58701Sbcallah static struct KEYMAPE (3) cmodemap = {
7843e1f234Skjell 3,
7908e58701Sbcallah 3,
8043e1f234Skjell rescan,
8143e1f234Skjell {
829d7fdde6Skjell { CCHR('C'), CCHR('M'), cmode_cc, (KEYMAP *) &cmode_cmap },
8392cb5ab0Skjell { ':', ':', cmode_spec, NULL },
8443e1f234Skjell { '}', '}', cmode_brace, NULL }
8543e1f234Skjell }
8643e1f234Skjell };
8743e1f234Skjell
8849cb4ed9Sop /* Function, Mode hooks */
8943e1f234Skjell
9043e1f234Skjell void
cmode_init(void)9143e1f234Skjell cmode_init(void)
9243e1f234Skjell {
93f8588f90Slum funmap_add(cmode, "c-mode", 0);
94f8588f90Slum funmap_add(cc_char, "c-handle-special-char", 0);
95f8588f90Slum funmap_add(cc_brace, "c-handle-special-brace", 0);
96f8588f90Slum funmap_add(cc_tab, "c-tab-or-indent", 0);
97f8588f90Slum funmap_add(cc_indent, "c-indent", 0);
98f8588f90Slum funmap_add(cc_lfindent, "c-indent-and-newline", 0);
99eb0368c5Ssobrado maps_add((KEYMAP *)&cmodemap, "c");
10043e1f234Skjell }
10143e1f234Skjell
10243e1f234Skjell /*
10343e1f234Skjell * Enable/toggle c-mode
10443e1f234Skjell */
10543e1f234Skjell int
cmode(int f,int n)10643e1f234Skjell cmode(int f, int n)
10743e1f234Skjell {
108eb0368c5Ssobrado return(changemode(f, n, "c"));
10943e1f234Skjell }
11043e1f234Skjell
11143e1f234Skjell /*
11243e1f234Skjell * Handle special C character - selfinsert then indent.
11343e1f234Skjell */
11443e1f234Skjell int
cc_char(int f,int n)11543e1f234Skjell cc_char(int f, int n)
11643e1f234Skjell {
11743e1f234Skjell if (n < 0)
11843e1f234Skjell return (FALSE);
11943e1f234Skjell if (selfinsert(FFRAND, n) == FALSE)
12043e1f234Skjell return (FALSE);
12143e1f234Skjell return (cc_indent(FFRAND, n));
12243e1f234Skjell }
12343e1f234Skjell
12443e1f234Skjell /*
125d3776cdaSkjell * Handle special C character - selfinsert then indent.
126d3776cdaSkjell */
127d3776cdaSkjell int
cc_brace(int f,int n)128d3776cdaSkjell cc_brace(int f, int n)
129d3776cdaSkjell {
130d3776cdaSkjell if (n < 0)
131d3776cdaSkjell return (FALSE);
132d3776cdaSkjell if (showmatch(FFRAND, 1) == FALSE)
133d3776cdaSkjell return (FALSE);
134d3776cdaSkjell return (cc_indent(FFRAND, n));
135d3776cdaSkjell }
136d3776cdaSkjell
137d3776cdaSkjell
138d3776cdaSkjell /*
13943e1f234Skjell * If we are in the whitespace at the beginning of the line,
14043e1f234Skjell * simply act as a regular tab. If we are not, indent
14143e1f234Skjell * current line according to whitespace rules.
14243e1f234Skjell */
14343e1f234Skjell int
cc_tab(int f,int n)14443e1f234Skjell cc_tab(int f, int n)
14543e1f234Skjell {
14643e1f234Skjell int inwhitep = FALSE; /* In leading whitespace? */
14743e1f234Skjell
14892cb5ab0Skjell inwhitep = in_whitespace(curwp->w_dotp, llength(curwp->w_dotp));
14943e1f234Skjell
15043e1f234Skjell /* If empty line, or in whitespace */
15143e1f234Skjell if (llength(curwp->w_dotp) == 0 || inwhitep)
15243e1f234Skjell return (selfinsert(f, n));
15343e1f234Skjell
15443e1f234Skjell return (cc_indent(FFRAND, 1));
15543e1f234Skjell }
15643e1f234Skjell
15743e1f234Skjell /*
15843e1f234Skjell * Attempt to indent current line according to KNF rules.
15943e1f234Skjell */
16043e1f234Skjell int
cc_indent(int f,int n)16143e1f234Skjell cc_indent(int f, int n)
16243e1f234Skjell {
163a70808f5Sguenther int pi, mi; /* Previous indents (mi is ignored) */
164a70808f5Sguenther int ci; /* current indent */
16543e1f234Skjell struct line *lp;
1669d7fdde6Skjell int ret;
16743e1f234Skjell
16843e1f234Skjell if (n < 0)
16943e1f234Skjell return (FALSE);
17043e1f234Skjell
171a13804d2Skjell undo_boundary_enable(FFRAND, 0);
17243e1f234Skjell if (cc_strip_trailp)
17343e1f234Skjell deltrailwhite(FFRAND, 1);
17443e1f234Skjell
17592cb5ab0Skjell /*
17692cb5ab0Skjell * Search backwards for a non-blank, non-preprocessor,
17792cb5ab0Skjell * non-comment line
17892cb5ab0Skjell */
17992cb5ab0Skjell
18092cb5ab0Skjell lp = findnonblank(curwp->w_dotp);
18143e1f234Skjell
18243e1f234Skjell pi = getindent(lp, &mi);
18343e1f234Skjell
18443e1f234Skjell /* Strip leading space on current line */
18543e1f234Skjell delleadwhite(FFRAND, 1);
18643e1f234Skjell /* current indent is computed only to current position */
187a70808f5Sguenther (void)getindent(curwp->w_dotp, &ci);
18843e1f234Skjell
18943e1f234Skjell if (pi + ci < 0)
1909d7fdde6Skjell ret = indent(FFOTHARG, 0);
19143e1f234Skjell else
1929d7fdde6Skjell ret = indent(FFOTHARG, pi + ci);
1939d7fdde6Skjell
194a13804d2Skjell undo_boundary_enable(FFRAND, 1);
1959d7fdde6Skjell
1969d7fdde6Skjell return (ret);
19743e1f234Skjell }
19843e1f234Skjell
19943e1f234Skjell /*
20043e1f234Skjell * Indent-and-newline (technically, newline then indent)
20143e1f234Skjell */
20243e1f234Skjell int
cc_lfindent(int f,int n)20343e1f234Skjell cc_lfindent(int f, int n)
20443e1f234Skjell {
20543e1f234Skjell if (n < 0)
20643e1f234Skjell return (FALSE);
207d1c1bfe0Sop if (cc_strip_trailp)
208d1c1bfe0Sop (void)delwhite(FFRAND, 1);
2093eb81a2eSbcallah if (enewline(FFRAND, 1) == FALSE)
21043e1f234Skjell return (FALSE);
21143e1f234Skjell return (cc_indent(FFRAND, n));
21243e1f234Skjell }
21343e1f234Skjell
21443e1f234Skjell /*
215d9a51c35Sjmc * Get the level of indentation after line lp is processed
21692cb5ab0Skjell * Note getindent has two returns:
21743e1f234Skjell * curi = value if indenting current line.
21843e1f234Skjell * return value = value affecting subsequent lines.
21943e1f234Skjell */
22043e1f234Skjell static int
getindent(const struct line * lp,int * curi)22143e1f234Skjell getindent(const struct line *lp, int *curi)
22243e1f234Skjell {
22343e1f234Skjell int lo, co; /* leading space, current offset*/
22443e1f234Skjell int nicol = 0; /* position count */
22543e1f234Skjell int c = '\0'; /* current char */
22643e1f234Skjell int newind = 0; /* new index value */
22743e1f234Skjell int stringp = FALSE; /* in string? */
22843e1f234Skjell int escp = FALSE; /* Escape char? */
229d9a51c35Sjmc int lastc = '\0'; /* Last matched string delimiter */
23043e1f234Skjell int nparen = 0; /* paren count */
23143e1f234Skjell int obrace = 0; /* open brace count */
23243e1f234Skjell int cbrace = 0; /* close brace count */
23392cb5ab0Skjell int firstnwsp = FALSE; /* First nonspace encountered? */
23443e1f234Skjell int colonp = FALSE; /* Did we see a colon? */
23543e1f234Skjell int questionp = FALSE; /* Did we see a question mark? */
23692cb5ab0Skjell int slashp = FALSE; /* Slash? */
23792cb5ab0Skjell int astp = FALSE; /* Asterisk? */
23892cb5ab0Skjell int cpos = -1; /* comment position */
23992cb5ab0Skjell int cppp = FALSE; /* Preprocessor command? */
24043e1f234Skjell
24143e1f234Skjell *curi = 0;
24243e1f234Skjell
24343e1f234Skjell /* Compute leading space */
24443e1f234Skjell for (lo = 0; lo < llength(lp); lo++) {
24543e1f234Skjell if (!isspace(c = lgetc(lp, lo)))
24643e1f234Skjell break;
247fb3e194eSop if (c == '\t')
248fb3e194eSop nicol = ntabstop(nicol, curbp->b_tabw);
249fb3e194eSop else
25043e1f234Skjell nicol++;
25143e1f234Skjell }
25243e1f234Skjell
25343e1f234Skjell /* If last line was blank, choose 0 */
25443e1f234Skjell if (lo == llength(lp))
25543e1f234Skjell nicol = 0;
25643e1f234Skjell
25743e1f234Skjell newind = 0;
25843e1f234Skjell /* Compute modifiers */
25943e1f234Skjell for (co = lo; co < llength(lp); co++) {
26043e1f234Skjell c = lgetc(lp, co);
26143e1f234Skjell /* We have a non-whitespace char */
26292cb5ab0Skjell if (!firstnwsp && !isspace(c)) {
26392cb5ab0Skjell if (c == '#')
26492cb5ab0Skjell cppp = TRUE;
26592cb5ab0Skjell firstnwsp = TRUE;
26643e1f234Skjell }
26743e1f234Skjell if (c == '\\')
26843e1f234Skjell escp = !escp;
26943e1f234Skjell else if (stringp) {
27043e1f234Skjell if (!escp && (c == '"' || c == '\'')) {
27143e1f234Skjell /* unescaped string char */
27243e1f234Skjell if (getmatch(c, lastc))
27343e1f234Skjell stringp = FALSE;
27443e1f234Skjell }
27543e1f234Skjell } else if (c == '"' || c == '\'') {
27643e1f234Skjell stringp = TRUE;
27743e1f234Skjell lastc = c;
27843e1f234Skjell } else if (c == '(') {
27943e1f234Skjell nparen++;
28043e1f234Skjell } else if (c == ')') {
28143e1f234Skjell nparen--;
28243e1f234Skjell } else if (c == '{') {
28343e1f234Skjell obrace++;
28492cb5ab0Skjell firstnwsp = FALSE;
28543e1f234Skjell } else if (c == '}') {
28643e1f234Skjell cbrace++;
28743e1f234Skjell } else if (c == '?') {
28843e1f234Skjell questionp = TRUE;
28943e1f234Skjell } else if (c == ':') {
29043e1f234Skjell /* ignore (foo ? bar : baz) construct */
29143e1f234Skjell if (!questionp)
29243e1f234Skjell colonp = TRUE;
29392cb5ab0Skjell } else if (c == '/') {
29492cb5ab0Skjell /* first nonwhitespace? -> indent */
29592cb5ab0Skjell if (firstnwsp) {
29692cb5ab0Skjell /* If previous char asterisk -> close */
29792cb5ab0Skjell if (astp)
29892cb5ab0Skjell cpos = -1;
29992cb5ab0Skjell else
30092cb5ab0Skjell slashp = TRUE;
30192cb5ab0Skjell }
30292cb5ab0Skjell } else if (c == '*') {
30392cb5ab0Skjell /* If previous char slash -> open */
30492cb5ab0Skjell if (slashp)
30592cb5ab0Skjell cpos = co;
30692cb5ab0Skjell else
30792cb5ab0Skjell astp = TRUE;
30892cb5ab0Skjell } else if (firstnwsp) {
30992cb5ab0Skjell firstnwsp = FALSE;
31043e1f234Skjell }
31143e1f234Skjell
31292cb5ab0Skjell /* Reset matches that apply to next character only */
31343e1f234Skjell if (c != '\\')
31443e1f234Skjell escp = FALSE;
31592cb5ab0Skjell if (c != '*')
31692cb5ab0Skjell astp = FALSE;
31792cb5ab0Skjell if (c != '/')
31892cb5ab0Skjell slashp = FALSE;
31943e1f234Skjell }
32043e1f234Skjell /*
32143e1f234Skjell * If not terminated with a semicolon, and brace or paren open.
32243e1f234Skjell * we continue
32343e1f234Skjell */
32443e1f234Skjell if (colonp) {
32543e1f234Skjell *curi += cc_colon_indent;
32643e1f234Skjell newind -= cc_colon_indent;
32743e1f234Skjell }
32843e1f234Skjell
32943e1f234Skjell *curi -= (cbrace) * cc_basic_indent;
33043e1f234Skjell newind += obrace * cc_basic_indent;
33143e1f234Skjell
33243e1f234Skjell if (nparen < 0)
33343e1f234Skjell newind -= cc_cont_indent;
33443e1f234Skjell else if (nparen > 0)
33543e1f234Skjell newind += cc_cont_indent;
33692cb5ab0Skjell
33743e1f234Skjell *curi += nicol;
33843e1f234Skjell
33992cb5ab0Skjell /* Ignore preprocessor. Otherwise, add current column */
34092cb5ab0Skjell if (cppp) {
34192cb5ab0Skjell newind = nicol;
34292cb5ab0Skjell *curi = 0;
34392cb5ab0Skjell } else {
34492cb5ab0Skjell newind += nicol;
34592cb5ab0Skjell }
34692cb5ab0Skjell
34792cb5ab0Skjell if (cpos != -1)
34892cb5ab0Skjell newind = findcolpos(curbp, lp, cpos);
34992cb5ab0Skjell
35043e1f234Skjell return (newind);
35143e1f234Skjell }
35243e1f234Skjell
35343e1f234Skjell /*
354d9a51c35Sjmc * Given a delimiter and its purported mate, tell us if they
35543e1f234Skjell * match.
35643e1f234Skjell */
35743e1f234Skjell static int
getmatch(int c,int mc)35843e1f234Skjell getmatch(int c, int mc)
35943e1f234Skjell {
36043e1f234Skjell int match = FALSE;
36143e1f234Skjell
36243e1f234Skjell switch (c) {
36343e1f234Skjell case '"':
36443e1f234Skjell match = (mc == '"');
36543e1f234Skjell break;
36643e1f234Skjell case '\'':
36743e1f234Skjell match = (mc == '\'');
36843e1f234Skjell break;
36943e1f234Skjell case '(':
37043e1f234Skjell match = (mc == ')');
37143e1f234Skjell break;
37243e1f234Skjell case '[':
37343e1f234Skjell match = (mc == ']');
37443e1f234Skjell break;
37543e1f234Skjell case '{':
37643e1f234Skjell match = (mc == '}');
37743e1f234Skjell break;
37843e1f234Skjell }
37943e1f234Skjell
38043e1f234Skjell return (match);
38143e1f234Skjell }
38292cb5ab0Skjell
38392cb5ab0Skjell static int
in_whitespace(struct line * lp,int len)38492cb5ab0Skjell in_whitespace(struct line *lp, int len)
38592cb5ab0Skjell {
38692cb5ab0Skjell int lo;
38792cb5ab0Skjell int inwhitep = FALSE;
38892cb5ab0Skjell
38992cb5ab0Skjell for (lo = 0; lo < len; lo++) {
39092cb5ab0Skjell if (!isspace(lgetc(lp, lo)))
39192cb5ab0Skjell break;
39292cb5ab0Skjell if (lo == len - 1)
39392cb5ab0Skjell inwhitep = TRUE;
39492cb5ab0Skjell }
39592cb5ab0Skjell
39692cb5ab0Skjell return (inwhitep);
39792cb5ab0Skjell }
39892cb5ab0Skjell
39992cb5ab0Skjell
40092cb5ab0Skjell /* convert a line/offset pair to a column position (for indenting) */
40192cb5ab0Skjell static int
findcolpos(const struct buffer * bp,const struct line * lp,int lo)40292cb5ab0Skjell findcolpos(const struct buffer *bp, const struct line *lp, int lo)
40392cb5ab0Skjell {
40492cb5ab0Skjell int col, i, c;
40592cb5ab0Skjell char tmp[5];
40692cb5ab0Skjell
40792cb5ab0Skjell /* determine column */
40892cb5ab0Skjell col = 0;
40992cb5ab0Skjell
41092cb5ab0Skjell for (i = 0; i < lo; ++i) {
41192cb5ab0Skjell c = lgetc(lp, i);
41238733382Sop if (c == '\t') {
413fb3e194eSop col = ntabstop(col, curbp->b_tabw);
41492cb5ab0Skjell } else if (ISCTRL(c) != FALSE)
41592cb5ab0Skjell col += 2;
41692cb5ab0Skjell else if (isprint(c)) {
41792cb5ab0Skjell col++;
41892cb5ab0Skjell } else {
41992cb5ab0Skjell col += snprintf(tmp, sizeof(tmp), "\\%o", c);
42092cb5ab0Skjell }
42192cb5ab0Skjell
42292cb5ab0Skjell }
42392cb5ab0Skjell return (col);
42492cb5ab0Skjell }
42592cb5ab0Skjell
42692cb5ab0Skjell /*
42792cb5ab0Skjell * Find a non-blank line, searching backwards from the supplied line pointer.
42892cb5ab0Skjell * For C, nonblank is non-preprocessor, non C++, and accounts
42992cb5ab0Skjell * for complete C-style comments.
43092cb5ab0Skjell */
43192cb5ab0Skjell static struct line *
findnonblank(struct line * lp)43292cb5ab0Skjell findnonblank(struct line *lp)
43392cb5ab0Skjell {
43492cb5ab0Skjell int lo;
43592cb5ab0Skjell int nonblankp = FALSE;
43692cb5ab0Skjell int commentp = FALSE;
43792cb5ab0Skjell int slashp;
43892cb5ab0Skjell int astp;
43992cb5ab0Skjell int c;
44092cb5ab0Skjell
44192cb5ab0Skjell while (lback(lp) != curbp->b_headp && (commentp || !nonblankp)) {
44292cb5ab0Skjell lp = lback(lp);
44392cb5ab0Skjell slashp = FALSE;
44492cb5ab0Skjell astp = FALSE;
44592cb5ab0Skjell
44692cb5ab0Skjell /* Potential nonblank? */
44792cb5ab0Skjell nonblankp = isnonblank(lp, llength(lp));
44892cb5ab0Skjell
44992cb5ab0Skjell /*
45092cb5ab0Skjell * Search from end, removing complete C-style
45192cb5ab0Skjell * comments. If one is found, ignore it and
45292cb5ab0Skjell * test for nonblankness from where it starts.
45392cb5ab0Skjell */
45492cb5ab0Skjell for (lo = llength(lp) - 1; lo >= 0; lo--) {
45592cb5ab0Skjell if (!isspace(c = lgetc(lp, lo))) {
45692cb5ab0Skjell if (commentp) { /* find comment "open" */
45792cb5ab0Skjell if (c == '*')
45892cb5ab0Skjell astp = TRUE;
45992cb5ab0Skjell else if (astp && c == '/') {
46092cb5ab0Skjell commentp = FALSE;
46192cb5ab0Skjell /* whitespace to here? */
46292cb5ab0Skjell nonblankp = isnonblank(lp, lo);
46392cb5ab0Skjell }
46492cb5ab0Skjell } else { /* find comment "close" */
46592cb5ab0Skjell if (c == '/')
46692cb5ab0Skjell slashp = TRUE;
46792cb5ab0Skjell else if (slashp && c == '*')
46892cb5ab0Skjell /* found a comment */
46992cb5ab0Skjell commentp = TRUE;
47092cb5ab0Skjell }
47192cb5ab0Skjell }
47292cb5ab0Skjell }
47392cb5ab0Skjell }
47492cb5ab0Skjell
47592cb5ab0Skjell /* Rewound to start of file? */
47692cb5ab0Skjell if (lback(lp) == curbp->b_headp && !nonblankp)
47792cb5ab0Skjell return (curbp->b_headp);
47892cb5ab0Skjell
47992cb5ab0Skjell return (lp);
48092cb5ab0Skjell }
48192cb5ab0Skjell
48292cb5ab0Skjell /*
48392cb5ab0Skjell * Given a line, scan forward to 'omax' and determine if we
48492cb5ab0Skjell * are all C whitespace.
48592cb5ab0Skjell * Note that preprocessor directives and C++-style comments
48692cb5ab0Skjell * count as whitespace. C-style comments do not, and must
48792cb5ab0Skjell * be handled elsewhere.
48892cb5ab0Skjell */
48992cb5ab0Skjell static int
isnonblank(const struct line * lp,int omax)49092cb5ab0Skjell isnonblank(const struct line *lp, int omax)
49192cb5ab0Skjell {
49292cb5ab0Skjell int nonblankp = FALSE; /* Return value */
49392cb5ab0Skjell int slashp = FALSE; /* Encountered slash */
49492cb5ab0Skjell int lo; /* Loop index */
49592cb5ab0Skjell int c; /* char being read */
49692cb5ab0Skjell
49792cb5ab0Skjell /* Scan from front for preprocessor, C++ comments */
49892cb5ab0Skjell for (lo = 0; lo < omax; lo++) {
49992cb5ab0Skjell if (!isspace(c = lgetc(lp, lo))) {
50092cb5ab0Skjell /* Possible nonblank line */
50192cb5ab0Skjell nonblankp = TRUE;
50292cb5ab0Skjell /* skip // and # starts */
50392cb5ab0Skjell if (c == '#' || (slashp && c == '/')) {
50492cb5ab0Skjell nonblankp = FALSE;
50592cb5ab0Skjell break;
50692cb5ab0Skjell } else if (!slashp && c == '/') {
50792cb5ab0Skjell slashp = TRUE;
50892cb5ab0Skjell continue;
50992cb5ab0Skjell }
51092cb5ab0Skjell }
51192cb5ab0Skjell slashp = FALSE;
51292cb5ab0Skjell }
51392cb5ab0Skjell return (nonblankp);
51492cb5ab0Skjell }
515