From: VZDMZA::IN%"HUBER%DM0MPI53.BITNET@vm.gmd.de" "Joseph Huber, MPI Muenchen" 19-FEB-1992 15:34:38.43 To: IN%"WIEHL@VKCMZD.Chemie.Uni-Mainz.de" CC: Subj: INDENT PART 3 of 5 Received: from vm.gmd.de by VzdmzA.ZDV.Uni-Mainz.DE (PMDF #12046) id <01GGPHYO7MXS8WW2UP@VzdmzA.ZDV.Uni-Mainz.DE>; Wed, 19 Feb 1992 15:25 GMT +0100 Received: from DM0MPI11 by vm.gmd.de (IBM VM SMTP R1.2.2MX) with BSMTP id 3097; Wed, 19 Feb 92 15:27:01 CET Received: from DM0MPI53.BITNET (DM0MPI53@DM0MPI12) by DM0MPI11 (Mailer R2.08) with BSMTP id 9554; Wed, 19 Feb 92 15:27:39 GMT Date: Wed, 19 Feb 92 15:20 +0200 From: "Joseph Huber, MPI Muenchen" Subject: INDENT PART 3 of 5 To: WIEHL@VKCMZD.Chemie.Uni-Mainz.de Message-id: <01GGPHYO7MXS8WW2UP@VzdmzA.ZDV.Uni-Mainz.DE> Organization: Max-Planck-Institut fuer Physik, Muenchen X-Envelope-to: WIEHL@VKCMZD.Chemie.Uni-Mainz.de X-Delivery-Notice: SMTP MAIL FROM does not correspond to sender. X-Original-To: RSCS%"WIEHL@VKCMZD.CHEMIE.UNI-MAINZ.DE" Comments: This is gatewayed mail. WARNING: Mail may not necessarily be returnable thru this path. -+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+ X`09`09`09p = in_buffer + offset; X`09`09`09in_buffer_limit = in_buffer + size - 2; X`09`09`7D X`09`09if ((i = getc(f)) == EOF) `7B X`09`09`09*p++ = ' '; X`09`09`09*p++ = '\n'; X`09`09`09had_eof = true; X`09`09`09break; X`09`09`7D X`09`09*p++ = i; X`09`09if (i == '\n') X`09`09`09break; X`09`7D X`09buf_ptr = in_buffer; X`09buf_end = p; X`09if (p`5B-2`5D == '/' && p`5B-3`5D == '*') `7B X`09`09if (in_buffer`5B3`5D == 'I' && strncmp(in_buffer, "/**INDENT**", 11) = V= 0) X`09`09`09fill_buffer();`09/* flush indent error message */ X`09`09else `7B X`09`09`09int com = 0; X X`09`09`09p = in_buffer; X`09`09`09while (*p == ' ' `7C`7C *p == '\t') X`09`09`09`09p++; X`09`09`09if (*p == '/' && p`5B1`5D == '*') `7B X`09`09`09`09p += 2; X`09`09`09`09while (*p == ' ' `7C`7C *p == '\t') X`09`09`09`09`09p++; X`09`09`09`09if (p`5B0`5D == 'I' && p`5B1`5D == 'N' && p`5B2`5D == 'D' && p`5 VB3`5D == 'E' X`09`09`09`09 && p`5B4`5D == 'N' && p`5B5`5D == 'T') `7B X`09`09`09`09`09p += 6; X`09`09`09`09`09while (*p == ' ' `7C`7C *p == '\t') X`09`09`09`09`09`09p++; X`09`09`09`09`09if (*p == '*') X`09`09`09`09`09`09com = 1; X`09`09`09`09`09else if (*p == 'O') X`09`09`09`09`09`09if (*++p == 'N') X`09`09`09`09`09`09`09p++, com = 1; X`09`09`09`09`09`09else if (*p == 'F' && *++p == 'F') X`09`09`09`09`09`09`09p++, com = 2; X`09`09`09`09`09while (*p == ' ' `7C`7C *p == '\t') X`09`09`09`09`09`09p++; X`09`09`09`09`09if (p`5B0`5D == '*' && p`5B1`5D == '/' && p`5B2`5D == '\n' && V com) `7B X`09`09`09`09`09`09if (s_com != e_com `7C`7C s_lab != e_lab `7C`7C s_code != V e_code) X`09`09`09`09`09`09`09dump_line(); X`09`09`09`09`09`09if (!(inhibit_formatting = com - 1)) `7B X`09`09`09`09`09`09`09n_real_blanklines = 0; X`09`09`09`09`09`09`09postfix_blankline_requested = 0; X`09`09`09`09`09`09`09prefix_blankline_requested = 0; X`09`09`09`09`09`09`09suppress_blanklines = 1; X`09`09`09`09`09`09`7D X`09`09`09`09`09`7D X`09`09`09`09`7D X`09`09`09`7D X`09`09`7D X`09`7D X`09if (inhibit_formatting) `7B X`09`09p = in_buffer; X`09`09do X`09`09`09putc(*p, output); X`09`09while (*p++ != '\n'); X`09`7D X`09return; X`7D X X/* X * Copyright (C) 1976 by the Board of Trustees of the University of Illinois X *`20 X * All rights reserved X *`20 X *`20 X * NAME: pad_output X *`20 X * FUNCTION: Writes tabs and spaces to move the current column up to the des Vired X * position. X *`20 X * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. X *`20 X * PARAMETERS: current`09`09integer`09`09The current column target X * nteger`09`09The desired column X *`20 X * RETURNS: Integer value of the new column. (If current >= target, no acti Von X * is taken, and current is returned. X *`20 X * GLOBALS: None X *`20 X * CALLS: write (sys) X *`20 X * CALLED BY: dump_line X *`20 X * HISTORY: initial coding `09November 1976`09D A Willcox of CAC X *`20 X */ Xpad_output(current, target)`09/* writes tabs and blanks (if necessary) to X`09`09`09`09 * get the current output position up to the X`09`09`09`09 * target column */ X`09int current;/* the current column value */ X`09int target;`09/* position we want it at */ X`7B X`09register int curr;`09/* internal column pointer */ X`09register int tcur; X X`09if (troff) X`09`09fprintf(output, "\\h'`7C%dp'", (target - 1) * 7); X`09else `7B X`09`09if (current >= target) X`09`09`09return (current);`09/* line is already long X`09`09`09`09`09`09 * enough */ X`09`09curr = current; X`09`09while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) `7B X`09`09`09putc('\t', output); X`09`09`09curr = tcur; X`09`09`7D X`09`09while (curr++ < target) X`09`09`09putc(' ', output);`09/* pad with final blanks */ X`09`7D X`09return (target); X`7D X X/* X * Copyright (C) 1976 by the Board of Trustees of the University of Illinois X *`20 X * All rights reserved X *`20 X *`20 X * NAME: count_spaces X *`20 X * FUNCTION: Find out where printing of a given string will leave the curren Vt X * character position on output. X *`20 X * ALGORITHM: Run thru input string and add appropriate values to current X * position. X *`20 X * RETURNS: Integer value of position after printing "buffer" starting in co Vlumn X * "current". X *`20 X * HISTORY: initial coding `09November 1976`09D A Willcox of CAC X *`20 X */ Xint Xcount_spaces(current, buffer, lastchar) X/* X * this routine figures out where the character position will be after X * printing the text in buffer starting at column "current" X */ X`09int current; X`09int lastchar; X`09char *buffer; X`7B X int *arg_list = ¤t-1; X`09register char *buf;`09/* used to look thru buffer */ X`09register int cur;`09/* current character counter */ X X`09cur = current; X X`09for (buf = buffer; *buf != '\0'`09&& (arg_list`5B0`5D == 2 X`09`09`7C`7C buf < lastchar); ++buf) `7B X`09`09switch (*buf) `7B X X`09`09case '\n': X`09`09case 014:`09/* form feed */ X`09`09`09cur = 1; X`09`09`09break; X X`09`09case '\t': X`09`09`09cur = ((cur - 1) & tabmask) + tabsize + 1; X`09`09`09break; X X`09`09case 010:`09/* backspace */ X`09`09`09--cur; X`09`09`09break; X X`09`09default: X`09`09`09++cur; X`09`09`09break; X`09`09`7D`09`09/* end of switch */ X`09`7D`09`09`09/* end of for loop */ X`09return (cur); X`7D X Xint found_err; X/* VARARGS2 */ Xdiag(level, msg, a, b) X`7B X`09if (level) X`09`09found_err = 1; X`09if (output == stdout) `7B X`09`09fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error V", line_no); X`09`09fprintf(stdout, msg, a, b); X`09`09fprintf(stdout, " */\n"); X`09`7D else `7B X`09`09fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no); X`09`09fprintf(stderr, msg, a, b); X`09`09fprintf(stderr, "\n"); X`09`7D X`7D X Xwritefdef(f, nm) X`09register struct fstate *f; X`7B X`09fprintf(output, ".ds f%c %s\n.nr s%c %d\n", X`09`09nm, f->font, nm, f->size); X`7D X Xchar * Xchfont(of, nf, s) X`09register struct fstate *of, *nf; X`09char *s; X`7B X`09if (of->font`5B0`5D != nf->font`5B0`5D X`09 `7C`7C of->font`5B1`5D != nf->font`5B1`5D) `7B X`09`09*s++ = '\\'; X`09`09*s++ = 'f'; X`09`09if (nf->font`5B1`5D) `7B X`09`09`09*s++ = '('; X`09`09`09*s++ = nf->font`5B0`5D; X`09`09`09*s++ = nf->font`5B1`5D; X`09`09`7D else X`09`09`09*s++ = nf->font`5B0`5D; X`09`7D X`09if (nf->size != of->size) `7B X`09`09*s++ = '\\'; X`09`09*s++ = 's'; X`09`09if (nf->size < of->size) `7B X`09`09`09*s++ = '-'; X`09`09`09*s++ = '0' + of->size - nf->size; X`09`09`7D else `7B X`09`09`09*s++ = '+'; X`09`09`09*s++ = '0' + nf->size - of->size; X`09`09`7D X`09`7D X`09return s; X`7D X X Xparsefont(f, s0) X`09register struct fstate *f; X`09char *s0; X`7B X`09register char *s = s0; X`09int sizedelta = 0; X`09memset(f, 0, sizeof *f); X`09while (*s) `7B X`09`09if (isdigit(*s)) X`09`09`09f->size = f->size * 10 + *s - '0'; X`09`09else if (isupper(*s)) X`09`09`09if (f->font`5B0`5D) X`09`09`09`09f->font`5B1`5D = *s; X`09`09`09else X`09`09`09`09f->font`5B0`5D = *s; X`09`09else if (*s == 'c') X`09`09`09f->allcaps = 1; X`09`09else if (*s == '+') X`09`09`09sizedelta++; X`09`09else if (*s == '-') X`09`09`09sizedelta--; X`09`09else `7B X`09`09`09fprintf(stderr, "indent: bad font specification: %s\n", s0); X`09`09`09exit(1); X`09`09`7D X`09`09s++; X`09`7D X`09if (f->font`5B0`5D == 0) X`09`09f->font`5B0`5D = 'R'; X`09if (bodyf.size == 0) X`09`09bodyf.size = 11; X`09if (f->size == 0) X`09`09f->size = bodyf.size + sizedelta; X`09else if (sizedelta > 0) X`09`09f->size += bodyf.size; X`09else X`09`09f->size = bodyf.size - f->size; X`7D $ CALL UNPACK IO.C;18 880289887 $ create 'f' X/* X * Copyright (c) 1985 Sun Microsystems, Inc. X * Copyright (c) 1980 The Regents of the University of California. X * Copyright (c) 1976 Board of Trustees of the University of Illinois. X * All rights reserved. X *`20 X * Redistribution and use in source and binary forms are permitted X * provided that: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: `60`60This product includes software X * developed by the University of California, Berkeley and its contributors' V' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED `60`60AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xstatic char sccsid`5B`5D = "@(#)lexi.c`095.15 (Berkeley) 6/1/90"; X#endif`09`09`09`09/* not lint */ X X/* X * Here we have the token scanner for indent. It scans off one token and pu Vts X * it in the global variable "token". It returns a code, indicating the typ Ve X * of token scanned. X */ X X#include "indent_globs.h" X#include "indent_codes.h" X#ifdef VMS X#include X#else X#include "ctype.h" X#endif X X#define alphanum 1 X#define opchar 3 X Xstruct templ X`7B X char *rwd; X int rwcode; X`7D; X Xstruct templ specials`5B100`5D = X`7B X "switch", 1, X "case", 2, X "break", 0, X "struct", 3, X "union", 3, X "enum", 3, X "default", 2, X "int", 4, X "char", 4, X "float", 4, X "double", 4, X "long", 4, X "short", 4, X "typdef", 4, X "unsigned", 4, X "register", 4, X "static", 4, X "global", 4, X "extern", 4, X "void", 4, X "goto", 0, X "return", 0, X "if", 5, X "while", 5, X "for", 5, X "else", 6, X "do", 6, X "sizeof", 7, X 0, 0 X`7D; X Xchar chartype`5B128`5D = X`7B`09`09`09`09/* this is used to facilitate the decision of X`09`09`09`09 * what type (alphanumeric, operator) each X`09`09`09`09 * character is */ X 0, 0, 0, 0, 0, 0, 0, 0, X 0, 0, 0, 0, 0, 0, 0, 0, X 0, 0, 0, 0, 0, 0, 0, 0, X 0, 0, 0, 0, 0, 0, 0, 0, X 0, 3, 0, 0, 1, 3, 3, 0, X 0, 0, 3, 3, 0, 3, 0, 3, X 1, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 0, 0, 3, 3, 3, 3, X 0, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 1, 0, 0, 0, 3, 1, X 0, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 1, 1, 1, 1, 1, 1, X 1, 1, 1, 0, 3, 0, 3, 0 X`7D; X X X X Xint X lexi() X`7B X int unary_delim;`09`09/* this is set to 1 if the current token X`09`09`09`09 *`20 X`09`09`09`09 * forces a following operator to be unary */ X static int last_code;`09`09/* the last token type returned */ X static int l_struct;`09`09/* set to 1 if the last token was 'struct' */ X int code;`09`09`09/* internal code to be returned */ X char qchar;`09`09`09/* the delimiter character for a string */ X int sflg = (buf_ptr == in_buffer); X X e_token = s_token;`09`09/* point to start of place to save token */ X unary_delim = false; X ps.col_1 = ps.last_nl;`09/* tell world that this token started in X`09`09`09`09 * column 1 iff the last thing scanned was nl */ X ps.last_nl = false; X X if (!sflg && ps.block_init X && (*buf_ptr == ' ' `7C`7C *buf_ptr == '\t')) X `7B X *e_token++ = *buf_ptr++; X *e_token++ = '\0'; X ps.want_blank = false; X last_code = ident; X return (ident);`09`09/* the ident is not in the list */ X `7D X if (sflg) X this_indent = 0; X while (*buf_ptr == ' ' `7C`7C *buf_ptr == '\t') X `7B`09`09`09`09/* get rid of blanks */ X ps.col_1 = false;`09`09/* leading blanks imply token is not in column X`09`09`09`09 * 1 */ X if (sflg) X `7B X if (*buf_ptr == ' ') this_indent++; X else if (*buf_ptr == '\t') X`09this_indent = ((this_indent + 8) / 8) * 8; X `7D X if (++buf_ptr >= buf_end) X `7B X if (sflg) X `7B X`09prev_indent = this_indent; X`09this_indent = 0; X `7D X fill_buffer(); X `7D X `7D X if (sflg && !ps.ind_stmt) prev_indent = this_indent; X X /* Scan an alphanumeric token */ X if (chartype`5B*buf_ptr`5D == alphanum `7C`7C buf_ptr`5B0`5D == '.' && isd Vigit(buf_ptr`5B1`5D)) X `7B X /* X * we have a character or number X */ X register char *j;`09`09/* used for searching thru list of X`09`09`09`09 *`20 X`09`09`09`09 * reserved words */ X register struct templ *p; X X if (isdigit(*buf_ptr) `7C`7C buf_ptr`5B0`5D == '.' && isdigit(buf_ptr`5B V1`5D)) X `7B X int seendot = 0,seenexp = 0; X if (*buf_ptr == '0' && X`09 (buf_ptr`5B1`5D == 'x' `7C`7C buf_ptr`5B1`5D == 'X')) X `7B X`09*e_token++ = *buf_ptr++; X`09*e_token++ = *buf_ptr++; X`09while (isxdigit(*buf_ptr)) X`09`7B X`09 CHECK_SIZE_TOKEN; X`09 *e_token++ = *buf_ptr++; X`09`7D X `7D X else X`09while (1) X`09`7B X`09 if (*buf_ptr == '.') X`09 if (seendot) X`09 break; X`09 else X`09 seendot++; X`09 CHECK_SIZE_TOKEN; X`09 *e_token++ = *buf_ptr++; X`09 if (!isdigit(*buf_ptr) && *buf_ptr != '.') X`09 if ((*buf_ptr != 'E' && *buf_ptr != 'e') `7C`7C seenexp) X`09 break; X`09 else X`09 `7B X`09 seenexp++; X`09 seendot++; X`09 CHECK_SIZE_TOKEN; X`09 *e_token++ = *buf_ptr++; X`09 if (*buf_ptr == '+' `7C`7C *buf_ptr == '-') X`09`09*e_token++ = *buf_ptr++; X`09 `7D X`09`7D X if (*buf_ptr == 'L' `7C`7C *buf_ptr == 'l') X`09*e_token++ = *buf_ptr++; X `7D X else X while (chartype`5B*buf_ptr`5D == alphanum) X `7B`09`09`09`09/* copy it over */ X`09CHECK_SIZE_TOKEN; X`09*e_token++ = *buf_ptr++; X`09if (buf_ptr >= buf_end) X`09 fill_buffer(); X `7D X *e_token++ = '\0'; X while (*buf_ptr == ' ' `7C`7C *buf_ptr == '\t') X `7B`09`09`09`09/* get rid of blanks */ X if (++buf_ptr >= buf_end) X`09fill_buffer(); X `7D X ps.its_a_keyword = false; X ps.sizeof_keyword = false; X if (l_struct) X `7B`09`09`09`09/* if last token was 'struct', then this token X`09`09`09`09 * should be treated as a declaration */ X l_struct = false; X last_code = ident; X ps.last_u_d = true; X return (decl); X `7D X ps.last_u_d = false;`09/* Operator after indentifier is binary */ X last_code = ident;`09`09/* Remember that this is the code we will X`09`09`09`09 * return */ X X /* X * This loop will check if the token is a keyword. X */ X for (p = specials; (j = p->rwd) != 0; p++) X `7B X register char *p = s_token;`09/* point at scanned token */ X if (*j++ != *p++ `7C`7C *j++ != *p++) X`09continue;`09`09/* This test depends on the fact that X`09`09`09`09 * identifiers are always at least 1 character X`09`09`09`09 * long (ie. the first two bytes of the X`09`09`09`09 * identifier are always meaningful) */ X if (p`5B-1`5D == 0) X`09break;`09`09`09/* If its a one-character identifier */ X while (*p++ == *j) X`09if (*j++ == 0) X`09 goto found_keyword;`09/* I wish that C had a multi-level X`09`09`09`09 * break... */ X `7D X if (p->rwd) X `7B`09`09`09`09/* we have a keyword */ X found_keyword: X ps.its_a_keyword = true; X ps.last_u_d = true; X switch (p->rwcode) X `7B X`09case 1:`09`09/* it is a switch */ X`09 return (swstmt); X`09case 2:`09`09/* a case or default */ X`09 return (casestmt); X X`09case 3:`09`09/* a "struct" */ X`09 if (ps.p_l_follow) X`09 break;`09`09/* inside parens: cast */ X`09 l_struct = true; X X`09 /* X`09 * next time around, we will want to know that we have had a X`09 * 'struct' X`09 */ X`09case 4:`09`09/* one of the declaration keywords */ X`09 if (ps.p_l_follow) X`09 `7B X`09 ps.cast_mask `7C= 1 << ps.p_l_follow; X`09 break;`09`09/* inside parens: cast */ X`09 `7D X`09 last_code = decl; X`09 return (decl); X X`09case 5:`09`09/* if, while, for */ X`09 return (sp_paren); X X`09case 6:`09`09/* do, else */ X`09 return (sp_nparen); X X`09case 7: X`09 ps.sizeof_keyword = true; X`09default:`09`09/* all others are treated like any other X`09`09`09`09 * identifier */ X`09 return (ident); X `7D`09`09`09`09/* end of switch */ X `7D`09`09`09`09/* end of if (found_it) */ X if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) X `7B X register char *tp = buf_ptr; X while (tp < buf_end) X`09if (*tp++ == ')' && (*tp == ';' `7C`7C *tp == ',')) X`09 goto not_proc; X strncpy(ps.procname,token,sizeof ps.procname - 1); X ps.in_parameter_declaration = 1; X rparen_count = 1; X not_proc:; X `7D X /* X * The following hack attempts to guess whether or not the current X * token is in fact a declaration keyword -- one that has been X * typedefd X */ X if (((*buf_ptr == '*' && buf_ptr`5B1`5D != '=') `7C`7C isalpha(*buf_ptr) V `7C`7C *buf_ptr == '_') X`09&& !ps.p_l_follow X`09&& !ps.block_init X`09&& (ps.last_token == rparen `7C`7C ps.last_token == semicolon `7C`7C X`09 ps.last_token == decl `7C`7C X`09 ps.last_token == lbrace `7C`7C ps.last_token == rbrace)) X `7B X ps.its_a_keyword = true; X ps.last_u_d = true; X last_code = decl; X return decl; X `7D X if (last_code == decl)`09/* if this is a declared variable, then X`09`09`09`09 * following sign is unary */ X ps.last_u_d = true;`09/* will make "int a -1" work */ X last_code = ident; X return (ident);`09`09/* the ident is not in the list */ X `7D`09`09`09`09/* end of procesing for alpanum character */ X X /* Scan a non-alphanumeric token */ X X *e_token++ = *buf_ptr;`09/* if it is only a one-character token, it is X`09`09`09`09 * moved here */ X *e_token = '\0'; X if (++buf_ptr >= buf_end) X fill_buffer(); X X switch (*token) X `7B X case '\n': X unary_delim = ps.last_u_d; X ps.last_nl = true;`09/* remember that we just had a newline */ X code = (had_eof ? 0 : newline); X X /* X * if data has been exausted, the newline is a dummy, and we should X * return code to stop X */ X break; X X case '\'':`09`09`09/* start of quoted character */ X case '"':`09`09`09/* start of string */ X qchar = *token; X if (troff) X `7B X`09e_token`5B-1`5D = '`60'; X`09if (qchar == '"') X`09 *e_token++ = '`60'; X`09e_token = chfont(&bodyf,&stringf,e_token); X `7D X do X `7B`09`09`09`09/* copy the string */ X`09while (1) X`09`7B`09`09`09/* move one character or `5B/`5D */ X`09 if (*buf_ptr == '\n') X`09 `7B X`09 printf("%d: Unterminated literal\n",line_no); X`09 goto stop_lit; X`09 `7D X`09 CHECK_SIZE_TOKEN;`09/* Only have to do this once in this loop, X`09`09`09`09 * since CHECK_SIZE guarantees that there X`09`09`09`09 * are at least 5 entries left */ X`09 *e_token = *buf_ptr++; X`09 if (buf_ptr >= buf_end) X`09 fill_buffer(); X`09 if (*e_token == BACKSLASH) X`09 `7B`09`09`09/* if escape, copy extra char */ X`09 if (*buf_ptr == '\n')`09/* check for escaped newline */ X`09 ++line_no; X`09 if (troff) X`09 `7B X`09 *++e_token = BACKSLASH; X`09 if (*buf_ptr == BACKSLASH) X`09`09*++e_token = BACKSLASH; X`09 `7D X`09 *++e_token = *buf_ptr++; X`09 ++e_token;`09`09/* we must increment this again because we X`09`09`09`09 * copied two chars */ X`09 if (buf_ptr >= buf_end) X`09 fill_buffer(); X`09 `7D X`09 else X`09 break;`09`09/* we copied one character */ X`09`7D`09`09`09/* end of while (1) */ X `7D while (*e_token++ != qchar); X if (troff) X `7B X`09e_token = chfont(&stringf,&bodyf,e_token - 1); X`09if (qchar == '"') X`09 *e_token++ = '\''; X `7D X stop_lit: X code = ident; X break; X X case ('('): X case ('`5B'): X unary_delim = true; X code = lparen; X break; X X case (')'): X case ('`5D'): X code = rparen; X break; X X case '#': X unary_delim = ps.last_u_d; X code = preesc; X break; X X case '?': X unary_delim = true; X code = question; X break; X X case (':'): X if (cplus && *buf_ptr == token`5B0`5D) `7Bbuf_ptr++; goto default_char V;`7D X code = colon; X unary_delim = true; X break; X X case (';'): X unary_delim = true; X code = semicolon; X break; X X case ('`7B'): X unary_delim = true; X X /* X * if (ps.in_or_st) ps.block_init = 1; X */ X /* ?`09code = ps.block_init ? lparen : lbrace; */ X code = lbrace; X break; X X case ('`7D'): X unary_delim = true; X /* ?`09code = ps.block_init ? rparen : rbrace; */ X code = rbrace; X break; X X case 014:`09`09`09/* a form feed */ X unary_delim = ps.last_u_d; X ps.last_nl = true;`09/* remember this so we can set 'ps.col_1' X`09`09`09`09 * right */ X code = form_feed; X break; X X case (','): X unary_delim = true; X code = comma; X break; X X case '.': X unary_delim = false; X code = period; X break; X X case '-': X case '+':`09`09`09/* check for -, +, --, ++ */ X code = (ps.last_u_d ? unary_op : binary_op); X unary_delim = true; X X if (*buf_ptr == token`5B0`5D) X `7B X`09/* check for doubled character */ X`09*e_token++ = *buf_ptr++; X`09/* buffer overflow will be checked at end of loop */ X`09if (last_code == ident `7C`7C last_code == rparen) X`09`7B X`09 code = (ps.last_u_d ? unary_op : postop); X`09 /* check for following ++ or -- */ X`09 unary_delim = false; X`09`7D X `7D X else if (*buf_ptr == '=') X`09/* check for operator += */ X`09*e_token++ = *buf_ptr++; X else if (*buf_ptr == '>') X `7B X`09/* check for operator -> */ X`09*e_token++ = *buf_ptr++; X`09if (!pointer_as_binop) X`09`7B X`09 unary_delim = false; X`09 code = unary_op; X`09 ps.want_blank = false; X`09`7D X `7D X break;`09`09`09/* buffer overflow will be checked at end of X`09`09`09`09 * switch */ X X case '=': X if (ps.in_or_st) X`09ps.block_init = 1; X#ifdef undef X if (chartype`5B*buf_ptr`5D == opchar) X `7B`09`09`09`09/* we have two char assignment */ X`09e_token`5B-1`5D = *buf_ptr++; X`09if ((e_token`5B-1`5D == '<' `7C`7C e_token`5B-1`5D == '>') && e_token`5B- V1`5D == *buf_ptr) X`09 *e_token++ = *buf_ptr++; X`09*e_token++ = '=';`09/* Flip =+ to += */ X`09*e_token = 0; X `7D X#else X if (*buf_ptr == '=') X `7B`09`09`09`09/* == */ X`09*e_token++ = '=';`09/* Flip =+ to += */ X`09buf_ptr++; X`09*e_token = 0; X `7D X#endif X code = binary_op; X unary_delim = true; X break; X /* can drop thru!!! */ X X case '>': X case '<': X case '!':`09`09`09/* ops like <, <<, <=, !=, etc */ X if (*buf_ptr == '>' `7C`7C *buf_ptr == '<' `7C`7C *buf_ptr == '=') X `7B X`09*e_token++ = *buf_ptr; X`09if (++buf_ptr >= buf_end) X`09 fill_buffer(); X `7D X if (*buf_ptr == '=') X`09*e_token++ = *buf_ptr++; X code = (ps.last_u_d ? unary_op : binary_op); X unary_delim = true; X break; X X case '*': X if (ps.ind_level == 0 && ps.p_l_follow == 1 && *buf_ptr != ' ' X && *buf_ptr != ')') X `7B X`09*e_token++ = *buf_ptr++; X`09code = unary_op; X`09unary_delim = true; X`09break; X `7D X X default: X default_char: X if (token`5B0`5D == '/' && *buf_ptr == '*') X `7B X`09/* it is start of comment */ X`09*e_token++ = '*'; X X`09if (++buf_ptr >= buf_end) X`09 fill_buffer(); X X`09code = comment; X`09unary_delim = ps.last_u_d; X`09break; X `7D X while (*(e_token - 1) == *buf_ptr `7C`7C *buf_ptr == '=') X `7B X`09/* X`09 * handle `7C`7C, &&, etc, and also things as in int *****i X`09 */ X`09*e_token++ = *buf_ptr; X`09if (++buf_ptr >= buf_end) X`09 fill_buffer(); X `7D X code = (ps.last_u_d ? unary_op : binary_op); X unary_delim = true; X X X `7D`09`09`09`09/* end of switch */ X if (code != newline) X `7B X l_struct = false; X last_code = code; X `7D X if (buf_ptr >= buf_end)`09/* check for input buffer empty */ X fill_buffer(); X ps.last_u_d = unary_delim; X *e_token = '\0';`09`09/* null terminate the token */ X return (code); X`7D X X/* X * Add the given keyword to the keyword table, using val as the keyword type X */ Xaddkey(key,val) X char *key; X`7B X register struct templ *p = specials; X while (p->rwd) X if (p->rwd`5B0`5D == key`5B0`5D && strcmp(p->rwd,key) == 0) X return; X else X p++; X if (p >= specials + sizeof specials / sizeof specials`5B0`5D) X return;`09`09`09/* For now, table overflows are silently X`09`09`09`09 * ignored */ X p->rwd = key; X p->rwcode = val; X p`5B1`5D.rwd = 0; X p`5B1`5D.rwcode = 0; X return; X`7D $ CALL UNPACK LEXI.C;20 2015745772 $ create 'f' X/* X * Copyright (c) 1985 Sun Microsystems, Inc. X * Copyright (c) 1980 The Regents of the University of California. X * Copyright (c) 1976 Board of Trustees of the University of Illinois. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: `60`60This product includes software X * developed by the University of California, Berkeley and its contributors' V' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED `60`60AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xstatic char sccsid`5B`5D = "@(#)parse.c`095.11 (Berkeley) 6/1/90"; X#endif /* not lint */ X X#include "indent_globs.h" X#include "indent_codes.h" X Xparse(tk) X int tk;`09`09/* the code for the construct scanned */ X`7B X int i; X X#ifdef debug X printf("%2d - %s\n", tk, token); X#endif X X while (ps.p_stack`5Bps.tos`5D == ifhead && tk != elselit) `7B X`09/* true if we have an if without an else */ X`09ps.p_stack`5Bps.tos`5D = stmt;`09/* apply the if(..) stmt ::= stmt X`09`09`09`09`09 * reduction */ X`09reduce();`09`09/* see if this allows any reduction */ X `7D X X X switch (tk) `7B`09`09/* go on and figure out what to do with the X`09`09`09`09 * input */ X X case decl:`09`09`09/* scanned a declaration word */ X`09ps.search_brace = btype_2; X`09/* indicate that following brace should be on same line */ X`09if (ps.p_stack`5Bps.tos`5D != decl) `7B`09/* only put one declaration X`09`09`09`09`09`09 * onto stack */ X`09 break_comma = true;`09/* while in declaration, newline should be X`09`09`09`09 * forced after comma */ X`09 ps.p_stack`5B++ps.tos`5D = decl; X`09 ps.il`5Bps.tos`5D = ps.i_l_follow; X X`09 if (ps.ljust_decl) `7B/* only do if we want left justified X`09`09`09`09 * declarations */ X`09`09ps.ind_level = 0; X`09`09for (i = ps.tos - 1; i > 0; --i) X`09`09 if (ps.p_stack`5Bi`5D == decl) X`09`09`09++ps.ind_level;`09/* indentation is number of X`09`09`09`09`09 * declaration levels deep we are */ X`09`09ps.i_l_follow = ps.ind_level; X`09 `7D X`09`7D X`09break; X X case ifstmt:`09`09/* scanned if (...) */ X`09if (ps.p_stack`5Bps.tos`5D == elsehead && ps.else_if)`09/* "else if ..." V */ X`09 ps.i_l_follow = ps.il`5Bps.tos`5D; X case dolit:`09`09/* 'do' */ X case forstmt:`09`09/* for (...) */ X`09ps.p_stack`5B++ps.tos`5D = tk; X`09ps.il`5Bps.tos`5D = ps.ind_level = ps.i_l_follow; X`09++ps.i_l_follow;`09/* subsequent statements should be indented 1 */ X`09ps.search_brace = btype_2; X`09break; X X case lbrace:`09`09/* scanned `7B */ X`09break_comma = false;`09/* don't break comma in an initial list */ X`09if (ps.p_stack`5Bps.tos`5D == stmt `7C`7C ps.p_stack`5Bps.tos`5D == decl X`09`09`7C`7C ps.p_stack`5Bps.tos`5D == stmtl) X`09 ++ps.i_l_follow;`09/* it is a random, isolated stmt group or a X`09`09`09`09 * declaration */ X`09else `7B X`09 if (s_code == e_code && !ps.block_init) `7B X`09`09/* X`09`09 * only do this if there is nothing on the line X`09`09 */ X`09`09--ps.ind_level; X`09`09/* X`09`09 * it is a group as part of a while, for, etc. X`09`09 */ X`09`09if (ps.p_stack`5Bps.tos`5D == swstmt && ps.case_indent >= 1) X`09`09 --ps.ind_level; X`09`09/* X`09`09 * for a switch, brace should be two levels out from the code X`09`09 */ X`09 `7D X`09`7D X X`09ps.p_stack`5B++ps.tos`5D = lbrace; X`09ps.il`5Bps.tos`5D = ps.ind_level; X`09ps.p_stack`5B++ps.tos`5D = stmt; X`09/* allow null stmt between braces */ X`09ps.il`5Bps.tos`5D = ps.i_l_follow; X`09break; X X case whilestmt:`09`09/* scanned while (...) */ X`09if (ps.p_stack`5Bps.tos`5D == dohead) `7B X`09 /* it is matched with do stmt */ X`09 ps.ind_level = ps.i_l_follow = ps.il`5Bps.tos`5D; X`09 ps.p_stack`5B++ps.tos`5D = whilestmt; X`09 ps.il`5Bps.tos`5D = ps.ind_level = ps.i_l_follow; X`09`7D X`09else `7B`09`09`09/* it is a while loop */ X`09 ps.p_stack`5B++ps.tos`5D = whilestmt; X`09 ps.il`5Bps.tos`5D = ps.i_l_follow; X`09 ++ps.i_l_follow; X`09 ps.search_brace = btype_2; X`09`7D X X`09break; X X case elselit:`09`09/* scanned an else */ X X`09if (ps.p_stack`5Bps.tos`5D != ifhead) X`09 diag(1, "Unmatched 'else'"); X`09else `7B X`09 ps.ind_level = ps.il`5Bps.tos`5D;`09/* indentation for else should X`09`09`09`09`09`09 * be same as for if */ X`09 ps.i_l_follow = ps.ind_level + 1;`09/* everything following should X`09`09`09`09`09`09 * be in 1 level */ X`09 ps.p_stack`5Bps.tos`5D = elsehead; X`09 /* remember if with else */ X`09 ps.search_brace = btype_2 `7C ps.else_if; X`09`7D X`09break; X X case rbrace:`09`09/* scanned a `7D */ X`09/* stack should have or */ X`09if (ps.p_stack`5Bps.tos - 1`5D == lbrace) `7B X`09 ps.i_l_follow = ps.il`5B--ps.tos`5D; X`09 if (!ps.block_init) ps.ind_level = ps.i_l_follow; X`09 ps.p_stack`5Bps.tos`5D = stmt; X`09`7D X`09else X`09 diag(1, "Stmt nesting error."); X`09break; X X case swstmt:`09`09/* had switch (...) */ X`09ps.p_stack`5B++ps.tos`5D = swstmt; X`09ps.cstk`5Bps.tos`5D = case_ind; X`09/* save current case indent level */ X`09ps.il`5Bps.tos`5D = ps.i_l_follow; X`09case_ind = ps.i_l_follow + ps.case_indent;`09/* cases should be one X`09`09`09`09`09`09`09 * level down from X`09`09`09`09`09`09`09 * switch */ X`09ps.i_l_follow += ps.case_indent + 1;`09/* statements should be two X`09`09`09`09`09`09 * levels in */ X`09ps.search_brace = btype_2; X`09break; X X case semicolon:`09`09/* this indicates a simple stmt */ X`09break_comma = false;`09/* turn off flag to break after commas in a X`09`09`09`09 * declaration */ X`09ps.p_stack`5B++ps.tos`5D = stmt; X`09ps.il`5Bps.tos`5D = ps.ind_level; X`09break; X X default:`09`09`09/* this is an error */ X`09diag(1, "Unknown code to parser"); X`09return; X X X `7D`09`09`09`09/* end of switch */ X X reduce();`09`09`09/* see if any reduction can be done */ X X#ifdef debug X for (i = 1; i <= ps.tos; ++i) X`09printf("(%d %d)", ps.p_stack`5Bi`5D, ps.il`5Bi`5D); X printf("\n"); X#endif X X return; X`7D X X/* X * NAME: reduce X *`20 X * FUNCTION: Implements the reduce part of the parsing algorithm X *`20 X * ALGORITHM: The following reductions are done. Reductions are repeated X *`09until no more are possible. X *`20 X * Old TOS`09`09New TOS X * `09 X * `09 X * do `09`09"dostmt" X * if `09`09"ifstmt" X * switch `09 X * decl `09`09 X * "ifelse" `09 X * for `09`09 X * while `09`09 X * "dostmt" while`09 X *`20 X * On each reduction, ps.i_l_follow (the indentation for the following line) X * is set to the indentation level associated with the old TOS. X *`20 X * PARAMETERS: None X *`20 X * RETURNS: Nothing X *`20 X * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos = X *`20 X * CALLS: None X *`20 X * CALLED BY: parse X *`20 X * HISTORY: initial coding `09November 1976`09D A Willcox of CAC X *`20 X */ X/*----------------------------------------------*\ X`7C REDUCTION PHASE`09`09`09`09 `7C X\*----------------------------------------------*/ Xreduce() X`7B X X register int i; X X for (;;) `7B`09`09`09/* keep looping until there is nothing left to X`09`09`09`09 * reduce */ X X`09switch (ps.p_stack`5Bps.tos`5D) `7B X X`09case stmt: X`09 switch (ps.p_stack`5Bps.tos - 1`5D) `7B X X`09 case stmt: X`09 case stmtl: X`09`09/* stmtl stmt or stmt stmt */ X`09`09ps.p_stack`5B--ps.tos`5D = stmtl; X`09`09break; X X`09 case dolit:`09/* */ X`09`09ps.p_stack`5B--ps.tos`5D = dohead; X`09`09ps.i_l_follow = ps.il`5Bps.tos`5D; X`09`09break; X X`09 case ifstmt: X`09`09/* */ X`09`09ps.p_stack`5B--ps.tos`5D = ifhead; X`09`09for (i = ps.tos - 1; X`09`09`09( X`09`09`09 ps.p_stack`5Bi`5D != stmt X`09`09`09 && X`09`09`09 ps.p_stack`5Bi`5D != stmtl X`09`09`09 && X`09`09`09 ps.p_stack`5Bi`5D != lbrace +-+-+-+-+-+-+-+- END OF PART 3 +-+-+-+-+-+-+-+-