xref: /csrg-svn/usr.bin/indent/lexi.c (revision 33768)
121970Sdist /*
221970Sdist  * Copyright (c) 1980 Regents of the University of California.
333767Sbostic  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
433767Sbostic  * All rights reserved.
533767Sbostic  *
633767Sbostic  * Redistribution and use in source and binary forms are permitted
733767Sbostic  * provided that this notice is preserved and that due credit is given
833767Sbostic  * to the University of California at Berkeley and the University of
933767Sbostic  * Illinois at Urbana.  The name of either University may not be used
1033767Sbostic  * to endorse or promote products derived from this software without
1133767Sbostic  * specific prior written permission. This software is provided
1233767Sbostic  * ``as is'' without express or implied warranty.
1321970Sdist  */
148804Smckusick 
1521970Sdist #ifndef lint
16*33768Sbostic static char sccsid[] = "@(#)lexi.c	5.7 (Berkeley) 03/22/88";
1733767Sbostic #endif /* not lint */
1821970Sdist 
1933767Sbostic /*
2024455Smckusick  * NAME:
2124455Smckusick  *	lexi
2224455Smckusick  *
2324455Smckusick  * FUNCTION:
2424455Smckusick  *	This is the token scanner for indent
2524455Smckusick  *
2624455Smckusick  * ALGORITHM:
2724455Smckusick  *	1) Strip off intervening blanks and/or tabs.
2824455Smckusick  *	2) If it is an alphanumeric token, move it to the token buffer "token".
2924455Smckusick  *	   Check if it is a special reserved word that indent will want to
3024455Smckusick  *	   know about.
3124455Smckusick  *	3) Non-alphanumeric tokens are handled with a big switch statement.  A
3224455Smckusick  *	   flag is kept to remember if the last token was a "unary delimiter",
3324455Smckusick  *	   which forces a following operator to be unary as opposed to binary.
3424455Smckusick  *
3524455Smckusick  * PARAMETERS:
3624455Smckusick  *	None
3724455Smckusick  *
3824455Smckusick  * RETURNS:
3924455Smckusick  *	An integer code indicating the type of token scanned.
4024455Smckusick  *
4124455Smckusick  * GLOBALS:
4224455Smckusick  *	buf_ptr =
4324455Smckusick  *	had_eof
4424455Smckusick  *	ps.last_u_d =	Set to true iff this token is a "unary delimiter"
4524455Smckusick  *
4624455Smckusick  * CALLS:
4724455Smckusick  *	fill_buffer
4824455Smckusick  *	printf (lib)
4924455Smckusick  *
5024455Smckusick  * CALLED BY:
5124455Smckusick  *	main
5224455Smckusick  *
5324455Smckusick  * NOTES:
5424455Smckusick  *	Start of comment is passed back so that the comment can be scanned by
5524455Smckusick  *	pr_comment.
5624455Smckusick  *
5724455Smckusick  *	Strings and character literals are returned just like identifiers.
5824455Smckusick  *
5924455Smckusick  * HISTORY:
6024455Smckusick  *	initial coding 	November 1976	D A Willcox of CAC
6124455Smckusick  *	1/7/77		D A Willcox of CAC	Fix to provide proper handling
6224455Smckusick  *						of "int a -1;"
6324455Smckusick  *
6424455Smckusick  */
6524455Smckusick 
668804Smckusick /*
6724455Smckusick  * Here we have the token scanner for indent.  It scans off one token and
6824455Smckusick  * puts it in the global variable "token".  It returns a code, indicating
6924455Smckusick  * the type of token scanned.
7024455Smckusick  */
718804Smckusick 
7233230Sbostic #include "indent_globs.h"
7333230Sbostic #include "indent_codes.h"
7424455Smckusick #include "ctype.h"
758804Smckusick 
768804Smckusick #define alphanum 1
778804Smckusick #define opchar 3
788804Smckusick 
798804Smckusick struct templ {
8024455Smckusick     char       *rwd;
8124455Smckusick     int         rwcode;
828804Smckusick };
838804Smckusick 
8424455Smckusick struct templ specials[100] =
858804Smckusick {
868804Smckusick     "switch", 1,
878804Smckusick     "case", 2,
8824455Smckusick     "break", 0,
898804Smckusick     "struct", 3,
9024455Smckusick     "union", 3,
9124455Smckusick     "enum", 3,
928804Smckusick     "default", 2,
938804Smckusick     "int", 4,
948804Smckusick     "char", 4,
958804Smckusick     "float", 4,
968804Smckusick     "double", 4,
978804Smckusick     "long", 4,
988804Smckusick     "short", 4,
998804Smckusick     "typdef", 4,
1008804Smckusick     "unsigned", 4,
1018804Smckusick     "register", 4,
1028804Smckusick     "static", 4,
1038804Smckusick     "global", 4,
1048804Smckusick     "extern", 4,
10524455Smckusick     "void", 4,
10624455Smckusick     "goto", 0,
10724455Smckusick     "return", 0,
1088804Smckusick     "if", 5,
1098804Smckusick     "while", 5,
1108804Smckusick     "for", 5,
1118804Smckusick     "else", 6,
1128804Smckusick     "do", 6,
11324455Smckusick     "sizeof", 7,
1148804Smckusick     0, 0
1158804Smckusick };
1168804Smckusick 
11724455Smckusick char        chartype[128] =
11824455Smckusick {				/* this is used to facilitate the decision
11924455Smckusick 				 * of what type (alphanumeric, operator)
12024455Smckusick 				 * each character is */
1218804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1228804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1238804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1248804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
125*33768Sbostic     0, 3, 0, 0, 1, 3, 3, 0,
1268804Smckusick     0, 0, 3, 3, 0, 3, 3, 3,
1278804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1288804Smckusick     1, 1, 0, 0, 3, 3, 3, 3,
1298804Smckusick     0, 1, 1, 1, 1, 1, 1, 1,
1308804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1318804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1328804Smckusick     1, 1, 1, 0, 0, 0, 3, 1,
1338804Smckusick     0, 1, 1, 1, 1, 1, 1, 1,
1348804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1358804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1368804Smckusick     1, 1, 1, 0, 3, 0, 3, 0
1378804Smckusick };
1388804Smckusick 
1398804Smckusick 
1408804Smckusick 
1418804Smckusick 
14224455Smckusick int
14324455Smckusick lexi()
14424455Smckusick {
14524455Smckusick     register char *tok;		/* local pointer to next char in token */
14624455Smckusick     int         unary_delim;	/* this is set to 1 if the current token
14724455Smckusick 				 *
14824455Smckusick 				 * forces a following operator to be unary */
14924455Smckusick     static int  last_code;	/* the last token type returned */
15024455Smckusick     static int  l_struct;	/* set to 1 if the last token was 'struct' */
15124455Smckusick     int         code;		/* internal code to be returned */
15224455Smckusick     char        qchar;		/* the delimiter character for a string */
1538804Smckusick 
15424455Smckusick     tok = token;		/* point to start of place to save token */
1558804Smckusick     unary_delim = false;
15624455Smckusick     ps.col_1 = ps.last_nl;	/* tell world that this token started in
15724455Smckusick 				 * column 1 iff the last thing scanned was
15824455Smckusick 				 * nl */
15924455Smckusick     ps.last_nl = false;
1608804Smckusick 
16124455Smckusick     while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
16224455Smckusick 	ps.col_1 = false;	/* leading blanks imply token is not in
16324455Smckusick 				 * column 1 */
1648804Smckusick 	if (++buf_ptr >= buf_end)
16524455Smckusick 	    fill_buffer();
1668804Smckusick     }
1678804Smckusick 
16824649Smckusick     /* Scan an alphanumeric token.  Note that we must also handle
16924649Smckusick      * stuff like "1.0e+03" and "7e-6". */
17024455Smckusick     if (chartype[*buf_ptr & 0177] == alphanum) {	/* we have a character
17124455Smckusick 							 * or number */
17224455Smckusick 	register char *j;	/* used for searching thru list of
17324455Smckusick 				 * reserved words */
17424455Smckusick 	register struct templ *p;
17524649Smckusick 	register int c;
1768804Smckusick 
17724649Smckusick 	do {			/* copy it over */
1788804Smckusick 	    *tok++ = *buf_ptr++;
1798804Smckusick 	    if (buf_ptr >= buf_end)
18024455Smckusick 		fill_buffer();
18124649Smckusick 	} while (chartype[c = *buf_ptr & 0177] == alphanum ||
18224649Smckusick 		isdigit(token[0]) && (c == '+' || c == '-') &&
18324649Smckusick 		(tok[-1] == 'e' || tok[-1] == 'E'));
1848804Smckusick 	*tok++ = '\0';
18524455Smckusick 	while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
18624455Smckusick 	    if (++buf_ptr >= buf_end)
18724455Smckusick 		fill_buffer();
18824455Smckusick 	}
18924455Smckusick 	ps.its_a_keyword = false;
19024455Smckusick 	ps.sizeof_keyword = false;
19124455Smckusick 	if (l_struct) {		/* if last token was 'struct', then this
19224455Smckusick 				 * token should be treated as a
19324455Smckusick 				 * declaration */
1948804Smckusick 	    l_struct = false;
1958804Smckusick 	    last_code = ident;
19624455Smckusick 	    ps.last_u_d = true;
1978804Smckusick 	    return (decl);
1988804Smckusick 	}
19924455Smckusick 	ps.last_u_d = false;	/* Operator after indentifier is binary */
20024455Smckusick 	last_code = ident;	/* Remember that this is the code we will
20124455Smckusick 				 * return */
2028804Smckusick 
20324455Smckusick 	/*
20424455Smckusick 	 * This loop will check if the token is a keyword.
20524455Smckusick 	 */
20624455Smckusick 	for (p = specials; (j = p->rwd) != 0; p++) {
20724455Smckusick 	    tok = token;	/* point at scanned token */
20824455Smckusick 	    if (*j++ != *tok++ || *j++ != *tok++)
20924455Smckusick 		continue;	/* This test depends on the fact that
21024455Smckusick 				 * identifiers are always at least 1
21124455Smckusick 				 * character long (ie. the first two bytes
21224455Smckusick 				 * of the identifier are always
21324455Smckusick 				 * meaningful) */
21424455Smckusick 	    if (tok[-1] == 0)
21524455Smckusick 		break;		/* If its a one-character identifier */
21624455Smckusick 	    while (*tok++ == *j)
21724455Smckusick 		if (*j++ == 0)
21824455Smckusick 		    goto found_keyword;	/* I wish that C had a multi-level
21924455Smckusick 					 * break... */
22024455Smckusick 	}
22124455Smckusick 	if (p->rwd) {		/* we have a keyword */
22224455Smckusick     found_keyword:
22324455Smckusick 	    ps.its_a_keyword = true;
22424455Smckusick 	    ps.last_u_d = true;
22524455Smckusick 	    switch (p->rwcode) {
22624455Smckusick 		case 1:	/* it is a switch */
22724455Smckusick 		    return (swstmt);
22824455Smckusick 		case 2:	/* a case or default */
22924455Smckusick 		    return (casestmt);
2308804Smckusick 
23124455Smckusick 		case 3:	/* a "struct" */
23224455Smckusick 		    if (ps.p_l_follow)
23324455Smckusick 			break;	/* inside parens: cast */
23424455Smckusick 		    l_struct = true;
2358804Smckusick 
23624455Smckusick 		    /*
23724455Smckusick 		     * Next time around, we will want to know that we have
23824455Smckusick 		     * had a 'struct'
23924455Smckusick 		     */
24024455Smckusick 		case 4:	/* one of the declaration keywords */
24124455Smckusick 		    if (ps.p_l_follow) {
24224455Smckusick 			ps.cast_mask |= 1 << ps.p_l_follow;
24324455Smckusick 			break;	/* inside parens: cast */
24424455Smckusick 		    }
24524455Smckusick 		    last_code = decl;
24624455Smckusick 		    return (decl);
2478804Smckusick 
24824455Smckusick 		case 5:	/* if, while, for */
24924455Smckusick 		    return (sp_paren);
2508804Smckusick 
25124455Smckusick 		case 6:	/* do, else */
25224455Smckusick 		    return (sp_nparen);
2538804Smckusick 
25424455Smckusick 		case 7:
25524455Smckusick 		    ps.sizeof_keyword = true;
25624455Smckusick 		default:	/* all others are treated like any other
25724455Smckusick 				 * identifier */
25824455Smckusick 		    return (ident);
25924455Smckusick 	    }			/* end of switch */
26024455Smckusick 	}			/* end of if (found_it) */
26124455Smckusick 	if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0
26224455Smckusick 	    && (buf_ptr[1] != ')' || buf_ptr[2] != ';')) {
26324455Smckusick 	    strncpy(ps.procname, token, sizeof ps.procname - 1);
26424455Smckusick 	    ps.in_parameter_declaration = 1;
26524455Smckusick 	}
2668804Smckusick 
26724455Smckusick 	/*
26824455Smckusick 	 * The following hack attempts to guess whether or not the current
26924455Smckusick 	 * token is in fact a declaration keyword -- one that has been
27024455Smckusick 	 * typedefd
27124455Smckusick 	 */
27224455Smckusick 	if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr))
27324455Smckusick 	    && !ps.p_l_follow
27424455Smckusick 	    && (ps.last_token == rparen || ps.last_token == semicolon ||
27524455Smckusick 		ps.last_token == decl ||
27624455Smckusick 		ps.last_token == lbrace || ps.last_token == rbrace)) {
27724455Smckusick 	    ps.its_a_keyword = true;
27824455Smckusick 	    ps.last_u_d = true;
27924455Smckusick 	    last_code = decl;
28024455Smckusick 	    return decl;
2818804Smckusick 	}
28224455Smckusick 	if (last_code == decl)	/* if this is a declared variable, then
28324455Smckusick 				 * following sign is unary */
28424455Smckusick 	    ps.last_u_d = true;	/* will make "int a -1" work */
2858804Smckusick 	last_code = ident;
28624455Smckusick 	return (ident);		/* the ident is not in the list */
28724455Smckusick     }				/* end of procesing for alpanum character */
28824649Smckusick     /* Scan a non-alphanumeric token */
2898804Smckusick 
29024455Smckusick     *tok++ = *buf_ptr;		/* if it is only a one-character token, it
29124455Smckusick 				 * is moved here */
2928804Smckusick     *tok = '\0';
2938804Smckusick     if (++buf_ptr >= buf_end)
29424455Smckusick 	fill_buffer();
2958804Smckusick 
2968804Smckusick     switch (*token) {
29724455Smckusick 	case '\n':
29824455Smckusick 	    unary_delim = ps.last_u_d;
29924455Smckusick 	    ps.last_nl = true;	/* remember that we just had a newline */
3008804Smckusick 	    code = (had_eof ? 0 : newline);
30124455Smckusick 
30224455Smckusick 	    /*
30324455Smckusick 	     * if data has been exausted, the newline is a dummy, and we
30424455Smckusick 	     * should return code to stop
30524455Smckusick 	     */
3068804Smckusick 	    break;
3078804Smckusick 
30824455Smckusick 	case '\'':		/* start of quoted character */
30924455Smckusick 	case '"':		/* start of string */
31024455Smckusick 	    qchar = *token;
31124455Smckusick 	    if (troff) {
31224455Smckusick 		tok[-1] = '`';
31324455Smckusick 		if (qchar == '"')
31424455Smckusick 		    *tok++ = '`';
31524455Smckusick 		*tok++ = BACKSLASH;
31624455Smckusick 		*tok++ = 'f';
31724455Smckusick 		*tok++ = 'L';
31824455Smckusick 	    }
31924455Smckusick 	    do {		/* copy the string */
32024455Smckusick 		while (1) {	/* move one character or [/<char>]<char> */
3218804Smckusick 		    if (*buf_ptr == '\n') {
32224455Smckusick 			printf("%d: Unterminated literal\n", line_no);
3238804Smckusick 			goto stop_lit;
3248804Smckusick 		    }
3258804Smckusick 		    *tok = *buf_ptr++;
3268804Smckusick 		    if (buf_ptr >= buf_end)
32724455Smckusick 			fill_buffer();
3288804Smckusick 		    if (had_eof || ((tok - token) > (bufsize - 2))) {
32924455Smckusick 			printf("Unterminated literal\n");
3308804Smckusick 			++tok;
3318804Smckusick 			goto stop_lit;
33224455Smckusick 			/* get outof literal copying loop */
3338804Smckusick 		    }
33424455Smckusick 		    if (*tok == BACKSLASH) {	/* if escape, copy extra
33524455Smckusick 						 * char */
33624455Smckusick 			if (*buf_ptr == '\n')	/* check for escaped
33724455Smckusick 						 * newline */
3388804Smckusick 			    ++line_no;
33924455Smckusick 			if (troff) {
34024455Smckusick 			    *++tok = BACKSLASH;
34124455Smckusick 			    if (*buf_ptr == BACKSLASH)
34224455Smckusick 				*++tok = BACKSLASH;
34324455Smckusick 			}
34424455Smckusick 			*++tok = *buf_ptr++;
34524455Smckusick 			++tok;	/* we must increment this again because we
34624455Smckusick 				 * copied two chars */
3478804Smckusick 			if (buf_ptr >= buf_end)
34824455Smckusick 			    fill_buffer();
3498804Smckusick 		    }
3508804Smckusick 		    else
35124455Smckusick 			break;	/* we copied one character */
35224455Smckusick 		}		/* end of while (1) */
3538804Smckusick 	    } while (*tok++ != qchar);
35424455Smckusick 	    if (troff) {
35524455Smckusick 		tok[-1] = BACKSLASH;
35624455Smckusick 		*tok++ = 'f';
35724455Smckusick 		*tok++ = 'R';
35824455Smckusick 		*tok++ = '\'';
35924455Smckusick 		if (qchar == '"')
36024455Smckusick 		    *tok++ = '\'';
36124455Smckusick 	    }
36224455Smckusick     stop_lit:
3638804Smckusick 	    code = ident;
3648804Smckusick 	    break;
3658804Smckusick 
36624455Smckusick 	case ('('):
36724455Smckusick 	case ('['):
3688804Smckusick 	    unary_delim = true;
3698804Smckusick 	    code = lparen;
3708804Smckusick 	    break;
3718804Smckusick 
37224455Smckusick 	case (')'):
37324455Smckusick 	case (']'):
3748804Smckusick 	    code = rparen;
3758804Smckusick 	    break;
3768804Smckusick 
37724455Smckusick 	case '#':
37824455Smckusick 	    unary_delim = ps.last_u_d;
3798804Smckusick 	    code = preesc;
3808804Smckusick 	    break;
3818804Smckusick 
38224455Smckusick 	case '?':
3838804Smckusick 	    unary_delim = true;
3848804Smckusick 	    code = question;
3858804Smckusick 	    break;
3868804Smckusick 
38724455Smckusick 	case (':'):
3888804Smckusick 	    code = colon;
3898804Smckusick 	    unary_delim = true;
3908804Smckusick 	    break;
3918804Smckusick 
39224455Smckusick 	case (';'):
3938804Smckusick 	    unary_delim = true;
3948804Smckusick 	    code = semicolon;
3958804Smckusick 	    break;
3968804Smckusick 
39724455Smckusick 	case ('{'):
3988804Smckusick 	    unary_delim = true;
39924455Smckusick 
40024455Smckusick 	    /*
40124455Smckusick 	     * if (ps.in_or_st) ps.block_init = 1;
40224455Smckusick 	     */
40324455Smckusick 	    code = ps.block_init ? lparen : lbrace;
4048804Smckusick 	    break;
4058804Smckusick 
40624455Smckusick 	case ('}'):
4078804Smckusick 	    unary_delim = true;
40824455Smckusick 	    code = ps.block_init ? rparen : rbrace;
4098804Smckusick 	    break;
4108804Smckusick 
41124455Smckusick 	case 014:		/* a form feed */
41224455Smckusick 	    unary_delim = ps.last_u_d;
41324455Smckusick 	    ps.last_nl = true;	/* remember this so we can set 'ps.col_1'
41424455Smckusick 				 * right */
4158804Smckusick 	    code = form_feed;
4168804Smckusick 	    break;
4178804Smckusick 
41824455Smckusick 	case (','):
4198804Smckusick 	    unary_delim = true;
4208804Smckusick 	    code = comma;
4218804Smckusick 	    break;
4228804Smckusick 
42324455Smckusick 	case '.':
4248804Smckusick 	    unary_delim = false;
4258804Smckusick 	    code = period;
4268804Smckusick 	    break;
4278804Smckusick 
42824455Smckusick 	case '-':
42924455Smckusick 	case '+':		/* check for -, +, --, ++ */
43024455Smckusick 	    code = (ps.last_u_d ? unary_op : binary_op);
4318804Smckusick 	    unary_delim = true;
4328804Smckusick 
4338804Smckusick 	    if (*buf_ptr == token[0]) {
43424455Smckusick 		/* check for doubled character */
4358804Smckusick 		*tok++ = *buf_ptr++;
43624455Smckusick 		/* buffer overflow will be checked at end of loop */
4378804Smckusick 		if (last_code == ident || last_code == rparen) {
43824455Smckusick 		    code = (ps.last_u_d ? unary_op : postop);
43924455Smckusick 		    /* check for following ++ or -- */
4408804Smckusick 		    unary_delim = false;
4418804Smckusick 		}
4428804Smckusick 	    }
44324455Smckusick 	    else if (*buf_ptr == '=')
44424455Smckusick 		/* check for operator += */
44524455Smckusick 		*tok++ = *buf_ptr++;
44624677Smckusick 	    else if (token[0] == '-' && *buf_ptr == '>') {
44724455Smckusick 		/* check for operator -> */
44824455Smckusick 		*tok++ = *buf_ptr++;
44924677Smckusick 		if (!pointer_as_binop) {
45024677Smckusick 		    code = unary_op;
45124677Smckusick 		    unary_delim = false;
45224677Smckusick 		    ps.want_blank = false;
45324677Smckusick 		}
45424455Smckusick 	    }
45524455Smckusick 	    /* buffer overflow will be checked at end of switch */
4568804Smckusick 
4578804Smckusick 	    break;
4588804Smckusick 
45924455Smckusick 	case '=':
46024455Smckusick 	    if (ps.in_or_st)
46124455Smckusick 		ps.block_init = 1;
46224455Smckusick 	    if (chartype[*buf_ptr] == opchar) {	/* we have two char
46324455Smckusick 						 * assignment */
46424455Smckusick 		tok[-1] = *buf_ptr++;
46524455Smckusick 		if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr)
46624455Smckusick 		    *tok++ = *buf_ptr++;
46724455Smckusick 		*tok++ = '=';	/* Flip =+ to += */
46824455Smckusick 		*tok = 0;
4698804Smckusick 	    }
4708804Smckusick 	    code = binary_op;
4718804Smckusick 	    unary_delim = true;
47224455Smckusick 	    break;
47324455Smckusick 	    /* can drop thru!!! */
4748804Smckusick 
47524455Smckusick 	case '>':
47624455Smckusick 	case '<':
47724455Smckusick 	case '!':		/* ops like <, <<, <=, !=, etc */
4788804Smckusick 	    if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
4798804Smckusick 		*tok++ = *buf_ptr;
4808804Smckusick 		if (++buf_ptr >= buf_end)
48124455Smckusick 		    fill_buffer();
4828804Smckusick 	    }
4838804Smckusick 	    if (*buf_ptr == '=')
48424455Smckusick 		*tok++ = *buf_ptr++;
48524455Smckusick 	    code = (ps.last_u_d ? unary_op : binary_op);
4868804Smckusick 	    unary_delim = true;
4878804Smckusick 	    break;
4888804Smckusick 
48924455Smckusick 	default:
4908804Smckusick 	    if (token[0] == '/' && *buf_ptr == '*') {
49124455Smckusick 		/* it is start of comment */
4928804Smckusick 		*tok++ = '*';
4938804Smckusick 
4948804Smckusick 		if (++buf_ptr >= buf_end)
49524455Smckusick 		    fill_buffer();
4968804Smckusick 
4978804Smckusick 		code = comment;
49824455Smckusick 		unary_delim = ps.last_u_d;
4998804Smckusick 		break;
5008804Smckusick 	    }
50124455Smckusick 	    while (*(tok - 1) == *buf_ptr || *buf_ptr == '=') {
50224455Smckusick 		/* handle ||, &&, etc, and also things as in int *****i */
5038804Smckusick 		*tok++ = *buf_ptr;
5048804Smckusick 		if (++buf_ptr >= buf_end)
50524455Smckusick 		    fill_buffer();
5068804Smckusick 	    }
50724455Smckusick 	    code = (ps.last_u_d ? unary_op : binary_op);
5088804Smckusick 	    unary_delim = true;
5098804Smckusick 
5108804Smckusick 
51124455Smckusick     }				/* end of switch */
5128804Smckusick     if (code != newline) {
5138804Smckusick 	l_struct = false;
5148804Smckusick 	last_code = code;
5158804Smckusick     }
51624455Smckusick     if (buf_ptr >= buf_end)	/* check for input buffer empty */
51724455Smckusick 	fill_buffer();
51824455Smckusick     ps.last_u_d = unary_delim;
51924455Smckusick     *tok = '\0';		/* null terminate the token */
5208804Smckusick     return (code);
5218804Smckusick };
52224455Smckusick 
52324455Smckusick /* Add the given keyword to the keyword table, using val as the keyword type
52424455Smckusick    */
52524455Smckusick addkey (key, val)
52624455Smckusick char       *key;
52724455Smckusick {
52824455Smckusick     register struct templ *p = specials;
52924455Smckusick     while (p->rwd)
53024455Smckusick 	if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
53124455Smckusick 	    return;
53224455Smckusick 	else
53324455Smckusick 	    p++;
53424455Smckusick     if (p >= specials + sizeof specials / sizeof specials[0])
53524455Smckusick 	return;			/* For now, table overflows are silently
53624455Smckusick 				   ignored */
53724455Smckusick     p->rwd = key;
53824455Smckusick     p->rwcode = val;
53924455Smckusick     p[1].rwd = 0;
54024455Smckusick     p[1].rwcode = 0;
54124455Smckusick     return;
54224455Smckusick }
543