1218885Sdim/* 2218885Sdim * Copyright (c) 1985 Sun Microsystems, Inc. 3218885Sdim * Copyright (c) 1980, 1993 4218885Sdim * The Regents of the University of California. All rights reserved. 5218885Sdim * All rights reserved. 6218885Sdim * 7218885Sdim * Redistribution and use in source and binary forms, with or without 8218885Sdim * modification, are permitted provided that the following conditions 9218885Sdim * are met: 10218885Sdim * 1. Redistributions of source code must retain the above copyright 11218885Sdim * notice, this list of conditions and the following disclaimer. 12218885Sdim * 2. Redistributions in binary form must reproduce the above copyright 13218885Sdim * notice, this list of conditions and the following disclaimer in the 14218885Sdim * documentation and/or other materials provided with the distribution. 15218885Sdim * 3. All advertising materials mentioning features or use of this software 16218885Sdim * must display the following acknowledgement: 17218885Sdim * This product includes software developed by the University of 18218885Sdim * California, Berkeley and its contributors. 19218885Sdim * 4. Neither the name of the University nor the names of its contributors 20218885Sdim * may be used to endorse or promote products derived from this software 21218885Sdim * without specific prior written permission. 22218885Sdim * 23218885Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24218885Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25218885Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26218885Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27218885Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28218885Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29218885Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30218885Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31218885Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32218885Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33218885Sdim * SUCH DAMAGE. 34218885Sdim */ 35218885Sdim 36218885Sdim#if 0 37218885Sdim#ifndef lint 38218885Sdimstatic char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93"; 39218885Sdim#endif /* not lint */ 40218885Sdim#endif 41218885Sdim#include <sys/cdefs.h> 42218885Sdim__FBSDID("$FreeBSD$"); 43218885Sdim 44218885Sdim/* 45218885Sdim * Here we have the token scanner for indent. It scans off one token and puts 46218885Sdim * it in the global variable "token". It returns a code, indicating the type 47218885Sdim * of token scanned. 48218885Sdim */ 49218885Sdim 50218885Sdim#include <err.h> 51218885Sdim#include <stdio.h> 52218885Sdim#include <ctype.h> 53218885Sdim#include <stdlib.h> 54218885Sdim#include <string.h> 55218885Sdim#include "indent_globs.h" 56218885Sdim#include "indent_codes.h" 57218885Sdim#include "indent.h" 58218885Sdim 59218885Sdim#define alphanum 1 60218885Sdim#define opchar 3 61218885Sdim 62218885Sdimstruct templ { 63218885Sdim const char *rwd; 64218885Sdim int rwcode; 65218885Sdim}; 66218885Sdim 67218885Sdimstruct templ specials[1000] = 68218885Sdim{ 69218885Sdim {"switch", 1}, 70218885Sdim {"case", 2}, 71218885Sdim {"break", 0}, 72218885Sdim {"struct", 3}, 73218885Sdim {"union", 3}, 74218885Sdim {"enum", 3}, 75218885Sdim {"default", 2}, 76218885Sdim {"int", 4}, 77218885Sdim {"char", 4}, 78218885Sdim {"float", 4}, 79218885Sdim {"double", 4}, 80218885Sdim {"long", 4}, 81218885Sdim {"short", 4}, 82218885Sdim {"typedef", 4}, 83218885Sdim {"unsigned", 4}, 84218885Sdim {"register", 4}, 85218885Sdim {"static", 4}, 86218885Sdim {"global", 4}, 87218885Sdim {"extern", 4}, 88218885Sdim {"void", 4}, 89218885Sdim {"const", 4}, 90218885Sdim {"volatile", 4}, 91218885Sdim {"goto", 0}, 92218885Sdim {"return", 0}, 93218885Sdim {"if", 5}, 94218885Sdim {"while", 5}, 95218885Sdim {"for", 5}, 96218885Sdim {"else", 6}, 97218885Sdim {"do", 6}, 98218885Sdim {"sizeof", 7}, 99218885Sdim {0, 0} 100218885Sdim}; 101218885Sdim 102249423Sdimchar chartype[128] = 103218885Sdim{ /* this is used to facilitate the decision of 104288943Sdim * what type (alphanumeric, operator) each 105218885Sdim * character is */ 106218885Sdim 0, 0, 0, 0, 0, 0, 0, 0, 107314564Sdim 0, 0, 0, 0, 0, 0, 0, 0, 108314564Sdim 0, 0, 0, 0, 0, 0, 0, 0, 109321369Sdim 0, 0, 0, 0, 0, 0, 0, 0, 110218885Sdim 0, 3, 0, 0, 1, 3, 3, 0, 111314564Sdim 0, 0, 3, 3, 0, 3, 0, 3, 112314564Sdim 1, 1, 1, 1, 1, 1, 1, 1, 113218885Sdim 1, 1, 0, 0, 3, 3, 3, 3, 114218885Sdim 0, 1, 1, 1, 1, 1, 1, 1, 115218885Sdim 1, 1, 1, 1, 1, 1, 1, 1, 116218885Sdim 1, 1, 1, 1, 1, 1, 1, 1, 117218885Sdim 1, 1, 1, 0, 0, 0, 3, 1, 118218885Sdim 0, 1, 1, 1, 1, 1, 1, 1, 119218885Sdim 1, 1, 1, 1, 1, 1, 1, 1, 120218885Sdim 1, 1, 1, 1, 1, 1, 1, 1, 121218885Sdim 1, 1, 1, 0, 3, 0, 3, 0 122218885Sdim}; 123218885Sdim 124218885Sdimint 125218885Sdimlexi(void) 126218885Sdim{ 127218885Sdim int unary_delim; /* this is set to 1 if the current token 128218885Sdim * forces a following operator to be unary */ 129218885Sdim static int last_code; /* the last token type returned */ 130218885Sdim static int l_struct; /* set to 1 if the last token was 'struct' */ 131218885Sdim int code; /* internal code to be returned */ 132218885Sdim char qchar; /* the delimiter character for a string */ 133218885Sdim 134218885Sdim e_token = s_token; /* point to start of place to save token */ 135218885Sdim unary_delim = false; 136218885Sdim ps.col_1 = ps.last_nl; /* tell world that this token started in 137218885Sdim * column 1 iff the last thing scanned was nl */ 138218885Sdim ps.last_nl = false; 139218885Sdim 140218885Sdim while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ 141218885Sdim ps.col_1 = false; /* leading blanks imply token is not in column 142218885Sdim * 1 */ 143218885Sdim if (++buf_ptr >= buf_end) 144218885Sdim fill_buffer(); 145218885Sdim } 146218885Sdim 147218885Sdim /* Scan an alphanumeric token */ 148218885Sdim if (chartype[(int)*buf_ptr] == alphanum || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { 149218885Sdim /* 150218885Sdim * we have a character or number 151218885Sdim */ 152218885Sdim const char *j; /* used for searching thru list of 153218885Sdim * 154218885Sdim * reserved words */ 155218885Sdim struct templ *p; 156314564Sdim 157314564Sdim if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) { 158314564Sdim int seendot = 0, 159314564Sdim seenexp = 0, 160314564Sdim seensfx = 0; 161218885Sdim if (*buf_ptr == '0' && 162218885Sdim (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) { 163249423Sdim *e_token++ = *buf_ptr++; 164249423Sdim *e_token++ = *buf_ptr++; 165249423Sdim while (isxdigit(*buf_ptr)) { 166249423Sdim CHECK_SIZE_TOKEN; 167249423Sdim *e_token++ = *buf_ptr++; 168249423Sdim } 169249423Sdim } 170249423Sdim else 171249423Sdim while (1) { 172249423Sdim if (*buf_ptr == '.') { 173249423Sdim if (seendot) 174249423Sdim break; 175249423Sdim else 176249423Sdim seendot++; 177249423Sdim } 178249423Sdim CHECK_SIZE_TOKEN; 179249423Sdim *e_token++ = *buf_ptr++; 180314564Sdim if (!isdigit(*buf_ptr) && *buf_ptr != '.') { 181314564Sdim if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp) 182314564Sdim break; 183314564Sdim else { 184249423Sdim seenexp++; 185249423Sdim seendot++; 186218885Sdim CHECK_SIZE_TOKEN; 187218885Sdim *e_token++ = *buf_ptr++; 188218885Sdim if (*buf_ptr == '+' || *buf_ptr == '-') 189218885Sdim *e_token++ = *buf_ptr++; 190321369Sdim } 191218885Sdim } 192218885Sdim } 193218885Sdim while (1) { 194218885Sdim if (!(seensfx & 1) && 195218885Sdim (*buf_ptr == 'U' || *buf_ptr == 'u')) { 196218885Sdim CHECK_SIZE_TOKEN; 197218885Sdim *e_token++ = *buf_ptr++; 198218885Sdim seensfx |= 1; 199218885Sdim continue; 200218885Sdim } 201218885Sdim if (!(seensfx & 2) && 202218885Sdim (*buf_ptr == 'L' || *buf_ptr == 'l')) { 203218885Sdim CHECK_SIZE_TOKEN; 204218885Sdim if (buf_ptr[1] == buf_ptr[0]) 205218885Sdim *e_token++ = *buf_ptr++; 206218885Sdim *e_token++ = *buf_ptr++; 207218885Sdim seensfx |= 2; 208218885Sdim continue; 209218885Sdim } 210218885Sdim break; 211218885Sdim } 212218885Sdim } 213218885Sdim else 214218885Sdim while (chartype[(int)*buf_ptr] == alphanum || *buf_ptr == BACKSLASH) { 215218885Sdim /* fill_buffer() terminates buffer with newline */ 216218885Sdim if (*buf_ptr == BACKSLASH) { 217218885Sdim if (*(buf_ptr + 1) == '\n') { 218218885Sdim buf_ptr += 2; 219218885Sdim if (buf_ptr >= buf_end) 220218885Sdim fill_buffer(); 221218885Sdim } else 222218885Sdim break; 223218885Sdim } 224218885Sdim CHECK_SIZE_TOKEN; 225218885Sdim /* copy it over */ 226218885Sdim *e_token++ = *buf_ptr++; 227218885Sdim if (buf_ptr >= buf_end) 228218885Sdim fill_buffer(); 229218885Sdim } 230218885Sdim *e_token++ = '\0'; 231218885Sdim while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */ 232218885Sdim if (++buf_ptr >= buf_end) 233218885Sdim fill_buffer(); 234218885Sdim } 235218885Sdim ps.its_a_keyword = false; 236218885Sdim ps.sizeof_keyword = false; 237218885Sdim if (l_struct && !ps.p_l_follow) { 238218885Sdim /* if last token was 'struct' and we're not 239218885Sdim * in parentheses, then this token 240218885Sdim * should be treated as a declaration */ 241218885Sdim l_struct = false; 242218885Sdim last_code = ident; 243218885Sdim ps.last_u_d = true; 244218885Sdim return (decl); 245218885Sdim } 246218885Sdim ps.last_u_d = l_struct; /* Operator after identifier is binary 247218885Sdim * unless last token was 'struct' */ 248218885Sdim l_struct = false; 249218885Sdim last_code = ident; /* Remember that this is the code we will 250218885Sdim * return */ 251218885Sdim 252218885Sdim if (auto_typedefs) { 253218885Sdim const char *q = s_token; 254218885Sdim size_t q_len = strlen(q); 255218885Sdim /* Check if we have an "_t" in the end */ 256218885Sdim if (q_len > 2 && 257218885Sdim (strcmp(q + q_len - 2, "_t") == 0)) { 258218885Sdim ps.its_a_keyword = true; 259218885Sdim ps.last_u_d = true; 260218885Sdim goto found_auto_typedef; 261218885Sdim } 262218885Sdim } 263218885Sdim 264218885Sdim /* 265218885Sdim * This loop will check if the token is a keyword. 266218885Sdim */ 267218885Sdim for (p = specials; (j = p->rwd) != 0; p++) { 268218885Sdim const char *q = s_token; /* point at scanned token */ 269218885Sdim if (*j++ != *q++ || *j++ != *q++) 270218885Sdim continue; /* This test depends on the fact that 271218885Sdim * identifiers are always at least 1 character 272218885Sdim * long (ie. the first two bytes of the 273218885Sdim * identifier are always meaningful) */ 274218885Sdim if (q[-1] == 0) 275218885Sdim break; /* If its a one-character identifier */ 276218885Sdim while (*q++ == *j) 277218885Sdim if (*j++ == 0) 278218885Sdim goto found_keyword; /* I wish that C had a multi-level 279218885Sdim * break... */ 280218885Sdim } 281218885Sdim if (p->rwd) { /* we have a keyword */ 282218885Sdim found_keyword: 283218885Sdim ps.its_a_keyword = true; 284218885Sdim ps.last_u_d = true; 285218885Sdim switch (p->rwcode) { 286218885Sdim case 1: /* it is a switch */ 287218885Sdim return (swstmt); 288218885Sdim case 2: /* a case or default */ 289218885Sdim return (casestmt); 290218885Sdim 291218885Sdim case 3: /* a "struct" */ 292218885Sdim /* 293218885Sdim * Next time around, we will want to know that we have had a 294218885Sdim * 'struct' 295218885Sdim */ 296218885Sdim l_struct = true; 297218885Sdim /* FALLTHROUGH */ 298218885Sdim 299218885Sdim case 4: /* one of the declaration keywords */ 300218885Sdim found_auto_typedef: 301218885Sdim if (ps.p_l_follow) { 302218885Sdim ps.cast_mask |= (1 << ps.p_l_follow) & ~ps.sizeof_mask; 303218885Sdim break; /* inside parens: cast, param list or sizeof */ 304218885Sdim } 305218885Sdim last_code = decl; 306218885Sdim return (decl); 307218885Sdim 308218885Sdim case 5: /* if, while, for */ 309218885Sdim return (sp_paren); 310218885Sdim 311218885Sdim case 6: /* do, else */ 312218885Sdim return (sp_nparen); 313218885Sdim 314218885Sdim case 7: 315218885Sdim ps.sizeof_keyword = true; 316218885Sdim default: /* all others are treated like any other 317218885Sdim * identifier */ 318218885Sdim return (ident); 319218885Sdim } /* end of switch */ 320218885Sdim } /* end of if (found_it) */ 321218885Sdim if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) { 322218885Sdim char *tp = buf_ptr; 323218885Sdim while (tp < buf_end) 324218885Sdim if (*tp++ == ')' && (*tp == ';' || *tp == ',')) 325218885Sdim goto not_proc; 326218885Sdim strncpy(ps.procname, token, sizeof ps.procname - 1); 327218885Sdim ps.in_parameter_declaration = 1; 328218885Sdim rparen_count = 1; 329218885Sdim not_proc:; 330218885Sdim } 331218885Sdim /* 332218885Sdim * The following hack attempts to guess whether or not the current 333218885Sdim * token is in fact a declaration keyword -- one that has been 334218885Sdim * typedefd 335218885Sdim */ 336218885Sdim if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_') 337218885Sdim && !ps.p_l_follow 338218885Sdim && !ps.block_init 339218885Sdim && (ps.last_token == rparen || ps.last_token == semicolon || 340218885Sdim ps.last_token == decl || 341218885Sdim ps.last_token == lbrace || ps.last_token == rbrace)) { 342218885Sdim ps.its_a_keyword = true; 343218885Sdim ps.last_u_d = true; 344218885Sdim last_code = decl; 345218885Sdim return decl; 346218885Sdim } 347218885Sdim if (last_code == decl) /* if this is a declared variable, then 348218885Sdim * following sign is unary */ 349218885Sdim ps.last_u_d = true; /* will make "int a -1" work */ 350218885Sdim last_code = ident; 351218885Sdim return (ident); /* the ident is not in the list */ 352218885Sdim } /* end of procesing for alpanum character */ 353218885Sdim 354218885Sdim /* Scan a non-alphanumeric token */ 355218885Sdim 356218885Sdim *e_token++ = *buf_ptr; /* if it is only a one-character token, it is 357218885Sdim * moved here */ 358218885Sdim *e_token = '\0'; 359218885Sdim if (++buf_ptr >= buf_end) 360218885Sdim fill_buffer(); 361218885Sdim 362218885Sdim switch (*token) { 363218885Sdim case '\n': 364218885Sdim unary_delim = ps.last_u_d; 365218885Sdim ps.last_nl = true; /* remember that we just had a newline */ 366218885Sdim code = (had_eof ? 0 : newline); 367218885Sdim 368218885Sdim /* 369218885Sdim * if data has been exhausted, the newline is a dummy, and we should 370218885Sdim * return code to stop 371218885Sdim */ 372218885Sdim break; 373218885Sdim 374218885Sdim case '\'': /* start of quoted character */ 375218885Sdim case '"': /* start of string */ 376218885Sdim qchar = *token; 377218885Sdim if (troff) { 378218885Sdim e_token[-1] = '`'; 379218885Sdim if (qchar == '"') 380218885Sdim *e_token++ = '`'; 381218885Sdim e_token = chfont(&bodyf, &stringf, e_token); 382218885Sdim } 383218885Sdim do { /* copy the string */ 384218885Sdim while (1) { /* move one character or [/<char>]<char> */ 385218885Sdim if (*buf_ptr == '\n') { 386218885Sdim diag2(1, "Unterminated literal"); 387218885Sdim goto stop_lit; 388218885Sdim } 389218885Sdim CHECK_SIZE_TOKEN; /* Only have to do this once in this loop, 390218885Sdim * since CHECK_SIZE guarantees that there 391218885Sdim * are at least 5 entries left */ 392218885Sdim *e_token = *buf_ptr++; 393218885Sdim if (buf_ptr >= buf_end) 394218885Sdim fill_buffer(); 395218885Sdim if (*e_token == BACKSLASH) { /* if escape, copy extra char */ 396218885Sdim if (*buf_ptr == '\n') /* check for escaped newline */ 397218885Sdim ++line_no; 398218885Sdim if (troff) { 399218885Sdim *++e_token = BACKSLASH; 400218885Sdim if (*buf_ptr == BACKSLASH) 401218885Sdim *++e_token = BACKSLASH; 402218885Sdim } 403218885Sdim *++e_token = *buf_ptr++; 404218885Sdim ++e_token; /* we must increment this again because we 405218885Sdim * copied two chars */ 406218885Sdim if (buf_ptr >= buf_end) 407218885Sdim fill_buffer(); 408218885Sdim } 409218885Sdim else 410218885Sdim break; /* we copied one character */ 411218885Sdim } /* end of while (1) */ 412218885Sdim } while (*e_token++ != qchar); 413218885Sdim if (troff) { 414218885Sdim e_token = chfont(&stringf, &bodyf, e_token - 1); 415218885Sdim if (qchar == '"') 416218885Sdim *e_token++ = '\''; 417218885Sdim } 418218885Sdimstop_lit: 419218885Sdim code = ident; 420218885Sdim break; 421218885Sdim 422218885Sdim case ('('): 423218885Sdim case ('['): 424218885Sdim unary_delim = true; 425218885Sdim code = lparen; 426218885Sdim break; 427218885Sdim 428218885Sdim case (')'): 429218885Sdim case (']'): 430218885Sdim code = rparen; 431218885Sdim break; 432218885Sdim 433218885Sdim case '#': 434218885Sdim unary_delim = ps.last_u_d; 435218885Sdim code = preesc; 436218885Sdim break; 437218885Sdim 438218885Sdim case '?': 439218885Sdim unary_delim = true; 440218885Sdim code = question; 441218885Sdim break; 442218885Sdim 443218885Sdim case (':'): 444218885Sdim code = colon; 445218885Sdim unary_delim = true; 446218885Sdim break; 447218885Sdim 448218885Sdim case (';'): 449321369Sdim unary_delim = true; 450218885Sdim code = semicolon; 451218885Sdim break; 452218885Sdim 453218885Sdim case ('{'): 454218885Sdim unary_delim = true; 455218885Sdim 456218885Sdim /* 457218885Sdim * if (ps.in_or_st) ps.block_init = 1; 458218885Sdim */ 459218885Sdim /* ? code = ps.block_init ? lparen : lbrace; */ 460218885Sdim code = lbrace; 461218885Sdim break; 462218885Sdim 463218885Sdim case ('}'): 464218885Sdim unary_delim = true; 465321369Sdim /* ? code = ps.block_init ? rparen : rbrace; */ 466321369Sdim code = rbrace; 467218885Sdim break; 468218885Sdim 469218885Sdim case 014: /* a form feed */ 470218885Sdim unary_delim = ps.last_u_d; 471218885Sdim ps.last_nl = true; /* remember this so we can set 'ps.col_1' 472218885Sdim * right */ 473218885Sdim code = form_feed; 474218885Sdim break; 475218885Sdim 476218885Sdim case (','): 477218885Sdim unary_delim = true; 478218885Sdim code = comma; 479218885Sdim break; 480218885Sdim 481218885Sdim case '.': 482218885Sdim unary_delim = false; 483218885Sdim code = period; 484218885Sdim break; 485218885Sdim 486218885Sdim case '-': 487218885Sdim case '+': /* check for -, +, --, ++ */ 488218885Sdim code = (ps.last_u_d ? unary_op : binary_op); 489218885Sdim unary_delim = true; 490218885Sdim 491218885Sdim if (*buf_ptr == token[0]) { 492218885Sdim /* check for doubled character */ 493218885Sdim *e_token++ = *buf_ptr++; 494218885Sdim /* buffer overflow will be checked at end of loop */ 495218885Sdim if (last_code == ident || last_code == rparen) { 496218885Sdim code = (ps.last_u_d ? unary_op : postop); 497218885Sdim /* check for following ++ or -- */ 498218885Sdim unary_delim = false; 499218885Sdim } 500314564Sdim } 501218885Sdim else if (*buf_ptr == '=') 502218885Sdim /* check for operator += */ 503288943Sdim *e_token++ = *buf_ptr++; 504218885Sdim else if (*buf_ptr == '>') { 505218885Sdim /* check for operator -> */ 506218885Sdim *e_token++ = *buf_ptr++; 507218885Sdim if (!pointer_as_binop) { 508218885Sdim unary_delim = false; 509218885Sdim code = unary_op; 510218885Sdim ps.want_blank = false; 511218885Sdim } 512218885Sdim } 513218885Sdim break; /* buffer overflow will be checked at end of 514218885Sdim * switch */ 515218885Sdim 516218885Sdim case '=': 517218885Sdim if (ps.in_or_st) 518218885Sdim ps.block_init = 1; 519218885Sdim#ifdef undef 520218885Sdim if (chartype[*buf_ptr] == opchar) { /* we have two char assignment */ 521218885Sdim e_token[-1] = *buf_ptr++; 522218885Sdim if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr) 523218885Sdim *e_token++ = *buf_ptr++; 524218885Sdim *e_token++ = '='; /* Flip =+ to += */ 525218885Sdim *e_token = 0; 526218885Sdim } 527218885Sdim#else 528218885Sdim if (*buf_ptr == '=') {/* == */ 529218885Sdim *e_token++ = '='; /* Flip =+ to += */ 530218885Sdim buf_ptr++; 531218885Sdim *e_token = 0; 532218885Sdim } 533218885Sdim#endif 534218885Sdim code = binary_op; 535218885Sdim unary_delim = true; 536218885Sdim break; 537218885Sdim /* can drop thru!!! */ 538218885Sdim 539218885Sdim case '>': 540218885Sdim case '<': 541218885Sdim case '!': /* ops like <, <<, <=, !=, etc */ 542218885Sdim if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') { 543218885Sdim *e_token++ = *buf_ptr; 544218885Sdim if (++buf_ptr >= buf_end) 545218885Sdim fill_buffer(); 546218885Sdim } 547218885Sdim if (*buf_ptr == '=') 548218885Sdim *e_token++ = *buf_ptr++; 549218885Sdim code = (ps.last_u_d ? unary_op : binary_op); 550218885Sdim unary_delim = true; 551218885Sdim break; 552218885Sdim 553218885Sdim default: 554218885Sdim if (token[0] == '/' && *buf_ptr == '*') { 555218885Sdim /* it is start of comment */ 556218885Sdim *e_token++ = '*'; 557218885Sdim 558218885Sdim if (++buf_ptr >= buf_end) 559218885Sdim fill_buffer(); 560218885Sdim 561218885Sdim code = comment; 562218885Sdim unary_delim = ps.last_u_d; 563218885Sdim break; 564218885Sdim } 565218885Sdim while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') { 566218885Sdim /* 567218885Sdim * handle ||, &&, etc, and also things as in int *****i 568218885Sdim */ 569218885Sdim *e_token++ = *buf_ptr; 570218885Sdim if (++buf_ptr >= buf_end) 571218885Sdim fill_buffer(); 572218885Sdim } 573218885Sdim code = (ps.last_u_d ? unary_op : binary_op); 574218885Sdim unary_delim = true; 575218885Sdim 576218885Sdim 577218885Sdim } /* end of switch */ 578218885Sdim if (code != newline) { 579218885Sdim l_struct = false; 580218885Sdim last_code = code; 581218885Sdim } 582218885Sdim if (buf_ptr >= buf_end) /* check for input buffer empty */ 583218885Sdim fill_buffer(); 584218885Sdim ps.last_u_d = unary_delim; 585218885Sdim *e_token = '\0'; /* null terminate the token */ 586218885Sdim return (code); 587218885Sdim} 588218885Sdim 589218885Sdim/* 590218885Sdim * Add the given keyword to the keyword table, using val as the keyword type 591218885Sdim */ 592218885Sdimvoid 593218885Sdimaddkey(char *key, int val) 594218885Sdim{ 595218885Sdim struct templ *p = specials; 596218885Sdim while (p->rwd) 597218885Sdim if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0) 598218885Sdim return; 599218885Sdim else 600218885Sdim p++; 601218885Sdim if (p >= specials + sizeof specials / sizeof specials[0]) 602218885Sdim return; /* For now, table overflows are silently 603218885Sdim * ignored */ 604218885Sdim p->rwd = key; 605218885Sdim p->rwcode = val; 606218885Sdim p[1].rwd = 0; 607218885Sdim p[1].rwcode = 0; 608218885Sdim} 609218885Sdim