Home | History | Annotate | Line # | Download | only in indent
lexi.c revision 1.9
      1  1.9  kristerw /*	$NetBSD: lexi.c,v 1.9 1999/03/15 20:28:45 kristerw 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.9  kristerw __RCSID("$NetBSD: lexi.c,v 1.9 1999/03/15 20:28:45 kristerw 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.8  christos 	    (buf_ptr[0] == '.' && isdigit((unsigned char)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.8  christos 		if (isdigit((unsigned char)*buf_ptr) ||
    163  1.8  christos 		    (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
    164  1.6     lukem 			int     seendot = 0, seenexp = 0;
    165  1.6     lukem 			if (*buf_ptr == '0' &&
    166  1.6     lukem 			    (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) {
    167  1.6     lukem 				*e_token++ = *buf_ptr++;
    168  1.6     lukem 				*e_token++ = *buf_ptr++;
    169  1.8  christos 				while (isxdigit((unsigned char)*buf_ptr)) {
    170  1.6     lukem 					CHECK_SIZE_TOKEN;
    171  1.6     lukem 					*e_token++ = *buf_ptr++;
    172  1.6     lukem 				}
    173  1.7      ross 			} else {
    174  1.6     lukem 				while (1) {
    175  1.7      ross 					if (*buf_ptr == '.') {
    176  1.6     lukem 						if (seendot)
    177  1.6     lukem 							break;
    178  1.6     lukem 						else
    179  1.6     lukem 							seendot++;
    180  1.7      ross 					}
    181  1.6     lukem 					CHECK_SIZE_TOKEN;
    182  1.6     lukem 					*e_token++ = *buf_ptr++;
    183  1.8  christos 					if (!isdigit((unsigned char)*buf_ptr)
    184  1.7      ross 					&& *buf_ptr != '.') {
    185  1.7      ross 						if ((*buf_ptr != 'E'
    186  1.7      ross 						&& *buf_ptr != 'e') || seenexp)
    187  1.6     lukem 							break;
    188  1.6     lukem 						else {
    189  1.6     lukem 							seenexp++;
    190  1.6     lukem 							seendot++;
    191  1.6     lukem 							CHECK_SIZE_TOKEN;
    192  1.6     lukem 							*e_token++ = *buf_ptr++;
    193  1.6     lukem 							if (*buf_ptr == '+' || *buf_ptr == '-')
    194  1.6     lukem 								*e_token++ = *buf_ptr++;
    195  1.6     lukem 						}
    196  1.7      ross 					}
    197  1.6     lukem 				}
    198  1.7      ross 			}
    199  1.9  kristerw 			if (*buf_ptr == 'F' || *buf_ptr == 'f') {
    200  1.9  kristerw 				/* float constant */
    201  1.6     lukem 				*e_token++ = *buf_ptr++;
    202  1.9  kristerw 			} else {
    203  1.9  kristerw 				/* integer constant (U, L, UL, LL, ULL) */
    204  1.9  kristerw 				if (*buf_ptr == 'U' || *buf_ptr == 'u')
    205  1.9  kristerw 					*e_token++ = *buf_ptr++;
    206  1.9  kristerw 				if (*buf_ptr == 'L' || *buf_ptr == 'l')
    207  1.9  kristerw 					*e_token++ = *buf_ptr++;
    208  1.9  kristerw 				if (*buf_ptr == 'L' || *buf_ptr == 'l')
    209  1.9  kristerw 					*e_token++ = *buf_ptr++;
    210  1.9  kristerw 			}
    211  1.6     lukem 		} else
    212  1.6     lukem 			while (chartype[(int) *buf_ptr] == alphanum) {	/* copy it over */
    213  1.6     lukem 				CHECK_SIZE_TOKEN;
    214  1.1       cgd 				*e_token++ = *buf_ptr++;
    215  1.6     lukem 				if (buf_ptr >= buf_end)
    216  1.6     lukem 					fill_buffer();
    217  1.1       cgd 			}
    218  1.6     lukem 		*e_token++ = '\0';
    219  1.6     lukem 		while (*buf_ptr == ' ' || *buf_ptr == '\t') {	/* get rid of blanks */
    220  1.6     lukem 			if (++buf_ptr >= buf_end)
    221  1.6     lukem 				fill_buffer();
    222  1.1       cgd 		}
    223  1.6     lukem 		ps.its_a_keyword = false;
    224  1.6     lukem 		ps.sizeof_keyword = false;
    225  1.6     lukem 		if (l_struct) {	/* if last token was 'struct', then this token
    226  1.1       cgd 				 * should be treated as a declaration */
    227  1.6     lukem 			l_struct = false;
    228  1.6     lukem 			last_code = ident;
    229  1.6     lukem 			ps.last_u_d = true;
    230  1.6     lukem 			return (decl);
    231  1.6     lukem 		}
    232  1.6     lukem 		ps.last_u_d = false;	/* Operator after indentifier is
    233  1.6     lukem 					 * binary */
    234  1.6     lukem 		last_code = ident;	/* Remember that this is the code we
    235  1.6     lukem 					 * will return */
    236  1.1       cgd 
    237  1.1       cgd 		/*
    238  1.6     lukem 		 * This loop will check if the token is a keyword.
    239  1.6     lukem 		 */
    240  1.6     lukem 		for (p = specials; (j = p->rwd) != 0; p++) {
    241  1.6     lukem 			char   *p = s_token;	/* point at scanned token */
    242  1.6     lukem 			if (*j++ != *p++ || *j++ != *p++)
    243  1.6     lukem 				continue;	/* This test depends on the
    244  1.6     lukem 						 * fact that identifiers are
    245  1.6     lukem 						 * always at least 1 character
    246  1.6     lukem 						 * long (ie. the first two
    247  1.6     lukem 						 * bytes of the identifier are
    248  1.6     lukem 						 * always meaningful) */
    249  1.6     lukem 			if (p[-1] == 0)
    250  1.6     lukem 				break;	/* If its a one-character identifier */
    251  1.6     lukem 			while (*p++ == *j)
    252  1.6     lukem 				if (*j++ == 0)
    253  1.6     lukem 					goto found_keyword;	/* I wish that C had a
    254  1.6     lukem 								 * multi-level break... */
    255  1.6     lukem 		}
    256  1.6     lukem 		if (p->rwd) {	/* we have a keyword */
    257  1.6     lukem 	found_keyword:
    258  1.6     lukem 			ps.its_a_keyword = true;
    259  1.6     lukem 			ps.last_u_d = true;
    260  1.6     lukem 			switch (p->rwcode) {
    261  1.6     lukem 			case 1:/* it is a switch */
    262  1.6     lukem 				return (swstmt);
    263  1.6     lukem 			case 2:/* a case or default */
    264  1.6     lukem 				return (casestmt);
    265  1.6     lukem 
    266  1.6     lukem 			case 3:/* a "struct" */
    267  1.6     lukem 				if (ps.p_l_follow)
    268  1.6     lukem 					break;	/* inside parens: cast */
    269  1.6     lukem 				l_struct = true;
    270  1.6     lukem 
    271  1.6     lukem 				/*
    272  1.6     lukem 				 * Next time around, we will want to know that we have had a
    273  1.6     lukem 				 * 'struct'
    274  1.6     lukem 				 */
    275  1.6     lukem 			case 4:/* one of the declaration keywords */
    276  1.6     lukem 				if (ps.p_l_follow) {
    277  1.6     lukem 					ps.cast_mask |= 1 << ps.p_l_follow;
    278  1.6     lukem 					break;	/* inside parens: cast */
    279  1.6     lukem 				}
    280  1.6     lukem 				last_code = decl;
    281  1.6     lukem 				return (decl);
    282  1.6     lukem 
    283  1.6     lukem 			case 5:/* if, while, for */
    284  1.6     lukem 				return (sp_paren);
    285  1.6     lukem 
    286  1.6     lukem 			case 6:/* do, else */
    287  1.6     lukem 				return (sp_nparen);
    288  1.6     lukem 
    289  1.6     lukem 			case 7:
    290  1.6     lukem 				ps.sizeof_keyword = true;
    291  1.6     lukem 			default:	/* all others are treated like any
    292  1.6     lukem 					 * other identifier */
    293  1.6     lukem 				return (ident);
    294  1.6     lukem 			}	/* end of switch */
    295  1.6     lukem 		}		/* end of if (found_it) */
    296  1.6     lukem 		if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) {
    297  1.6     lukem 			char   *tp = buf_ptr;
    298  1.6     lukem 			while (tp < buf_end)
    299  1.6     lukem 				if (*tp++ == ')' && (*tp == ';' || *tp == ','))
    300  1.6     lukem 					goto not_proc;
    301  1.6     lukem 			strncpy(ps.procname, token, sizeof ps.procname - 1);
    302  1.6     lukem 			ps.in_parameter_declaration = 1;
    303  1.6     lukem 			rparen_count = 1;
    304  1.6     lukem 	not_proc:	;
    305  1.6     lukem 		}
    306  1.6     lukem 		/*
    307  1.6     lukem 		 * The following hack attempts to guess whether or not the current
    308  1.6     lukem 		 * token is in fact a declaration keyword -- one that has been
    309  1.6     lukem 		 * typedefd
    310  1.1       cgd 		 */
    311  1.8  christos 		if (((*buf_ptr == '*' && buf_ptr[1] != '=') ||
    312  1.8  christos 		    isalpha((unsigned char)*buf_ptr) || *buf_ptr == '_')
    313  1.6     lukem 		    && !ps.p_l_follow
    314  1.6     lukem 		    && !ps.block_init
    315  1.6     lukem 		    && (ps.last_token == rparen || ps.last_token == semicolon ||
    316  1.6     lukem 			ps.last_token == decl ||
    317  1.6     lukem 			ps.last_token == lbrace || ps.last_token == rbrace)) {
    318  1.6     lukem 			ps.its_a_keyword = true;
    319  1.6     lukem 			ps.last_u_d = true;
    320  1.6     lukem 			last_code = decl;
    321  1.6     lukem 			return decl;
    322  1.6     lukem 		}
    323  1.6     lukem 		if (last_code == decl)	/* if this is a declared variable,
    324  1.6     lukem 					 * then following sign is unary */
    325  1.6     lukem 			ps.last_u_d = true;	/* will make "int a -1" work */
    326  1.6     lukem 		last_code = ident;
    327  1.6     lukem 		return (ident);	/* the ident is not in the list */
    328  1.6     lukem 	}			/* end of procesing for alpanum character */
    329  1.6     lukem 	/* Scan a non-alphanumeric token */
    330  1.6     lukem 	*e_token++ = *buf_ptr;	/* if it is only a one-character token, it is
    331  1.6     lukem 				 * moved here */
    332  1.6     lukem 	*e_token = '\0';
    333  1.6     lukem 	if (++buf_ptr >= buf_end)
    334  1.6     lukem 		fill_buffer();
    335  1.6     lukem 
    336  1.6     lukem 	switch (*token) {
    337  1.6     lukem 	case '\n':
    338  1.6     lukem 		unary_delim = ps.last_u_d;
    339  1.6     lukem 		ps.last_nl = true;	/* remember that we just had a newline */
    340  1.6     lukem 		code = (had_eof ? 0 : newline);
    341  1.1       cgd 
    342  1.6     lukem 		/*
    343  1.6     lukem 		 * if data has been exausted, the newline is a dummy, and we should
    344  1.6     lukem 		 * return code to stop
    345  1.6     lukem 		 */
    346  1.6     lukem 		break;
    347  1.1       cgd 
    348  1.6     lukem 	case '\'':		/* start of quoted character */
    349  1.6     lukem 	case '"':		/* start of string */
    350  1.6     lukem 		qchar = *token;
    351  1.6     lukem 		if (troff) {
    352  1.6     lukem 			e_token[-1] = '`';
    353  1.6     lukem 			if (qchar == '"')
    354  1.6     lukem 				*e_token++ = '`';
    355  1.6     lukem 			e_token = chfont(&bodyf, &stringf, e_token);
    356  1.6     lukem 		}
    357  1.6     lukem 		do {		/* copy the string */
    358  1.6     lukem 			while (1) {	/* move one character or
    359  1.6     lukem 					 * [/<char>]<char> */
    360  1.6     lukem 				if (*buf_ptr == '\n') {
    361  1.6     lukem 					printf("%d: Unterminated literal\n", line_no);
    362  1.6     lukem 					goto stop_lit;
    363  1.6     lukem 				}
    364  1.6     lukem 				CHECK_SIZE_TOKEN;	/* Only have to do this
    365  1.6     lukem 							 * once in this loop,
    366  1.6     lukem 							 * since CHECK_SIZE
    367  1.6     lukem 							 * guarantees that there
    368  1.6     lukem 							 * are at least 5
    369  1.6     lukem 							 * entries left */
    370  1.6     lukem 				*e_token = *buf_ptr++;
    371  1.6     lukem 				if (buf_ptr >= buf_end)
    372  1.6     lukem 					fill_buffer();
    373  1.6     lukem 				if (*e_token == BACKSLASH) {	/* if escape, copy extra
    374  1.6     lukem 								 * char */
    375  1.6     lukem 					if (*buf_ptr == '\n')	/* check for escaped
    376  1.6     lukem 								 * newline */
    377  1.6     lukem 						++line_no;
    378  1.6     lukem 					if (troff) {
    379  1.6     lukem 						*++e_token = BACKSLASH;
    380  1.6     lukem 						if (*buf_ptr == BACKSLASH)
    381  1.6     lukem 							*++e_token = BACKSLASH;
    382  1.6     lukem 					}
    383  1.6     lukem 					*++e_token = *buf_ptr++;
    384  1.6     lukem 					++e_token;	/* we must increment
    385  1.6     lukem 							 * this again because we
    386  1.6     lukem 							 * copied two chars */
    387  1.6     lukem 					if (buf_ptr >= buf_end)
    388  1.6     lukem 						fill_buffer();
    389  1.6     lukem 				} else
    390  1.6     lukem 					break;	/* we copied one character */
    391  1.6     lukem 			}	/* end of while (1) */
    392  1.6     lukem 		} while (*e_token++ != qchar);
    393  1.6     lukem 		if (troff) {
    394  1.6     lukem 			e_token = chfont(&stringf, &bodyf, e_token - 1);
    395  1.6     lukem 			if (qchar == '"')
    396  1.6     lukem 				*e_token++ = '\'';
    397  1.1       cgd 		}
    398  1.1       cgd stop_lit:
    399  1.6     lukem 		code = ident;
    400  1.6     lukem 		break;
    401  1.6     lukem 
    402  1.6     lukem 	case ('('):
    403  1.6     lukem 	case ('['):
    404  1.6     lukem 		unary_delim = true;
    405  1.6     lukem 		code = lparen;
    406  1.6     lukem 		break;
    407  1.6     lukem 
    408  1.6     lukem 	case (')'):
    409  1.6     lukem 	case (']'):
    410  1.6     lukem 		code = rparen;
    411  1.6     lukem 		break;
    412  1.6     lukem 
    413  1.6     lukem 	case '#':
    414  1.6     lukem 		unary_delim = ps.last_u_d;
    415  1.6     lukem 		code = preesc;
    416  1.6     lukem 		break;
    417  1.6     lukem 
    418  1.6     lukem 	case '?':
    419  1.6     lukem 		unary_delim = true;
    420  1.6     lukem 		code = question;
    421  1.6     lukem 		break;
    422  1.6     lukem 
    423  1.6     lukem 	case (':'):
    424  1.6     lukem 		code = colon;
    425  1.6     lukem 		unary_delim = true;
    426  1.6     lukem 		break;
    427  1.6     lukem 
    428  1.6     lukem 	case (';'):
    429  1.6     lukem 		unary_delim = true;
    430  1.6     lukem 		code = semicolon;
    431  1.6     lukem 		break;
    432  1.1       cgd 
    433  1.6     lukem 	case ('{'):
    434  1.6     lukem 		unary_delim = true;
    435  1.1       cgd 
    436  1.6     lukem 		/*
    437  1.6     lukem 		 * if (ps.in_or_st) ps.block_init = 1;
    438  1.6     lukem 		 */
    439  1.6     lukem 		/* ?	code = ps.block_init ? lparen : lbrace; */
    440  1.6     lukem 		code = lbrace;
    441  1.6     lukem 		break;
    442  1.6     lukem 
    443  1.6     lukem 	case ('}'):
    444  1.6     lukem 		unary_delim = true;
    445  1.6     lukem 		/* ?	code = ps.block_init ? rparen : rbrace; */
    446  1.6     lukem 		code = rbrace;
    447  1.6     lukem 		break;
    448  1.6     lukem 
    449  1.6     lukem 	case 014:		/* a form feed */
    450  1.6     lukem 		unary_delim = ps.last_u_d;
    451  1.6     lukem 		ps.last_nl = true;	/* remember this so we can set
    452  1.6     lukem 					 * 'ps.col_1' right */
    453  1.6     lukem 		code = form_feed;
    454  1.6     lukem 		break;
    455  1.6     lukem 
    456  1.6     lukem 	case (','):
    457  1.6     lukem 		unary_delim = true;
    458  1.6     lukem 		code = comma;
    459  1.6     lukem 		break;
    460  1.1       cgd 
    461  1.6     lukem 	case '.':
    462  1.1       cgd 		unary_delim = false;
    463  1.6     lukem 		code = period;
    464  1.6     lukem 		break;
    465  1.6     lukem 
    466  1.6     lukem 	case '-':
    467  1.6     lukem 	case '+':		/* check for -, +, --, ++ */
    468  1.6     lukem 		code = (ps.last_u_d ? unary_op : binary_op);
    469  1.6     lukem 		unary_delim = true;
    470  1.6     lukem 
    471  1.6     lukem 		if (*buf_ptr == token[0]) {
    472  1.6     lukem 			/* check for doubled character */
    473  1.6     lukem 			*e_token++ = *buf_ptr++;
    474  1.6     lukem 			/* buffer overflow will be checked at end of loop */
    475  1.6     lukem 			if (last_code == ident || last_code == rparen) {
    476  1.6     lukem 				code = (ps.last_u_d ? unary_op : postop);
    477  1.6     lukem 				/* check for following ++ or -- */
    478  1.6     lukem 				unary_delim = false;
    479  1.6     lukem 			}
    480  1.6     lukem 		} else
    481  1.6     lukem 			if (*buf_ptr == '=')
    482  1.6     lukem 				/* check for operator += */
    483  1.6     lukem 				*e_token++ = *buf_ptr++;
    484  1.6     lukem 			else
    485  1.6     lukem 				if (*buf_ptr == '>') {
    486  1.6     lukem 					/* check for operator -> */
    487  1.6     lukem 					*e_token++ = *buf_ptr++;
    488  1.6     lukem 					if (!pointer_as_binop) {
    489  1.6     lukem 						unary_delim = false;
    490  1.6     lukem 						code = unary_op;
    491  1.6     lukem 						ps.want_blank = false;
    492  1.6     lukem 					}
    493  1.6     lukem 				}
    494  1.6     lukem 		break;		/* buffer overflow will be checked at end of
    495  1.1       cgd 				 * switch */
    496  1.1       cgd 
    497  1.6     lukem 	case '=':
    498  1.6     lukem 		if (ps.in_or_st)
    499  1.6     lukem 			ps.block_init = 1;
    500  1.1       cgd #ifdef undef
    501  1.6     lukem 		if (chartype[*buf_ptr] == opchar) {	/* we have two char
    502  1.6     lukem 							 * assignment */
    503  1.6     lukem 			e_token[-1] = *buf_ptr++;
    504  1.6     lukem 			if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
    505  1.6     lukem 				*e_token++ = *buf_ptr++;
    506  1.6     lukem 			*e_token++ = '=';	/* Flip =+ to += */
    507  1.6     lukem 			*e_token = 0;
    508  1.6     lukem 		}
    509  1.1       cgd #else
    510  1.6     lukem 		if (*buf_ptr == '=') {	/* == */
    511  1.6     lukem 			*e_token++ = '=';	/* Flip =+ to += */
    512  1.6     lukem 			buf_ptr++;
    513  1.6     lukem 			*e_token = 0;
    514  1.6     lukem 		}
    515  1.1       cgd #endif
    516  1.6     lukem 		code = binary_op;
    517  1.6     lukem 		unary_delim = true;
    518  1.6     lukem 		break;
    519  1.6     lukem 		/* can drop thru!!! */
    520  1.6     lukem 
    521  1.6     lukem 	case '>':
    522  1.6     lukem 	case '<':
    523  1.6     lukem 	case '!':		/* ops like <, <<, <=, !=, etc */
    524  1.6     lukem 		if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
    525  1.6     lukem 			*e_token++ = *buf_ptr;
    526  1.6     lukem 			if (++buf_ptr >= buf_end)
    527  1.6     lukem 				fill_buffer();
    528  1.6     lukem 		}
    529  1.6     lukem 		if (*buf_ptr == '=')
    530  1.6     lukem 			*e_token++ = *buf_ptr++;
    531  1.6     lukem 		code = (ps.last_u_d ? unary_op : binary_op);
    532  1.6     lukem 		unary_delim = true;
    533  1.6     lukem 		break;
    534  1.6     lukem 
    535  1.6     lukem 	default:
    536  1.6     lukem 		if (token[0] == '/' && *buf_ptr == '*') {
    537  1.6     lukem 			/* it is start of comment */
    538  1.6     lukem 			*e_token++ = '*';
    539  1.6     lukem 
    540  1.6     lukem 			if (++buf_ptr >= buf_end)
    541  1.6     lukem 				fill_buffer();
    542  1.6     lukem 
    543  1.6     lukem 			code = comment;
    544  1.6     lukem 			unary_delim = ps.last_u_d;
    545  1.6     lukem 			break;
    546  1.6     lukem 		}
    547  1.6     lukem 		while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
    548  1.6     lukem 			/*
    549  1.6     lukem 		         * handle ||, &&, etc, and also things as in int *****i
    550  1.6     lukem 		         */
    551  1.6     lukem 			*e_token++ = *buf_ptr;
    552  1.6     lukem 			if (++buf_ptr >= buf_end)
    553  1.6     lukem 				fill_buffer();
    554  1.6     lukem 		}
    555  1.6     lukem 		code = (ps.last_u_d ? unary_op : binary_op);
    556  1.6     lukem 		unary_delim = true;
    557  1.1       cgd 
    558  1.1       cgd 
    559  1.6     lukem 	}			/* end of switch */
    560  1.6     lukem 	if (code != newline) {
    561  1.6     lukem 		l_struct = false;
    562  1.6     lukem 		last_code = code;
    563  1.1       cgd 	}
    564  1.6     lukem 	if (buf_ptr >= buf_end)	/* check for input buffer empty */
    565  1.1       cgd 		fill_buffer();
    566  1.6     lukem 	ps.last_u_d = unary_delim;
    567  1.6     lukem 	*e_token = '\0';	/* null terminate the token */
    568  1.6     lukem 	return (code);
    569  1.1       cgd }
    570  1.1       cgd /*
    571  1.1       cgd  * Add the given keyword to the keyword table, using val as the keyword type
    572  1.1       cgd  */
    573  1.6     lukem void
    574  1.1       cgd addkey(key, val)
    575  1.6     lukem 	char   *key;
    576  1.6     lukem 	int     val;
    577  1.1       cgd {
    578  1.6     lukem 	struct templ *p = specials;
    579  1.6     lukem 	while (p->rwd)
    580  1.6     lukem 		if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
    581  1.6     lukem 			return;
    582  1.6     lukem 		else
    583  1.6     lukem 			p++;
    584  1.6     lukem 	if (p >= specials + sizeof specials / sizeof specials[0])
    585  1.6     lukem 		return;		/* For now, table overflows are silently
    586  1.1       cgd 				 * ignored */
    587  1.6     lukem 	p->rwd = key;
    588  1.6     lukem 	p->rwcode = val;
    589  1.6     lukem 	p[1].rwd = 0;
    590  1.6     lukem 	p[1].rwcode = 0;
    591  1.1       cgd }
    592