Home | History | Annotate | Line # | Download | only in indent
lexi.c revision 1.6
      1  1.6  lukem /*	$NetBSD: lexi.c,v 1.6 1997/10/19 03:17:25 lukem Exp $	*/
      2  1.3    tls 
      3  1.1    cgd /*
      4  1.5    mrg  * Copyright (c) 1980, 1993
      5  1.5    mrg  *	The Regents of the University of California.  All rights reserved.
      6  1.5    mrg  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
      7  1.1    cgd  * Copyright (c) 1985 Sun Microsystems, Inc.
      8  1.1    cgd  * All rights reserved.
      9  1.1    cgd  *
     10  1.1    cgd  * Redistribution and use in source and binary forms, with or without
     11  1.1    cgd  * modification, are permitted provided that the following conditions
     12  1.1    cgd  * are met:
     13  1.1    cgd  * 1. Redistributions of source code must retain the above copyright
     14  1.1    cgd  *    notice, this list of conditions and the following disclaimer.
     15  1.1    cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1    cgd  *    notice, this list of conditions and the following disclaimer in the
     17  1.1    cgd  *    documentation and/or other materials provided with the distribution.
     18  1.1    cgd  * 3. All advertising materials mentioning features or use of this software
     19  1.1    cgd  *    must display the following acknowledgement:
     20  1.1    cgd  *	This product includes software developed by the University of
     21  1.1    cgd  *	California, Berkeley and its contributors.
     22  1.1    cgd  * 4. Neither the name of the University nor the names of its contributors
     23  1.1    cgd  *    may be used to endorse or promote products derived from this software
     24  1.1    cgd  *    without specific prior written permission.
     25  1.1    cgd  *
     26  1.1    cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27  1.1    cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28  1.1    cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29  1.1    cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30  1.1    cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31  1.1    cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32  1.1    cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33  1.1    cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34  1.1    cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35  1.1    cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36  1.1    cgd  * SUCH DAMAGE.
     37  1.1    cgd  */
     38  1.1    cgd 
     39  1.6  lukem #include <sys/cdefs.h>
     40  1.1    cgd #ifndef lint
     41  1.5    mrg #if 0
     42  1.5    mrg static char sccsid[] = "@(#)lexi.c	8.1 (Berkeley) 6/6/93";
     43  1.5    mrg #else
     44  1.6  lukem __RCSID("$NetBSD: lexi.c,v 1.6 1997/10/19 03:17:25 lukem Exp $");
     45  1.5    mrg #endif
     46  1.6  lukem #endif				/* not lint */
     47  1.1    cgd 
     48  1.1    cgd /*
     49  1.1    cgd  * Here we have the token scanner for indent.  It scans off one token and puts
     50  1.1    cgd  * it in the global variable "token".  It returns a code, indicating the type
     51  1.1    cgd  * of token scanned.
     52  1.1    cgd  */
     53  1.1    cgd 
     54  1.1    cgd #include <stdio.h>
     55  1.1    cgd #include <ctype.h>
     56  1.1    cgd #include <stdlib.h>
     57  1.1    cgd #include <string.h>
     58  1.1    cgd #include "indent_globs.h"
     59  1.1    cgd #include "indent_codes.h"
     60  1.1    cgd 
     61  1.1    cgd #define alphanum 1
     62  1.1    cgd #define opchar 3
     63  1.1    cgd 
     64  1.1    cgd struct templ {
     65  1.6  lukem 	char   *rwd;
     66  1.6  lukem 	int     rwcode;
     67  1.1    cgd };
     68  1.1    cgd 
     69  1.4    agc struct templ specials[1000] =
     70  1.1    cgd {
     71  1.6  lukem 	{"switch", 1},
     72  1.6  lukem 	{"case", 2},
     73  1.6  lukem 	{"break", 0},
     74  1.6  lukem 	{"struct", 3},
     75  1.6  lukem 	{"union", 3},
     76  1.6  lukem 	{"enum", 3},
     77  1.6  lukem 	{"default", 2},
     78  1.6  lukem 	{"int", 4},
     79  1.6  lukem 	{"char", 4},
     80  1.6  lukem 	{"float", 4},
     81  1.6  lukem 	{"double", 4},
     82  1.6  lukem 	{"long", 4},
     83  1.6  lukem 	{"short", 4},
     84  1.6  lukem 	{"typdef", 4},
     85  1.6  lukem 	{"unsigned", 4},
     86  1.6  lukem 	{"register", 4},
     87  1.6  lukem 	{"static", 4},
     88  1.6  lukem 	{"global", 4},
     89  1.6  lukem 	{"extern", 4},
     90  1.6  lukem 	{"void", 4},
     91  1.6  lukem 	{"goto", 0},
     92  1.6  lukem 	{"return", 0},
     93  1.6  lukem 	{"if", 5},
     94  1.6  lukem 	{"while", 5},
     95  1.6  lukem 	{"for", 5},
     96  1.6  lukem 	{"else", 6},
     97  1.6  lukem 	{"do", 6},
     98  1.6  lukem 	{"sizeof", 7},
     99  1.6  lukem 	{0, 0}
    100  1.1    cgd };
    101  1.1    cgd 
    102  1.6  lukem char    chartype[128] =
    103  1.1    cgd {				/* this is used to facilitate the decision of
    104  1.1    cgd 				 * what type (alphanumeric, operator) each
    105  1.1    cgd 				 * character is */
    106  1.6  lukem 	0, 0, 0, 0, 0, 0, 0, 0,
    107  1.6  lukem 	0, 0, 0, 0, 0, 0, 0, 0,
    108  1.6  lukem 	0, 0, 0, 0, 0, 0, 0, 0,
    109  1.6  lukem 	0, 0, 0, 0, 0, 0, 0, 0,
    110  1.6  lukem 	0, 3, 0, 0, 1, 3, 3, 0,
    111  1.6  lukem 	0, 0, 3, 3, 0, 3, 0, 3,
    112  1.6  lukem 	1, 1, 1, 1, 1, 1, 1, 1,
    113  1.6  lukem 	1, 1, 0, 0, 3, 3, 3, 3,
    114  1.6  lukem 	0, 1, 1, 1, 1, 1, 1, 1,
    115  1.6  lukem 	1, 1, 1, 1, 1, 1, 1, 1,
    116  1.6  lukem 	1, 1, 1, 1, 1, 1, 1, 1,
    117  1.6  lukem 	1, 1, 1, 0, 0, 0, 3, 1,
    118  1.6  lukem 	0, 1, 1, 1, 1, 1, 1, 1,
    119  1.6  lukem 	1, 1, 1, 1, 1, 1, 1, 1,
    120  1.6  lukem 	1, 1, 1, 1, 1, 1, 1, 1,
    121  1.6  lukem 	1, 1, 1, 0, 3, 0, 3, 0
    122  1.1    cgd };
    123  1.1    cgd 
    124  1.1    cgd 
    125  1.1    cgd 
    126  1.1    cgd 
    127  1.1    cgd int
    128  1.1    cgd lexi()
    129  1.1    cgd {
    130  1.6  lukem 	int     unary_delim;	/* this is set to 1 if the current token
    131  1.1    cgd 				 *
    132  1.1    cgd 				 * forces a following operator to be unary */
    133  1.6  lukem 	static int last_code;	/* the last token type returned */
    134  1.6  lukem 	static int l_struct;	/* set to 1 if the last token was 'struct' */
    135  1.6  lukem 	int     code;		/* internal code to be returned */
    136  1.6  lukem 	char    qchar;		/* the delimiter character for a string */
    137  1.6  lukem 
    138  1.6  lukem 	e_token = s_token;	/* point to start of place to save token */
    139  1.6  lukem 	unary_delim = false;
    140  1.6  lukem 	ps.col_1 = ps.last_nl;	/* tell world that this token started in
    141  1.1    cgd 				 * column 1 iff the last thing scanned was nl */
    142  1.6  lukem 	ps.last_nl = false;
    143  1.1    cgd 
    144  1.6  lukem 	while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
    145  1.6  lukem 		ps.col_1 = false;	/* leading blanks imply token is not
    146  1.6  lukem 					 * in column 1 */
    147  1.6  lukem 		if (++buf_ptr >= buf_end)
    148  1.6  lukem 			fill_buffer();
    149  1.6  lukem 	}
    150  1.1    cgd 
    151  1.6  lukem 	/* Scan an alphanumeric token */
    152  1.6  lukem 	if (chartype[(int) *buf_ptr] == alphanum ||
    153  1.6  lukem 	    (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) {
    154  1.6  lukem 		/*
    155  1.6  lukem 		 * we have a character or number
    156  1.6  lukem 		 */
    157  1.6  lukem 		char   *j;	/* used for searching thru list of
    158  1.1    cgd 				 *
    159  1.1    cgd 				 * reserved words */
    160  1.6  lukem 		struct templ *p;
    161  1.1    cgd 
    162  1.6  lukem 		if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) {
    163  1.6  lukem 			int     seendot = 0, seenexp = 0;
    164  1.6  lukem 			if (*buf_ptr == '0' &&
    165  1.6  lukem 			    (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) {
    166  1.6  lukem 				*e_token++ = *buf_ptr++;
    167  1.6  lukem 				*e_token++ = *buf_ptr++;
    168  1.6  lukem 				while (isxdigit(*buf_ptr)) {
    169  1.6  lukem 					CHECK_SIZE_TOKEN;
    170  1.6  lukem 					*e_token++ = *buf_ptr++;
    171  1.6  lukem 				}
    172  1.6  lukem 			} else
    173  1.6  lukem 				while (1) {
    174  1.6  lukem 					if (*buf_ptr == '.')
    175  1.6  lukem 						if (seendot)
    176  1.6  lukem 							break;
    177  1.6  lukem 						else
    178  1.6  lukem 							seendot++;
    179  1.6  lukem 					CHECK_SIZE_TOKEN;
    180  1.6  lukem 					*e_token++ = *buf_ptr++;
    181  1.6  lukem 					if (!isdigit(*buf_ptr) && *buf_ptr != '.')
    182  1.6  lukem 						if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
    183  1.6  lukem 							break;
    184  1.6  lukem 						else {
    185  1.6  lukem 							seenexp++;
    186  1.6  lukem 							seendot++;
    187  1.6  lukem 							CHECK_SIZE_TOKEN;
    188  1.6  lukem 							*e_token++ = *buf_ptr++;
    189  1.6  lukem 							if (*buf_ptr == '+' || *buf_ptr == '-')
    190  1.6  lukem 								*e_token++ = *buf_ptr++;
    191  1.6  lukem 						}
    192  1.6  lukem 				}
    193  1.6  lukem 			if (*buf_ptr == 'L' || *buf_ptr == 'l')
    194  1.6  lukem 				*e_token++ = *buf_ptr++;
    195  1.6  lukem 		} else
    196  1.6  lukem 			while (chartype[(int) *buf_ptr] == alphanum) {	/* copy it over */
    197  1.6  lukem 				CHECK_SIZE_TOKEN;
    198  1.1    cgd 				*e_token++ = *buf_ptr++;
    199  1.6  lukem 				if (buf_ptr >= buf_end)
    200  1.6  lukem 					fill_buffer();
    201  1.1    cgd 			}
    202  1.6  lukem 		*e_token++ = '\0';
    203  1.6  lukem 		while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
    204  1.6  lukem 			if (++buf_ptr >= buf_end)
    205  1.6  lukem 				fill_buffer();
    206  1.1    cgd 		}
    207  1.6  lukem 		ps.its_a_keyword = false;
    208  1.6  lukem 		ps.sizeof_keyword = false;
    209  1.6  lukem 		if (l_struct) {	/* if last token was 'struct', then this token
    210  1.1    cgd 				 * should be treated as a declaration */
    211  1.6  lukem 			l_struct = false;
    212  1.6  lukem 			last_code = ident;
    213  1.6  lukem 			ps.last_u_d = true;
    214  1.6  lukem 			return (decl);
    215  1.6  lukem 		}
    216  1.6  lukem 		ps.last_u_d = false;	/* Operator after indentifier is
    217  1.6  lukem 					 * binary */
    218  1.6  lukem 		last_code = ident;	/* Remember that this is the code we
    219  1.6  lukem 					 * will return */
    220  1.1    cgd 
    221  1.1    cgd 		/*
    222  1.6  lukem 		 * This loop will check if the token is a keyword.
    223  1.6  lukem 		 */
    224  1.6  lukem 		for (p = specials; (j = p->rwd) != 0; p++) {
    225  1.6  lukem 			char   *p = s_token;	/* point at scanned token */
    226  1.6  lukem 			if (*j++ != *p++ || *j++ != *p++)
    227  1.6  lukem 				continue;	/* This test depends on the
    228  1.6  lukem 						 * fact that identifiers are
    229  1.6  lukem 						 * always at least 1 character
    230  1.6  lukem 						 * long (ie. the first two
    231  1.6  lukem 						 * bytes of the identifier are
    232  1.6  lukem 						 * always meaningful) */
    233  1.6  lukem 			if (p[-1] == 0)
    234  1.6  lukem 				break;	/* If its a one-character identifier */
    235  1.6  lukem 			while (*p++ == *j)
    236  1.6  lukem 				if (*j++ == 0)
    237  1.6  lukem 					goto found_keyword;	/* I wish that C had a
    238  1.6  lukem 								 * multi-level break... */
    239  1.6  lukem 		}
    240  1.6  lukem 		if (p->rwd) {	/* we have a keyword */
    241  1.6  lukem 	found_keyword:
    242  1.6  lukem 			ps.its_a_keyword = true;
    243  1.6  lukem 			ps.last_u_d = true;
    244  1.6  lukem 			switch (p->rwcode) {
    245  1.6  lukem 			case 1:/* it is a switch */
    246  1.6  lukem 				return (swstmt);
    247  1.6  lukem 			case 2:/* a case or default */
    248  1.6  lukem 				return (casestmt);
    249  1.6  lukem 
    250  1.6  lukem 			case 3:/* a "struct" */
    251  1.6  lukem 				if (ps.p_l_follow)
    252  1.6  lukem 					break;	/* inside parens: cast */
    253  1.6  lukem 				l_struct = true;
    254  1.6  lukem 
    255  1.6  lukem 				/*
    256  1.6  lukem 				 * Next time around, we will want to know that we have had a
    257  1.6  lukem 				 * 'struct'
    258  1.6  lukem 				 */
    259  1.6  lukem 			case 4:/* one of the declaration keywords */
    260  1.6  lukem 				if (ps.p_l_follow) {
    261  1.6  lukem 					ps.cast_mask |= 1 << ps.p_l_follow;
    262  1.6  lukem 					break;	/* inside parens: cast */
    263  1.6  lukem 				}
    264  1.6  lukem 				last_code = decl;
    265  1.6  lukem 				return (decl);
    266  1.6  lukem 
    267  1.6  lukem 			case 5:/* if, while, for */
    268  1.6  lukem 				return (sp_paren);
    269  1.6  lukem 
    270  1.6  lukem 			case 6:/* do, else */
    271  1.6  lukem 				return (sp_nparen);
    272  1.6  lukem 
    273  1.6  lukem 			case 7:
    274  1.6  lukem 				ps.sizeof_keyword = true;
    275  1.6  lukem 			default:	/* all others are treated like any
    276  1.6  lukem 					 * other identifier */
    277  1.6  lukem 				return (ident);
    278  1.6  lukem 			}	/* end of switch */
    279  1.6  lukem 		}		/* end of if (found_it) */
    280  1.6  lukem 		if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) {
    281  1.6  lukem 			char   *tp = buf_ptr;
    282  1.6  lukem 			while (tp < buf_end)
    283  1.6  lukem 				if (*tp++ == ')' && (*tp == ';' || *tp == ','))
    284  1.6  lukem 					goto not_proc;
    285  1.6  lukem 			strncpy(ps.procname, token, sizeof ps.procname - 1);
    286  1.6  lukem 			ps.in_parameter_declaration = 1;
    287  1.6  lukem 			rparen_count = 1;
    288  1.6  lukem 	not_proc:	;
    289  1.6  lukem 		}
    290  1.6  lukem 		/*
    291  1.6  lukem 		 * The following hack attempts to guess whether or not the current
    292  1.6  lukem 		 * token is in fact a declaration keyword -- one that has been
    293  1.6  lukem 		 * typedefd
    294  1.1    cgd 		 */
    295  1.6  lukem 		if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_')
    296  1.6  lukem 		    && !ps.p_l_follow
    297  1.6  lukem 		    && !ps.block_init
    298  1.6  lukem 		    && (ps.last_token == rparen || ps.last_token == semicolon ||
    299  1.6  lukem 			ps.last_token == decl ||
    300  1.6  lukem 			ps.last_token == lbrace || ps.last_token == rbrace)) {
    301  1.6  lukem 			ps.its_a_keyword = true;
    302  1.6  lukem 			ps.last_u_d = true;
    303  1.6  lukem 			last_code = decl;
    304  1.6  lukem 			return decl;
    305  1.6  lukem 		}
    306  1.6  lukem 		if (last_code == decl)	/* if this is a declared variable,
    307  1.6  lukem 					 * then following sign is unary */
    308  1.6  lukem 			ps.last_u_d = true;	/* will make "int a -1" work */
    309  1.6  lukem 		last_code = ident;
    310  1.6  lukem 		return (ident);	/* the ident is not in the list */
    311  1.6  lukem 	}			/* end of procesing for alpanum character */
    312  1.6  lukem 	/* Scan a non-alphanumeric token */
    313  1.6  lukem 	*e_token++ = *buf_ptr;	/* if it is only a one-character token, it is
    314  1.6  lukem 				 * moved here */
    315  1.6  lukem 	*e_token = '\0';
    316  1.6  lukem 	if (++buf_ptr >= buf_end)
    317  1.6  lukem 		fill_buffer();
    318  1.6  lukem 
    319  1.6  lukem 	switch (*token) {
    320  1.6  lukem 	case '\n':
    321  1.6  lukem 		unary_delim = ps.last_u_d;
    322  1.6  lukem 		ps.last_nl = true;	/* remember that we just had a newline */
    323  1.6  lukem 		code = (had_eof ? 0 : newline);
    324  1.1    cgd 
    325  1.6  lukem 		/*
    326  1.6  lukem 		 * if data has been exausted, the newline is a dummy, and we should
    327  1.6  lukem 		 * return code to stop
    328  1.6  lukem 		 */
    329  1.6  lukem 		break;
    330  1.1    cgd 
    331  1.6  lukem 	case '\'':		/* start of quoted character */
    332  1.6  lukem 	case '"':		/* start of string */
    333  1.6  lukem 		qchar = *token;
    334  1.6  lukem 		if (troff) {
    335  1.6  lukem 			e_token[-1] = '`';
    336  1.6  lukem 			if (qchar == '"')
    337  1.6  lukem 				*e_token++ = '`';
    338  1.6  lukem 			e_token = chfont(&bodyf, &stringf, e_token);
    339  1.6  lukem 		}
    340  1.6  lukem 		do {		/* copy the string */
    341  1.6  lukem 			while (1) {	/* move one character or
    342  1.6  lukem 					 * [/<char>]<char> */
    343  1.6  lukem 				if (*buf_ptr == '\n') {
    344  1.6  lukem 					printf("%d: Unterminated literal\n", line_no);
    345  1.6  lukem 					goto stop_lit;
    346  1.6  lukem 				}
    347  1.6  lukem 				CHECK_SIZE_TOKEN;	/* Only have to do this
    348  1.6  lukem 							 * once in this loop,
    349  1.6  lukem 							 * since CHECK_SIZE
    350  1.6  lukem 							 * guarantees that there
    351  1.6  lukem 							 * are at least 5
    352  1.6  lukem 							 * entries left */
    353  1.6  lukem 				*e_token = *buf_ptr++;
    354  1.6  lukem 				if (buf_ptr >= buf_end)
    355  1.6  lukem 					fill_buffer();
    356  1.6  lukem 				if (*e_token == BACKSLASH) {	/* if escape, copy extra
    357  1.6  lukem 								 * char */
    358  1.6  lukem 					if (*buf_ptr == '\n')	/* check for escaped
    359  1.6  lukem 								 * newline */
    360  1.6  lukem 						++line_no;
    361  1.6  lukem 					if (troff) {
    362  1.6  lukem 						*++e_token = BACKSLASH;
    363  1.6  lukem 						if (*buf_ptr == BACKSLASH)
    364  1.6  lukem 							*++e_token = BACKSLASH;
    365  1.6  lukem 					}
    366  1.6  lukem 					*++e_token = *buf_ptr++;
    367  1.6  lukem 					++e_token;	/* we must increment
    368  1.6  lukem 							 * this again because we
    369  1.6  lukem 							 * copied two chars */
    370  1.6  lukem 					if (buf_ptr >= buf_end)
    371  1.6  lukem 						fill_buffer();
    372  1.6  lukem 				} else
    373  1.6  lukem 					break;	/* we copied one character */
    374  1.6  lukem 			}	/* end of while (1) */
    375  1.6  lukem 		} while (*e_token++ != qchar);
    376  1.6  lukem 		if (troff) {
    377  1.6  lukem 			e_token = chfont(&stringf, &bodyf, e_token - 1);
    378  1.6  lukem 			if (qchar == '"')
    379  1.6  lukem 				*e_token++ = '\'';
    380  1.1    cgd 		}
    381  1.1    cgd stop_lit:
    382  1.6  lukem 		code = ident;
    383  1.6  lukem 		break;
    384  1.6  lukem 
    385  1.6  lukem 	case ('('):
    386  1.6  lukem 	case ('['):
    387  1.6  lukem 		unary_delim = true;
    388  1.6  lukem 		code = lparen;
    389  1.6  lukem 		break;
    390  1.6  lukem 
    391  1.6  lukem 	case (')'):
    392  1.6  lukem 	case (']'):
    393  1.6  lukem 		code = rparen;
    394  1.6  lukem 		break;
    395  1.6  lukem 
    396  1.6  lukem 	case '#':
    397  1.6  lukem 		unary_delim = ps.last_u_d;
    398  1.6  lukem 		code = preesc;
    399  1.6  lukem 		break;
    400  1.6  lukem 
    401  1.6  lukem 	case '?':
    402  1.6  lukem 		unary_delim = true;
    403  1.6  lukem 		code = question;
    404  1.6  lukem 		break;
    405  1.6  lukem 
    406  1.6  lukem 	case (':'):
    407  1.6  lukem 		code = colon;
    408  1.6  lukem 		unary_delim = true;
    409  1.6  lukem 		break;
    410  1.6  lukem 
    411  1.6  lukem 	case (';'):
    412  1.6  lukem 		unary_delim = true;
    413  1.6  lukem 		code = semicolon;
    414  1.6  lukem 		break;
    415  1.1    cgd 
    416  1.6  lukem 	case ('{'):
    417  1.6  lukem 		unary_delim = true;
    418  1.1    cgd 
    419  1.6  lukem 		/*
    420  1.6  lukem 		 * if (ps.in_or_st) ps.block_init = 1;
    421  1.6  lukem 		 */
    422  1.6  lukem 		/* ?	code = ps.block_init ? lparen : lbrace; */
    423  1.6  lukem 		code = lbrace;
    424  1.6  lukem 		break;
    425  1.6  lukem 
    426  1.6  lukem 	case ('}'):
    427  1.6  lukem 		unary_delim = true;
    428  1.6  lukem 		/* ?	code = ps.block_init ? rparen : rbrace; */
    429  1.6  lukem 		code = rbrace;
    430  1.6  lukem 		break;
    431  1.6  lukem 
    432  1.6  lukem 	case 014:		/* a form feed */
    433  1.6  lukem 		unary_delim = ps.last_u_d;
    434  1.6  lukem 		ps.last_nl = true;	/* remember this so we can set
    435  1.6  lukem 					 * 'ps.col_1' right */
    436  1.6  lukem 		code = form_feed;
    437  1.6  lukem 		break;
    438  1.6  lukem 
    439  1.6  lukem 	case (','):
    440  1.6  lukem 		unary_delim = true;
    441  1.6  lukem 		code = comma;
    442  1.6  lukem 		break;
    443  1.1    cgd 
    444  1.6  lukem 	case '.':
    445  1.1    cgd 		unary_delim = false;
    446  1.6  lukem 		code = period;
    447  1.6  lukem 		break;
    448  1.6  lukem 
    449  1.6  lukem 	case '-':
    450  1.6  lukem 	case '+':		/* check for -, +, --, ++ */
    451  1.6  lukem 		code = (ps.last_u_d ? unary_op : binary_op);
    452  1.6  lukem 		unary_delim = true;
    453  1.6  lukem 
    454  1.6  lukem 		if (*buf_ptr == token[0]) {
    455  1.6  lukem 			/* check for doubled character */
    456  1.6  lukem 			*e_token++ = *buf_ptr++;
    457  1.6  lukem 			/* buffer overflow will be checked at end of loop */
    458  1.6  lukem 			if (last_code == ident || last_code == rparen) {
    459  1.6  lukem 				code = (ps.last_u_d ? unary_op : postop);
    460  1.6  lukem 				/* check for following ++ or -- */
    461  1.6  lukem 				unary_delim = false;
    462  1.6  lukem 			}
    463  1.6  lukem 		} else
    464  1.6  lukem 			if (*buf_ptr == '=')
    465  1.6  lukem 				/* check for operator += */
    466  1.6  lukem 				*e_token++ = *buf_ptr++;
    467  1.6  lukem 			else
    468  1.6  lukem 				if (*buf_ptr == '>') {
    469  1.6  lukem 					/* check for operator -> */
    470  1.6  lukem 					*e_token++ = *buf_ptr++;
    471  1.6  lukem 					if (!pointer_as_binop) {
    472  1.6  lukem 						unary_delim = false;
    473  1.6  lukem 						code = unary_op;
    474  1.6  lukem 						ps.want_blank = false;
    475  1.6  lukem 					}
    476  1.6  lukem 				}
    477  1.6  lukem 		break;		/* buffer overflow will be checked at end of
    478  1.1    cgd 				 * switch */
    479  1.1    cgd 
    480  1.6  lukem 	case '=':
    481  1.6  lukem 		if (ps.in_or_st)
    482  1.6  lukem 			ps.block_init = 1;
    483  1.1    cgd #ifdef undef
    484  1.6  lukem 		if (chartype[*buf_ptr] == opchar) {	/* we have two char
    485  1.6  lukem 							 * assignment */
    486  1.6  lukem 			e_token[-1] = *buf_ptr++;
    487  1.6  lukem 			if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
    488  1.6  lukem 				*e_token++ = *buf_ptr++;
    489  1.6  lukem 			*e_token++ = '=';	/* Flip =+ to += */
    490  1.6  lukem 			*e_token = 0;
    491  1.6  lukem 		}
    492  1.1    cgd #else
    493  1.6  lukem 		if (*buf_ptr == '=') {	/* == */
    494  1.6  lukem 			*e_token++ = '=';	/* Flip =+ to += */
    495  1.6  lukem 			buf_ptr++;
    496  1.6  lukem 			*e_token = 0;
    497  1.6  lukem 		}
    498  1.1    cgd #endif
    499  1.6  lukem 		code = binary_op;
    500  1.6  lukem 		unary_delim = true;
    501  1.6  lukem 		break;
    502  1.6  lukem 		/* can drop thru!!! */
    503  1.6  lukem 
    504  1.6  lukem 	case '>':
    505  1.6  lukem 	case '<':
    506  1.6  lukem 	case '!':		/* ops like <, <<, <=, !=, etc */
    507  1.6  lukem 		if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
    508  1.6  lukem 			*e_token++ = *buf_ptr;
    509  1.6  lukem 			if (++buf_ptr >= buf_end)
    510  1.6  lukem 				fill_buffer();
    511  1.6  lukem 		}
    512  1.6  lukem 		if (*buf_ptr == '=')
    513  1.6  lukem 			*e_token++ = *buf_ptr++;
    514  1.6  lukem 		code = (ps.last_u_d ? unary_op : binary_op);
    515  1.6  lukem 		unary_delim = true;
    516  1.6  lukem 		break;
    517  1.6  lukem 
    518  1.6  lukem 	default:
    519  1.6  lukem 		if (token[0] == '/' && *buf_ptr == '*') {
    520  1.6  lukem 			/* it is start of comment */
    521  1.6  lukem 			*e_token++ = '*';
    522  1.6  lukem 
    523  1.6  lukem 			if (++buf_ptr >= buf_end)
    524  1.6  lukem 				fill_buffer();
    525  1.6  lukem 
    526  1.6  lukem 			code = comment;
    527  1.6  lukem 			unary_delim = ps.last_u_d;
    528  1.6  lukem 			break;
    529  1.6  lukem 		}
    530  1.6  lukem 		while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
    531  1.6  lukem 			/*
    532  1.6  lukem 		         * handle ||, &&, etc, and also things as in int *****i
    533  1.6  lukem 		         */
    534  1.6  lukem 			*e_token++ = *buf_ptr;
    535  1.6  lukem 			if (++buf_ptr >= buf_end)
    536  1.6  lukem 				fill_buffer();
    537  1.6  lukem 		}
    538  1.6  lukem 		code = (ps.last_u_d ? unary_op : binary_op);
    539  1.6  lukem 		unary_delim = true;
    540  1.1    cgd 
    541  1.1    cgd 
    542  1.6  lukem 	}			/* end of switch */
    543  1.6  lukem 	if (code != newline) {
    544  1.6  lukem 		l_struct = false;
    545  1.6  lukem 		last_code = code;
    546  1.1    cgd 	}
    547  1.6  lukem 	if (buf_ptr >= buf_end)	/* check for input buffer empty */
    548  1.1    cgd 		fill_buffer();
    549  1.6  lukem 	ps.last_u_d = unary_delim;
    550  1.6  lukem 	*e_token = '\0';	/* null terminate the token */
    551  1.6  lukem 	return (code);
    552  1.1    cgd }
    553  1.1    cgd /*
    554  1.1    cgd  * Add the given keyword to the keyword table, using val as the keyword type
    555  1.1    cgd  */
    556  1.6  lukem void
    557  1.1    cgd addkey(key, val)
    558  1.6  lukem 	char   *key;
    559  1.6  lukem 	int     val;
    560  1.1    cgd {
    561  1.6  lukem 	struct templ *p = specials;
    562  1.6  lukem 	while (p->rwd)
    563  1.6  lukem 		if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
    564  1.6  lukem 			return;
    565  1.6  lukem 		else
    566  1.6  lukem 			p++;
    567  1.6  lukem 	if (p >= specials + sizeof specials / sizeof specials[0])
    568  1.6  lukem 		return;		/* For now, table overflows are silently
    569  1.1    cgd 				 * ignored */
    570  1.6  lukem 	p->rwd = key;
    571  1.6  lukem 	p->rwcode = val;
    572  1.6  lukem 	p[1].rwd = 0;
    573  1.6  lukem 	p[1].rwcode = 0;
    574  1.1    cgd }
    575