xref: /csrg-svn/usr.bin/indent/lexi.c (revision 24455)
121970Sdist /*
221970Sdist  * Copyright (c) 1980 Regents of the University of California.
321970Sdist  * All rights reserved.  The Berkeley software License Agreement
421970Sdist  * specifies the terms and conditions for redistribution.
521970Sdist  */
68804Smckusick 
721970Sdist #ifndef lint
8*24455Smckusick static char sccsid[] = "@(#)lexi.c	5.2 (Berkeley) 08/28/85";
921970Sdist #endif not lint
1021970Sdist 
11*24455Smckusick /*-
12*24455Smckusick  *
13*24455Smckusick  *			  Copyright (C) 1976
14*24455Smckusick  *				by the
15*24455Smckusick  *			  Board of Trustees
16*24455Smckusick  *				of the
17*24455Smckusick  *			University of Illinois
18*24455Smckusick  *
19*24455Smckusick  *			 All rights reserved
20*24455Smckusick  *
21*24455Smckusick  *
22*24455Smckusick  * NAME:
23*24455Smckusick  *	lexi
24*24455Smckusick  *
25*24455Smckusick  * FUNCTION:
26*24455Smckusick  *	This is the token scanner for indent
27*24455Smckusick  *
28*24455Smckusick  * ALGORITHM:
29*24455Smckusick  *	1) Strip off intervening blanks and/or tabs.
30*24455Smckusick  *	2) If it is an alphanumeric token, move it to the token buffer "token".
31*24455Smckusick  *	   Check if it is a special reserved word that indent will want to
32*24455Smckusick  *	   know about.
33*24455Smckusick  *	3) Non-alphanumeric tokens are handled with a big switch statement.  A
34*24455Smckusick  *	   flag is kept to remember if the last token was a "unary delimiter",
35*24455Smckusick  *	   which forces a following operator to be unary as opposed to binary.
36*24455Smckusick  *
37*24455Smckusick  * PARAMETERS:
38*24455Smckusick  *	None
39*24455Smckusick  *
40*24455Smckusick  * RETURNS:
41*24455Smckusick  *	An integer code indicating the type of token scanned.
42*24455Smckusick  *
43*24455Smckusick  * GLOBALS:
44*24455Smckusick  *	buf_ptr =
45*24455Smckusick  *	had_eof
46*24455Smckusick  *	ps.last_u_d =	Set to true iff this token is a "unary delimiter"
47*24455Smckusick  *
48*24455Smckusick  * CALLS:
49*24455Smckusick  *	fill_buffer
50*24455Smckusick  *	printf (lib)
51*24455Smckusick  *
52*24455Smckusick  * CALLED BY:
53*24455Smckusick  *	main
54*24455Smckusick  *
55*24455Smckusick  * NOTES:
56*24455Smckusick  *	Start of comment is passed back so that the comment can be scanned by
57*24455Smckusick  *	pr_comment.
58*24455Smckusick  *
59*24455Smckusick  *	Strings and character literals are returned just like identifiers.
60*24455Smckusick  *
61*24455Smckusick  * HISTORY:
62*24455Smckusick  *	initial coding 	November 1976	D A Willcox of CAC
63*24455Smckusick  *	1/7/77		D A Willcox of CAC	Fix to provide proper handling
64*24455Smckusick  *						of "int a -1;"
65*24455Smckusick  *
66*24455Smckusick  */
67*24455Smckusick 
688804Smckusick /*
69*24455Smckusick  * Here we have the token scanner for indent.  It scans off one token and
70*24455Smckusick  * puts it in the global variable "token".  It returns a code, indicating
71*24455Smckusick  * the type of token scanned.
72*24455Smckusick  */
738804Smckusick 
748804Smckusick #include "indent_globs.h";
758804Smckusick #include "indent_codes.h";
76*24455Smckusick #include "ctype.h"
778804Smckusick 
788804Smckusick #define alphanum 1
798804Smckusick #define opchar 3
808804Smckusick 
818804Smckusick struct templ {
82*24455Smckusick     char       *rwd;
83*24455Smckusick     int         rwcode;
848804Smckusick };
858804Smckusick 
86*24455Smckusick struct templ specials[100] =
878804Smckusick {
888804Smckusick     "switch", 1,
898804Smckusick     "case", 2,
90*24455Smckusick     "break", 0,
918804Smckusick     "struct", 3,
92*24455Smckusick     "union", 3,
93*24455Smckusick     "enum", 3,
948804Smckusick     "default", 2,
958804Smckusick     "int", 4,
968804Smckusick     "char", 4,
978804Smckusick     "float", 4,
988804Smckusick     "double", 4,
998804Smckusick     "long", 4,
1008804Smckusick     "short", 4,
1018804Smckusick     "typdef", 4,
1028804Smckusick     "unsigned", 4,
1038804Smckusick     "register", 4,
1048804Smckusick     "static", 4,
1058804Smckusick     "global", 4,
1068804Smckusick     "extern", 4,
107*24455Smckusick     "void", 4,
108*24455Smckusick     "goto", 0,
109*24455Smckusick     "return", 0,
1108804Smckusick     "if", 5,
1118804Smckusick     "while", 5,
1128804Smckusick     "for", 5,
1138804Smckusick     "else", 6,
1148804Smckusick     "do", 6,
115*24455Smckusick     "sizeof", 7,
1168804Smckusick     0, 0
1178804Smckusick };
1188804Smckusick 
119*24455Smckusick char        chartype[128] =
120*24455Smckusick {				/* this is used to facilitate the decision
121*24455Smckusick 				 * of what type (alphanumeric, operator)
122*24455Smckusick 				 * each character is */
1238804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1248804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1258804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1268804Smckusick     0, 0, 0, 0, 0, 0, 0, 0,
1278804Smckusick     0, 3, 0, 0, 0, 3, 3, 0,
1288804Smckusick     0, 0, 3, 3, 0, 3, 3, 3,
1298804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1308804Smckusick     1, 1, 0, 0, 3, 3, 3, 3,
1318804Smckusick     0, 1, 1, 1, 1, 1, 1, 1,
1328804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1338804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1348804Smckusick     1, 1, 1, 0, 0, 0, 3, 1,
1358804Smckusick     0, 1, 1, 1, 1, 1, 1, 1,
1368804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1378804Smckusick     1, 1, 1, 1, 1, 1, 1, 1,
1388804Smckusick     1, 1, 1, 0, 3, 0, 3, 0
1398804Smckusick };
1408804Smckusick 
1418804Smckusick 
1428804Smckusick 
1438804Smckusick 
144*24455Smckusick int
145*24455Smckusick lexi()
146*24455Smckusick {
147*24455Smckusick     register char *tok;		/* local pointer to next char in token */
148*24455Smckusick     int         unary_delim;	/* this is set to 1 if the current token
149*24455Smckusick 				 *
150*24455Smckusick 				 * forces a following operator to be unary */
151*24455Smckusick     static int  last_code;	/* the last token type returned */
152*24455Smckusick     static int  l_struct;	/* set to 1 if the last token was 'struct' */
153*24455Smckusick     int         code;		/* internal code to be returned */
154*24455Smckusick     char        qchar;		/* the delimiter character for a string */
1558804Smckusick 
156*24455Smckusick     tok = token;		/* point to start of place to save token */
1578804Smckusick     unary_delim = false;
158*24455Smckusick     ps.col_1 = ps.last_nl;	/* tell world that this token started in
159*24455Smckusick 				 * column 1 iff the last thing scanned was
160*24455Smckusick 				 * nl */
161*24455Smckusick     ps.last_nl = false;
1628804Smckusick 
163*24455Smckusick     while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
164*24455Smckusick 	ps.col_1 = false;	/* leading blanks imply token is not in
165*24455Smckusick 				 * column 1 */
1668804Smckusick 	if (++buf_ptr >= buf_end)
167*24455Smckusick 	    fill_buffer();
1688804Smckusick     }
1698804Smckusick 
170*24455Smckusick     /* Scan an alphanumeric token */
171*24455Smckusick     if (chartype[*buf_ptr & 0177] == alphanum) {	/* we have a character
172*24455Smckusick 							 * or number */
173*24455Smckusick 	register char *j;	/* used for searching thru list of
174*24455Smckusick 				 *
175*24455Smckusick 				 * reserved words */
176*24455Smckusick 	register struct templ *p;
1778804Smckusick 
178*24455Smckusick 	while (chartype[*buf_ptr & 0177] == alphanum) {	/* copy it over */
1798804Smckusick 	    *tok++ = *buf_ptr++;
1808804Smckusick 	    if (buf_ptr >= buf_end)
181*24455Smckusick 		fill_buffer();
1828804Smckusick 	}
1838804Smckusick 	*tok++ = '\0';
184*24455Smckusick 	while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
185*24455Smckusick 	    if (++buf_ptr >= buf_end)
186*24455Smckusick 		fill_buffer();
187*24455Smckusick 	}
188*24455Smckusick 	ps.its_a_keyword = false;
189*24455Smckusick 	ps.sizeof_keyword = false;
190*24455Smckusick 	if (l_struct) {		/* if last token was 'struct', then this
191*24455Smckusick 				 * token should be treated as a
192*24455Smckusick 				 * declaration */
1938804Smckusick 	    l_struct = false;
1948804Smckusick 	    last_code = ident;
195*24455Smckusick 	    ps.last_u_d = true;
1968804Smckusick 	    return (decl);
1978804Smckusick 	}
198*24455Smckusick 	ps.last_u_d = false;	/* Operator after indentifier is binary */
199*24455Smckusick 	last_code = ident;	/* Remember that this is the code we will
200*24455Smckusick 				 * return */
2018804Smckusick 
202*24455Smckusick 	/*
203*24455Smckusick 	 * This loop will check if the token is a keyword.
204*24455Smckusick 	 */
205*24455Smckusick 	for (p = specials; (j = p->rwd) != 0; p++) {
206*24455Smckusick 	    tok = token;	/* point at scanned token */
207*24455Smckusick 	    if (*j++ != *tok++ || *j++ != *tok++)
208*24455Smckusick 		continue;	/* This test depends on the fact that
209*24455Smckusick 				 * identifiers are always at least 1
210*24455Smckusick 				 * character long (ie. the first two bytes
211*24455Smckusick 				 * of the identifier are always
212*24455Smckusick 				 * meaningful) */
213*24455Smckusick 	    if (tok[-1] == 0)
214*24455Smckusick 		break;		/* If its a one-character identifier */
215*24455Smckusick 	    while (*tok++ == *j)
216*24455Smckusick 		if (*j++ == 0)
217*24455Smckusick 		    goto found_keyword;	/* I wish that C had a multi-level
218*24455Smckusick 					 * break... */
219*24455Smckusick 	}
220*24455Smckusick 	if (p->rwd) {		/* we have a keyword */
221*24455Smckusick     found_keyword:
222*24455Smckusick 	    ps.its_a_keyword = true;
223*24455Smckusick 	    ps.last_u_d = true;
224*24455Smckusick 	    switch (p->rwcode) {
225*24455Smckusick 		case 1:	/* it is a switch */
226*24455Smckusick 		    return (swstmt);
227*24455Smckusick 		case 2:	/* a case or default */
228*24455Smckusick 		    return (casestmt);
2298804Smckusick 
230*24455Smckusick 		case 3:	/* a "struct" */
231*24455Smckusick 		    if (ps.p_l_follow)
232*24455Smckusick 			break;	/* inside parens: cast */
233*24455Smckusick 		    l_struct = true;
2348804Smckusick 
235*24455Smckusick 		    /*
236*24455Smckusick 		     * Next time around, we will want to know that we have
237*24455Smckusick 		     * had a 'struct'
238*24455Smckusick 		     */
239*24455Smckusick 		case 4:	/* one of the declaration keywords */
240*24455Smckusick 		    if (ps.p_l_follow) {
241*24455Smckusick 			ps.cast_mask |= 1 << ps.p_l_follow;
242*24455Smckusick 			break;	/* inside parens: cast */
243*24455Smckusick 		    }
244*24455Smckusick 		    last_code = decl;
245*24455Smckusick 		    return (decl);
2468804Smckusick 
247*24455Smckusick 		case 5:	/* if, while, for */
248*24455Smckusick 		    return (sp_paren);
2498804Smckusick 
250*24455Smckusick 		case 6:	/* do, else */
251*24455Smckusick 		    return (sp_nparen);
2528804Smckusick 
253*24455Smckusick 		case 7:
254*24455Smckusick 		    ps.sizeof_keyword = true;
255*24455Smckusick 		default:	/* all others are treated like any other
256*24455Smckusick 				 * identifier */
257*24455Smckusick 		    return (ident);
258*24455Smckusick 	    }			/* end of switch */
259*24455Smckusick 	}			/* end of if (found_it) */
260*24455Smckusick 	if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0
261*24455Smckusick 	    && (buf_ptr[1] != ')' || buf_ptr[2] != ';')) {
262*24455Smckusick 	    strncpy(ps.procname, token, sizeof ps.procname - 1);
263*24455Smckusick 	    ps.in_parameter_declaration = 1;
264*24455Smckusick 	}
2658804Smckusick 
266*24455Smckusick 	/*
267*24455Smckusick 	 * The following hack attempts to guess whether or not the current
268*24455Smckusick 	 * token is in fact a declaration keyword -- one that has been
269*24455Smckusick 	 * typedefd
270*24455Smckusick 	 */
271*24455Smckusick 	if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr))
272*24455Smckusick 	    && !ps.p_l_follow
273*24455Smckusick 	    && (ps.last_token == rparen || ps.last_token == semicolon ||
274*24455Smckusick 		ps.last_token == decl ||
275*24455Smckusick 		ps.last_token == lbrace || ps.last_token == rbrace)) {
276*24455Smckusick 	    ps.its_a_keyword = true;
277*24455Smckusick 	    ps.last_u_d = true;
278*24455Smckusick 	    last_code = decl;
279*24455Smckusick 	    return decl;
2808804Smckusick 	}
281*24455Smckusick 	if (last_code == decl)	/* if this is a declared variable, then
282*24455Smckusick 				 * following sign is unary */
283*24455Smckusick 	    ps.last_u_d = true;	/* will make "int a -1" work */
2848804Smckusick 	last_code = ident;
285*24455Smckusick 	return (ident);		/* the ident is not in the list */
286*24455Smckusick     }				/* end of procesing for alpanum character */
287*24455Smckusick     /* l l Scan a non-alphanumeric token */
2888804Smckusick 
289*24455Smckusick     *tok++ = *buf_ptr;		/* if it is only a one-character token, it
290*24455Smckusick 				 * is moved here */
2918804Smckusick     *tok = '\0';
2928804Smckusick     if (++buf_ptr >= buf_end)
293*24455Smckusick 	fill_buffer();
2948804Smckusick 
2958804Smckusick     switch (*token) {
296*24455Smckusick 	case '\n':
297*24455Smckusick 	    unary_delim = ps.last_u_d;
298*24455Smckusick 	    ps.last_nl = true;	/* remember that we just had a newline */
2998804Smckusick 	    code = (had_eof ? 0 : newline);
300*24455Smckusick 
301*24455Smckusick 	    /*
302*24455Smckusick 	     * if data has been exausted, the newline is a dummy, and we
303*24455Smckusick 	     * should return code to stop
304*24455Smckusick 	     */
3058804Smckusick 	    break;
3068804Smckusick 
307*24455Smckusick 	case '\'':		/* start of quoted character */
308*24455Smckusick 	case '"':		/* start of string */
309*24455Smckusick 	    qchar = *token;
310*24455Smckusick 	    if (troff) {
311*24455Smckusick 		tok[-1] = '`';
312*24455Smckusick 		if (qchar == '"')
313*24455Smckusick 		    *tok++ = '`';
314*24455Smckusick 		*tok++ = BACKSLASH;
315*24455Smckusick 		*tok++ = 'f';
316*24455Smckusick 		*tok++ = 'L';
317*24455Smckusick 	    }
318*24455Smckusick 	    do {		/* copy the string */
319*24455Smckusick 		while (1) {	/* move one character or [/<char>]<char> */
3208804Smckusick 		    if (*buf_ptr == '\n') {
321*24455Smckusick 			printf("%d: Unterminated literal\n", line_no);
3228804Smckusick 			goto stop_lit;
3238804Smckusick 		    }
3248804Smckusick 		    *tok = *buf_ptr++;
3258804Smckusick 		    if (buf_ptr >= buf_end)
326*24455Smckusick 			fill_buffer();
3278804Smckusick 		    if (had_eof || ((tok - token) > (bufsize - 2))) {
328*24455Smckusick 			printf("Unterminated literal\n");
3298804Smckusick 			++tok;
3308804Smckusick 			goto stop_lit;
331*24455Smckusick 			/* get outof literal copying loop */
3328804Smckusick 		    }
333*24455Smckusick 		    if (*tok == BACKSLASH) {	/* if escape, copy extra
334*24455Smckusick 						 * char */
335*24455Smckusick 			if (*buf_ptr == '\n')	/* check for escaped
336*24455Smckusick 						 * newline */
3378804Smckusick 			    ++line_no;
338*24455Smckusick 			if (troff) {
339*24455Smckusick 			    *++tok = BACKSLASH;
340*24455Smckusick 			    if (*buf_ptr == BACKSLASH)
341*24455Smckusick 				*++tok = BACKSLASH;
342*24455Smckusick 			}
343*24455Smckusick 			*++tok = *buf_ptr++;
344*24455Smckusick 			++tok;	/* we must increment this again because we
345*24455Smckusick 				 * copied two chars */
3468804Smckusick 			if (buf_ptr >= buf_end)
347*24455Smckusick 			    fill_buffer();
3488804Smckusick 		    }
3498804Smckusick 		    else
350*24455Smckusick 			break;	/* we copied one character */
351*24455Smckusick 		}		/* end of while (1) */
3528804Smckusick 	    } while (*tok++ != qchar);
353*24455Smckusick 	    if (troff) {
354*24455Smckusick 		tok[-1] = BACKSLASH;
355*24455Smckusick 		*tok++ = 'f';
356*24455Smckusick 		*tok++ = 'R';
357*24455Smckusick 		*tok++ = '\'';
358*24455Smckusick 		if (qchar == '"')
359*24455Smckusick 		    *tok++ = '\'';
360*24455Smckusick 	    }
361*24455Smckusick     stop_lit:
3628804Smckusick 	    code = ident;
3638804Smckusick 	    break;
3648804Smckusick 
365*24455Smckusick 	case ('('):
366*24455Smckusick 	case ('['):
3678804Smckusick 	    unary_delim = true;
3688804Smckusick 	    code = lparen;
3698804Smckusick 	    break;
3708804Smckusick 
371*24455Smckusick 	case (')'):
372*24455Smckusick 	case (']'):
3738804Smckusick 	    code = rparen;
3748804Smckusick 	    break;
3758804Smckusick 
376*24455Smckusick 	case '#':
377*24455Smckusick 	    unary_delim = ps.last_u_d;
3788804Smckusick 	    code = preesc;
3798804Smckusick 	    break;
3808804Smckusick 
381*24455Smckusick 	case '?':
3828804Smckusick 	    unary_delim = true;
3838804Smckusick 	    code = question;
3848804Smckusick 	    break;
3858804Smckusick 
386*24455Smckusick 	case (':'):
3878804Smckusick 	    code = colon;
3888804Smckusick 	    unary_delim = true;
3898804Smckusick 	    break;
3908804Smckusick 
391*24455Smckusick 	case (';'):
3928804Smckusick 	    unary_delim = true;
3938804Smckusick 	    code = semicolon;
3948804Smckusick 	    break;
3958804Smckusick 
396*24455Smckusick 	case ('{'):
3978804Smckusick 	    unary_delim = true;
398*24455Smckusick 
399*24455Smckusick 	    /*
400*24455Smckusick 	     * if (ps.in_or_st) ps.block_init = 1;
401*24455Smckusick 	     */
402*24455Smckusick 	    code = ps.block_init ? lparen : lbrace;
4038804Smckusick 	    break;
4048804Smckusick 
405*24455Smckusick 	case ('}'):
4068804Smckusick 	    unary_delim = true;
407*24455Smckusick 	    code = ps.block_init ? rparen : rbrace;
4088804Smckusick 	    break;
4098804Smckusick 
410*24455Smckusick 	case 014:		/* a form feed */
411*24455Smckusick 	    unary_delim = ps.last_u_d;
412*24455Smckusick 	    ps.last_nl = true;	/* remember this so we can set 'ps.col_1'
413*24455Smckusick 				 * right */
4148804Smckusick 	    code = form_feed;
4158804Smckusick 	    break;
4168804Smckusick 
417*24455Smckusick 	case (','):
4188804Smckusick 	    unary_delim = true;
4198804Smckusick 	    code = comma;
4208804Smckusick 	    break;
4218804Smckusick 
422*24455Smckusick 	case '.':
4238804Smckusick 	    unary_delim = false;
4248804Smckusick 	    code = period;
4258804Smckusick 	    break;
4268804Smckusick 
427*24455Smckusick 	case '-':
428*24455Smckusick 	case '+':		/* check for -, +, --, ++ */
429*24455Smckusick 	    code = (ps.last_u_d ? unary_op : binary_op);
4308804Smckusick 	    unary_delim = true;
4318804Smckusick 
4328804Smckusick 	    if (*buf_ptr == token[0]) {
433*24455Smckusick 		/* check for doubled character */
4348804Smckusick 		*tok++ = *buf_ptr++;
435*24455Smckusick 		/* buffer overflow will be checked at end of loop */
4368804Smckusick 		if (last_code == ident || last_code == rparen) {
437*24455Smckusick 		    code = (ps.last_u_d ? unary_op : postop);
438*24455Smckusick 		    /* check for following ++ or -- */
4398804Smckusick 		    unary_delim = false;
4408804Smckusick 		}
4418804Smckusick 	    }
442*24455Smckusick 	    else if (*buf_ptr == '=')
443*24455Smckusick 		/* check for operator += */
444*24455Smckusick 		*tok++ = *buf_ptr++;
445*24455Smckusick 	    else if (*buf_ptr == '>') {
446*24455Smckusick 		/* check for operator -> */
447*24455Smckusick 		*tok++ = *buf_ptr++;
448*24455Smckusick 		code = unary_op;
449*24455Smckusick 		unary_delim = false;
450*24455Smckusick 		ps.want_blank = false;
451*24455Smckusick 	    }
452*24455Smckusick 	    /* buffer overflow will be checked at end of switch */
4538804Smckusick 
4548804Smckusick 	    break;
4558804Smckusick 
456*24455Smckusick 	case '=':
457*24455Smckusick 	    if (ps.in_or_st)
458*24455Smckusick 		ps.block_init = 1;
459*24455Smckusick 	    if (chartype[*buf_ptr] == opchar) {	/* we have two char
460*24455Smckusick 						 * assignment */
461*24455Smckusick 		tok[-1] = *buf_ptr++;
462*24455Smckusick 		if ((tok[-1] == '<' || tok[-1] == '>') && tok[-1] == *buf_ptr)
463*24455Smckusick 		    *tok++ = *buf_ptr++;
464*24455Smckusick 		*tok++ = '=';	/* Flip =+ to += */
465*24455Smckusick 		*tok = 0;
4668804Smckusick 	    }
4678804Smckusick 	    code = binary_op;
4688804Smckusick 	    unary_delim = true;
469*24455Smckusick 	    break;
470*24455Smckusick 	    /* can drop thru!!! */
4718804Smckusick 
472*24455Smckusick 	case '>':
473*24455Smckusick 	case '<':
474*24455Smckusick 	case '!':		/* ops like <, <<, <=, !=, etc */
4758804Smckusick 	    if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
4768804Smckusick 		*tok++ = *buf_ptr;
4778804Smckusick 		if (++buf_ptr >= buf_end)
478*24455Smckusick 		    fill_buffer();
4798804Smckusick 	    }
4808804Smckusick 	    if (*buf_ptr == '=')
481*24455Smckusick 		*tok++ = *buf_ptr++;
482*24455Smckusick 	    code = (ps.last_u_d ? unary_op : binary_op);
4838804Smckusick 	    unary_delim = true;
4848804Smckusick 	    break;
4858804Smckusick 
486*24455Smckusick 	default:
4878804Smckusick 	    if (token[0] == '/' && *buf_ptr == '*') {
488*24455Smckusick 		/* it is start of comment */
4898804Smckusick 		*tok++ = '*';
4908804Smckusick 
4918804Smckusick 		if (++buf_ptr >= buf_end)
492*24455Smckusick 		    fill_buffer();
4938804Smckusick 
4948804Smckusick 		code = comment;
495*24455Smckusick 		unary_delim = ps.last_u_d;
4968804Smckusick 		break;
4978804Smckusick 	    }
498*24455Smckusick 	    while (*(tok - 1) == *buf_ptr || *buf_ptr == '=') {
499*24455Smckusick 		/* handle ||, &&, etc, and also things as in int *****i */
5008804Smckusick 		*tok++ = *buf_ptr;
5018804Smckusick 		if (++buf_ptr >= buf_end)
502*24455Smckusick 		    fill_buffer();
5038804Smckusick 	    }
504*24455Smckusick 	    code = (ps.last_u_d ? unary_op : binary_op);
5058804Smckusick 	    unary_delim = true;
5068804Smckusick 
5078804Smckusick 
508*24455Smckusick     }				/* end of switch */
5098804Smckusick     if (code != newline) {
5108804Smckusick 	l_struct = false;
5118804Smckusick 	last_code = code;
5128804Smckusick     }
513*24455Smckusick     if (buf_ptr >= buf_end)	/* check for input buffer empty */
514*24455Smckusick 	fill_buffer();
515*24455Smckusick     ps.last_u_d = unary_delim;
516*24455Smckusick     *tok = '\0';		/* null terminate the token */
5178804Smckusick     return (code);
5188804Smckusick };
519*24455Smckusick 
520*24455Smckusick /* Add the given keyword to the keyword table, using val as the keyword type
521*24455Smckusick    */
522*24455Smckusick addkey (key, val)
523*24455Smckusick char       *key;
524*24455Smckusick {
525*24455Smckusick     register struct templ *p = specials;
526*24455Smckusick     while (p->rwd)
527*24455Smckusick 	if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
528*24455Smckusick 	    return;
529*24455Smckusick 	else
530*24455Smckusick 	    p++;
531*24455Smckusick     if (p >= specials + sizeof specials / sizeof specials[0])
532*24455Smckusick 	return;			/* For now, table overflows are silently
533*24455Smckusick 				   ignored */
534*24455Smckusick     p->rwd = key;
535*24455Smckusick     p->rwcode = val;
536*24455Smckusick     p[1].rwd = 0;
537*24455Smckusick     p[1].rwcode = 0;
538*24455Smckusick     return;
539*24455Smckusick }
540